diff --git a/drivers/comparator/CMakeLists.txt b/drivers/comparator/CMakeLists.txt index 43e98ce2a7000..b69cd8b705278 100644 --- a/drivers/comparator/CMakeLists.txt +++ b/drivers/comparator/CMakeLists.txt @@ -15,3 +15,4 @@ zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_COMP comparator_nrf_comp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_NRF_LPCOMP comparator_nrf_lpcomp.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_SHELL comparator_shell.c) zephyr_library_sources_ifdef(CONFIG_COMPARATOR_RENESAS_RA comparator_renesas_ra.c) +zephyr_library_sources_ifdef(CONFIG_COMPARATOR_STM32_COMP comparator_stm32_comp.c) diff --git a/drivers/comparator/Kconfig b/drivers/comparator/Kconfig index 8aec586bdc3f2..34815f9f3fe81 100644 --- a/drivers/comparator/Kconfig +++ b/drivers/comparator/Kconfig @@ -27,5 +27,6 @@ rsource "Kconfig.nrf_comp" rsource "Kconfig.nrf_lpcomp" rsource "Kconfig.shell" rsource "Kconfig.renesas_ra" +rsource "Kconfig.stm32_comp" endif # COMPARATOR diff --git a/drivers/comparator/Kconfig.stm32_comp b/drivers/comparator/Kconfig.stm32_comp new file mode 100644 index 0000000000000..8f6b6c2eadaa8 --- /dev/null +++ b/drivers/comparator/Kconfig.stm32_comp @@ -0,0 +1,9 @@ +# Copyright (c) 2025 Alexander Kozhinov +# SPDX-License-Identifier: Apache-2.0 + +config COMPARATOR_STM32_COMP + bool "ST STM32 comparator driver" + default y + depends on DT_HAS_ST_STM32_COMP_ENABLED + select PINCTRL + select EXTI_STM32 diff --git a/drivers/comparator/comparator_stm32_comp.c b/drivers/comparator/comparator_stm32_comp.c new file mode 100644 index 0000000000000..f8536655fb6e4 --- /dev/null +++ b/drivers/comparator/comparator_stm32_comp.c @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2025 Alexander Kozhinov + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +LOG_MODULE_REGISTER(stm32_comp, CONFIG_COMPARATOR_LOG_LEVEL); + +#define DT_DRV_COMPAT st_stm32_comp + +#define LL_COMP_INPUT_PLUS_IN0 LL_COMP_INPUT_PLUS_IO1 +#define LL_COMP_INPUT_PLUS_IN1 LL_COMP_INPUT_PLUS_IO2 + +#define LL_COMP_INPUT_MINUS_IN0 LL_COMP_INPUT_MINUS_IO1 +#define LL_COMP_INPUT_MINUS_IN1 LL_COMP_INPUT_MINUS_IO2 + +#define STM32_COMP_DT_INST_P_IN(inst) \ + CONCAT(LL_COMP_INPUT_PLUS_, DT_INST_STRING_TOKEN(inst, positive_input)) + +#define STM32_COMP_DT_INST_N_IN(inst) \ + CONCAT(LL_COMP_INPUT_MINUS_, DT_INST_STRING_TOKEN(inst, negative_input)) + +#define STM32_COMP_DT_INST_HYST_MODE(inst) \ + CONCAT(LL_COMP_HYSTERESIS_, DT_INST_STRING_TOKEN(inst, hysteresis)) + +#define STM32_COMP_DT_INST_INV_OUT(inst) \ + CONCAT(LL_COMP_OUTPUTPOL_, DT_INST_STRING_TOKEN(inst, invert_output)) + +#define STM32_COMP_DT_INST_BLANK_SEL(inst) \ + CONCAT(LL_COMP_BLANKINGSRC_, DT_INST_STRING_TOKEN(inst, st_blank_sel)) + +#define STM32_COMP_DT_INST_LOCK(inst) DT_INST_PROP(inst, st_lock_enable) + +#define STM32_COMP_DT_MILLER_EFFECT_HOLD_DISABLE(inst) \ + DT_INST_PROP_OR(inst, st_miller_effect_hold_disable, false) + +#define STM32_COMP_DT_EXTI_LINE_NUMBER(inst) DT_INST_PROP(inst, st_exti_line) + +/* Value 0 always relates to the default value of COMP PWRMODE bit field */ +#define STM32_COMP_DT_POWER_MODE(inst) \ + COND_CODE_1(DT_INST_NODE_HAS_PROP(inst, st_power_mode), \ + (CONCAT(LL_COMP_POWERMODE_, \ + DT_INST_STRING_TOKEN(inst, st_power_mode))), \ + (0)) + +struct stm32_comp_config { + COMP_TypeDef *comp; + struct stm32_pclken *pclken; + const struct pinctrl_dev_config *pincfg; + void (*irq_init)(void); + uint32_t irq_nr; + uint32_t exti_line_number; + bool lock_enable; + bool miller_effect_hold_disable; + uint32_t power_mode; + uint32_t input_plus; + uint32_t input_minus; + uint32_t hysteresis; + uint32_t invert_output; + uint32_t blank_sel; +}; + +struct stm32_comp_data { + comparator_callback_t callback; + void *user_data; +}; + +static bool stm32_comp_is_resumed(const struct device *dev) +{ +#ifdef CONFIG_PM_DEVICE + enum pm_device_state state; + + (void)pm_device_state_get(dev, &state); + return state == PM_DEVICE_STATE_ACTIVE; +#else + return true; +#endif /* CONFIG_PM_DEVICE */ +} + +static int stm32_comp_get_output(const struct device *dev) +{ + const struct stm32_comp_config *cfg = dev->config; + COMP_TypeDef *comp = cfg->comp; + + return LL_COMP_ReadOutputLevel(comp); +} + +static int stm32_comp_set_trigger(const struct device *dev, enum comparator_trigger trigger) +{ + const struct stm32_comp_config *cfg = dev->config; + struct stm32_comp_data *data = dev->data; + stm32_exti_trigger_type exti_trigger = 0U; + COMP_TypeDef *comp = cfg->comp; + int ret = 0; + + switch (trigger) { + case COMPARATOR_TRIGGER_NONE: + exti_trigger = STM32_EXTI_TRIG_NONE; + break; + case COMPARATOR_TRIGGER_RISING_EDGE: + exti_trigger = STM32_EXTI_TRIG_RISING; + break; + case COMPARATOR_TRIGGER_FALLING_EDGE: + exti_trigger = STM32_EXTI_TRIG_FALLING; + break; + case COMPARATOR_TRIGGER_BOTH_EDGES: + exti_trigger = STM32_EXTI_TRIG_BOTH; + break; + default: + LOG_ERR("%s: Unsupported trigger mode %d", dev->name, trigger); + return -ENOTSUP; + } + + irq_disable(cfg->irq_nr); + LL_COMP_Disable(comp); + + ret = stm32_exti_enable(cfg->exti_line_number, exti_trigger, + STM32_EXTI_MODE_IT); + if (ret != 0) { + LOG_ERR("%s: EXTI init failed (%d)", dev->name, ret); + return ret; + } + + if (stm32_comp_is_resumed(dev)) { + LL_COMP_Enable(comp); + } + + if (data->callback != NULL) { + irq_enable(cfg->irq_nr); + } + + return ret; +} + +static int stm32_comp_trigger_is_pending(const struct device *dev) +{ + const struct stm32_comp_config *cfg = dev->config; + + if (stm32_exti_is_pending(cfg->exti_line_number)) { + stm32_exti_clear_pending(cfg->exti_line_number); + return 1; + } + return 0; +} + +static int stm32_comp_set_trigger_callback(const struct device *dev, comparator_callback_t callback, + void *user_data) +{ + const struct stm32_comp_config *cfg = dev->config; + struct stm32_comp_data *data = dev->data; + + irq_disable(cfg->irq_nr); + + data->callback = callback; + data->user_data = user_data; + + irq_enable(cfg->irq_nr); + + if (data->callback != NULL && stm32_comp_trigger_is_pending(dev)) { + callback(dev, user_data); + } + + return 0; +} + +static int stm32_comp_pm_callback(const struct device *dev, enum pm_device_action action) +{ + const struct stm32_comp_config *cfg = dev->config; + COMP_TypeDef *comp = cfg->comp; + + if (LL_COMP_IsLocked(comp)) { + LOG_ERR("%s is locked", dev->name); + return -EACCES; + } + + if (action == PM_DEVICE_ACTION_RESUME) { + LL_COMP_Enable(comp); + if (cfg->lock_enable) { + LL_COMP_Lock(comp); + } + } + + if (IS_ENABLED(CONFIG_PM_DEVICE) && action == PM_DEVICE_ACTION_SUSPEND) { + LL_COMP_Disable(comp); + } + + return 0; +} + +static void stm32_comp_irq_handler(const struct device *dev) +{ + const struct stm32_comp_config *cfg = dev->config; + struct stm32_comp_data *data = dev->data; + + if (stm32_exti_is_pending(cfg->exti_line_number)) { + stm32_exti_clear_pending(cfg->exti_line_number); + } + + if (data->callback == NULL) { + return; + } + + data->callback(dev, data->user_data); +} + +static int stm32_comp_init(const struct device *dev) +{ + const struct device *const clk = DEVICE_DT_GET(STM32_CLOCK_CONTROL_NODE); + const struct stm32_comp_config *cfg = dev->config; + COMP_TypeDef *comp = cfg->comp; + int ret = 0; + + if (!device_is_ready(clk)) { + LOG_ERR("%s clock control device not ready", dev->name); + return -ENODEV; + } + + /* Enable COMP bus clock */ + ret = clock_control_on(clk, &cfg->pclken[0]); + if (ret != 0) { + LOG_ERR("%s clock op failed (%d)", dev->name, ret); + return ret; + } + + /* Enable COMP clock source */ +#ifndef CONFIG_SOC_SERIES_STM32G4X + /* stm32g4 clock configuration is not necessary, + * since it is enough to turn APB2 clock on (see: RM0440 Rev 8 767/2138) + */ + ret = clock_control_configure(clk, &cfg->pclken[1], NULL); + if (ret != 0) { + LOG_ERR("%s clock configure failed (%d)", dev->name, ret); + return ret; + } +#endif /* !CONFIG_SOC_SERIES_STM32G4X */ + + /* Configure COMP inputs as specified in Device Tree, if any */ + ret = pinctrl_apply_state(cfg->pincfg, PINCTRL_STATE_DEFAULT); + if (ret < 0 && ret != -ENOENT) { + /* + * If the COMP is used only with internal channels, then no pinctrl is + * provided in Device Tree, and pinctrl_apply_state returns -ENOENT, + * but this should not be treated as an error. + */ + LOG_ERR("%s pinctrl setup failed (%d)", dev->name, ret); + return ret; + } + + if (LL_COMP_IsLocked(comp)) { + /* COMP instance shall not be locked */ + LOG_ERR("%s COMP instance is locked", dev->name); + return -EACCES; + } + +#ifndef CONFIG_SOC_SERIES_STM32G4X + LL_COMP_SetPowerMode(comp, cfg->power_mode); +#endif /* !CONFIG_SOC_SERIES_STM32G4X */ + + LL_COMP_SetInputMinus(comp, cfg->input_minus); + LL_COMP_SetInputPlus(comp, cfg->input_plus); + LL_COMP_SetInputHysteresis(comp, cfg->hysteresis); + LL_COMP_SetOutputPolarity(comp, cfg->invert_output); + LL_COMP_SetOutputBlankingSource(comp, cfg->blank_sel); + +#if defined(CONFIG_SOC_SERIES_STM32G4X) + /* Undocumented bit, refer to st,miller-effect-hold-disable DT binding */ + WRITE_BIT(comp->CSR, 1, cfg->miller_effect_hold_disable ? 0 : 1); +#endif /* CONFIG_SOC_SERIES_STM32G4X */ + + cfg->irq_init(); + + return pm_device_driver_init(dev, stm32_comp_pm_callback); +} + +static DEVICE_API(comparator, stm32_comp_comp_api) = { + .get_output = stm32_comp_get_output, + .set_trigger = stm32_comp_set_trigger, + .set_trigger_callback = stm32_comp_set_trigger_callback, + .trigger_is_pending = stm32_comp_trigger_is_pending, +}; + +#define STM32_COMP_IRQ_HANDLER_SYM(inst) stm32_comp_irq_init_##inst + +#define STM32_COMP_IRQ_HANDLER_DEFINE(inst) \ + \ + static void STM32_COMP_IRQ_HANDLER_SYM(inst)(void) \ + { \ + IRQ_CONNECT(DT_INST_IRQN(inst), DT_INST_IRQ(inst, priority), \ + stm32_comp_irq_handler, DEVICE_DT_INST_GET(inst), 0); \ + irq_enable(DT_INST_IRQN(inst)); \ + } + +#define STM32_COMP_DEVICE(inst) \ + \ + static struct stm32_pclken comp_##inst##_clk[] = STM32_DT_INST_CLOCKS(inst); \ + \ + PINCTRL_DT_INST_DEFINE(inst); \ + \ + static struct stm32_comp_data stm32_comp_data_##inst; \ + \ + STM32_COMP_IRQ_HANDLER_DEFINE(inst) \ + static const struct stm32_comp_config stm32_comp_config_##inst = { \ + .comp = (COMP_TypeDef *)DT_INST_REG_ADDR(inst), \ + .pclken = comp_##inst##_clk, \ + .pincfg = PINCTRL_DT_INST_DEV_CONFIG_GET(inst), \ + .irq_init = STM32_COMP_IRQ_HANDLER_SYM(inst), \ + .irq_nr = DT_INST_IRQN(inst), \ + .exti_line_number = STM32_COMP_DT_EXTI_LINE_NUMBER(inst), \ + .lock_enable = STM32_COMP_DT_INST_LOCK(inst), \ + .miller_effect_hold_disable = \ + STM32_COMP_DT_MILLER_EFFECT_HOLD_DISABLE(inst), \ + .power_mode = STM32_COMP_DT_POWER_MODE(inst), \ + .input_plus = STM32_COMP_DT_INST_P_IN(inst), \ + .input_minus = STM32_COMP_DT_INST_N_IN(inst), \ + .hysteresis = STM32_COMP_DT_INST_HYST_MODE(inst), \ + .invert_output = STM32_COMP_DT_INST_INV_OUT(inst), \ + .blank_sel = STM32_COMP_DT_INST_BLANK_SEL(inst) \ + }; \ + \ + PM_DEVICE_DT_INST_DEFINE(inst, stm32_comp_pm_callback); \ + \ + DEVICE_DT_INST_DEFINE(inst, \ + stm32_comp_init, \ + PM_DEVICE_DT_INST_GET(inst), \ + &stm32_comp_data_##inst, \ + &stm32_comp_config_##inst, \ + POST_KERNEL, \ + CONFIG_COMPARATOR_INIT_PRIORITY, \ + &stm32_comp_comp_api \ + ); + +DT_INST_FOREACH_STATUS_OKAY(STM32_COMP_DEVICE) diff --git a/dts/arm/st/g4/stm32g4.dtsi b/dts/arm/st/g4/stm32g4.dtsi index 504e93e5c0c02..be23541a9f7f4 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 Alexander Kozhinov * Copyright (c) 2024 STMicroelectronics * Copyright (c) 2025 Mario Paja * @@ -698,6 +699,24 @@ STM32_DMA_16BITS)>; status = "disabled"; }; + + comp1: comparator@40010200 { + compatible = "st,stm32g4-comp", "st,stm32-comp"; + reg = <0x40010200 0x4>; + interrupts = <64 0>; + st,exti-line = <21>; + clocks = <&rcc STM32_CLOCK(APB2, 0)>; + status = "disabled"; + }; + + comp2: comparator@40010204 { + compatible = "st,stm32g4-comp", "st,stm32-comp"; + reg = <0x40010204 0x4>; + interrupts = <64 0>; + st,exti-line = <22>; + clocks = <&rcc STM32_CLOCK(APB2, 0)>; + status = "disabled"; + }; }; die_temp: dietemp { diff --git a/dts/arm/st/h7/stm32h7.dtsi b/dts/arm/st/h7/stm32h7.dtsi index 05a4b492e677d..92dfc6cf0c695 100644 --- a/dts/arm/st/h7/stm32h7.dtsi +++ b/dts/arm/st/h7/stm32h7.dtsi @@ -1138,6 +1138,24 @@ STM32_DMA_16BITS) 0>; status = "disabled"; }; + + comp1_ch1: comparator@5800380c { + compatible = "st,stm32h7-comp", "st,stm32-comp"; + reg = <0x5800380c 0x200>; + interrupts = <137 0>; + st,exti-line = <20>; + clocks = <&rcc STM32_CLOCK(APB4, 14)>; + status = "disabled"; + }; + + comp1_ch2: comparator@58003810 { + compatible = "st,stm32h7-comp", "st,stm32-comp"; + reg = <0x58003810 0x200>; + interrupts = <137 0>; + st,exti-line = <20>; + clocks = <&rcc STM32_CLOCK(APB4, 14)>; + status = "disabled"; + }; }; die_temp: dietemp { diff --git a/dts/bindings/comparator/st,stm32-comp.yaml b/dts/bindings/comparator/st,stm32-comp.yaml new file mode 100644 index 0000000000000..680dfdb41e7f9 --- /dev/null +++ b/dts/bindings/comparator/st,stm32-comp.yaml @@ -0,0 +1,121 @@ +# Copyright (c) 2025 Alexander Kozhinov +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32 Comparator + + The following example displays the minimum node layout: + + comp1: comparator@40010200 { + reg = <0x40010200 0x4>; + interrupts = <64 0>; + clocks = <&rcc STM32_CLOCK(APB2, 0)>; + st,exti-line = <21>; + positive-input = "IN0"; + negative-input = "VREFINT"; + status = "okay"; + }; + + NOTE: The shown example is for stm32g474re + + Enabling the comparator node requires setting the minimum default + configuration of the comparator. This includes selecting the + positive and negative inputs, and routing them using pinctrl: + + &comp1 { + pinctrl-0 = <&comp1_inp_pa1 &comp1_out_pa6>; + pinctrl-names = "default"; + + positive-input = "IN0"; + negative-input = "VREFINT"; + status = "okay"; + }; + + NOTE: Pins used above are an example for stm32g474re + +compatible: "st,stm32-comp" + +include: + - base.yaml + - pinctrl-device.yaml + +properties: + reg: + required: true + interrupts: + required: true + clocks: + required: true + + invert-output: + type: string + description: | + Output polarity selection. + enum: + - NONINVERTED + - INVERTED + default: NONINVERTED + + st,exti-line: + required: true + type: int + description: | + EXTI interrupt line number connected to the comparator (COMPx) event. + + st,lock-enable: + type: boolean + description: | + The comparator configuration can be locked to prevent any + modification until the next system reset. + Once the lock bit is set, it can be cleared only by a system reset. + This feature allows to protect the comparator configuration against + unintentional modification. + + positive-input: + required: true + type: string + description: | + Selects positive input pin provided by the pinmux controller. + IN0 corresponds to the first pinmux option, IN1 to the second one. + enum: + - IN0 + - IN1 + + negative-input: + required: true + type: string + description: | + Selects negative input. May be a package pin (IN0 / IN1) via pinctrl + or an internal signal (e.g. VREFINT, DAC). + In case of package pin assignment IN0 will correspond to first pinmux pin + option and IN1 to the second one. + enum: + - 1_4VREFINT + - 1_2VREFINT + - 3_4VREFINT + - VREFINT + - IN0 + - IN1 + + hysteresis: + type: string + description: | + Selects the hysteresis voltage level. + Hysteresis adds a voltage offset to the comparator threshold to prevent + unwanted output toggling when the input voltage is noisy or slowly + varying around the comparator threshold. + enum: + - NONE + - LOW + - MEDIUM + - HIGH + default: NONE + + st,blank-sel: + type: string + description: | + Blanking source to mask short spikes at PWM period start. + Ref (example): STM32G4 RM0440 Rev 8, 24.3.6. + enum: + - NONE + default: NONE diff --git a/dts/bindings/comparator/st,stm32g4-comp.yaml b/dts/bindings/comparator/st,stm32g4-comp.yaml new file mode 100644 index 0000000000000..56b0024ae79ec --- /dev/null +++ b/dts/bindings/comparator/st,stm32g4-comp.yaml @@ -0,0 +1,105 @@ +# Copyright (c) 2025 Alexander Kozhinov +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32G4 series Comparator + +include: + - name: st,stm32-comp.yaml + property-blocklist: + - hysteresis + - st,blank-sel + - positive-input + - negative-input + +compatible: "st,stm32g4-comp" + +properties: + negative-input: + required: true + type: string + enum: + - 1_4VREFINT + - 1_2VREFINT + - 3_4VREFINT + - VREFINT + - DAC1_CH1 + - DAC1_CH2 + - DAC2_CH1 + - DAC3_CH1 + - DAC3_CH2 + - DAC4_CH1 + - DAC4_CH2 + - IN0 + - IN1 + + positive-input: + required: true + type: string + enum: + - IN0 + - IN1 + - DAC2_CH1 + + hysteresis: + type: string + enum: + - NONE + - LOW + - MEDIUM + - HIGH + - 10MV + - 20MV + - 30MV + - 40MV + - 50MV + - 60MV + - 70MV + default: NONE + + st,blank-sel: + type: string + enum: + - NONE + - TIM1_OC5_COMP1 + - TIM1_OC5_COMP2 + - TIM1_OC5_COMP3 + - TIM1_OC5_COMP4 + - TIM1_OC5_COMP5 + - TIM1_OC5_COMP6 + - TIM1_OC5_COMP7 + - TIM2_OC3_COMP1 + - TIM2_OC3_COMP2 + - TIM2_OC3_COMP5 + - TIM2_OC4_COMP3 + - TIM2_OC4_COMP6 + - TIM3_OC3_COMP1 + - TIM3_OC3_COMP2 + - TIM3_OC3_COMP3 + - TIM3_OC3_COMP5 + - TIM3_OC3_COMP7 + - TIM3_OC4_COMP4 + - TIM8_OC5_COMP1 + - TIM8_OC5_COMP2 + - TIM8_OC5_COMP3 + - TIM8_OC5_COMP4 + - TIM8_OC5_COMP5 + - TIM8_OC5_COMP6 + - TIM8_OC5_COMP7 + - TIM15_OC1_COMP4 + - TIM15_OC2_COMP6 + - TIM15_OC2_COMP7 + - TIM20_OC5 + - TIM15_OC1 + - TIM4_OC3 + default: NONE + + st,miller-effect-hold-disable: + type: boolean + description: | + Disables an undocumented compare feature (sets COMP_CxCSR bit #1 to 0) which + holds the comparator output during the duration of the Miller effect. + NOTE: This setting is supported only by stm32g4x series. + NOTE: It is recommended to enable the feature unless very fast events are tracked. + Please refer to following url for details: + https://community.st.com/t5/stm32-mcus-products/stm32g431-comparator-bug/m-p/679540#M250779 diff --git a/dts/bindings/comparator/st,stm32h7-comp.yaml b/dts/bindings/comparator/st,stm32h7-comp.yaml new file mode 100644 index 0000000000000..da871aa80db80 --- /dev/null +++ b/dts/bindings/comparator/st,stm32h7-comp.yaml @@ -0,0 +1,52 @@ +# Copyright (c) 2025 Alexander Kozhinov +# SPDX-License-Identifier: Apache-2.0 + +description: | + STM32H7 series Comparator + +include: + - name: st,stm32-comp.yaml + property-blocklist: + - st,blank-sel + - negative-input + +compatible: "st,stm32h7-comp" + +properties: + negative-input: + required: true + type: string + enum: + - 1_4VREFINT + - 1_2VREFINT + - 3_4VREFINT + - VREFINT + - DAC1_CH1 + - DAC1_CH2 + - IN0 + - IN1 + - TPSENS_DAC2CH1 + - VBAT_VDDAP + + st,power-mode: + type: string + description: | + Select comparator speed vs power mode. + Typical modes: fast (higher current), medium, low power, ultra-low power. + Availability varies by series. + enum: + - HIGHSPEED + - MEDIUMSPEED + - ULTRALOWPOWER + + st,blank-sel: + type: string + enum: + - NONE + - TIM1_OC5 + - TIM2_OC3 + - TIM3_OC3 + - TIM3_OC4 + - TIM8_OC5 + - TIM15_OC1 + default: NONE diff --git a/tests/drivers/comparator/gpio_loopback/boards/nucleo_g474re_stm32g474xx.overlay b/tests/drivers/comparator/gpio_loopback/boards/nucleo_g474re_stm32g474xx.overlay new file mode 100644 index 0000000000000..d60f6848c51ad --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/nucleo_g474re_stm32g474xx.overlay @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2025 Alexander Kozhinov + */ + + #include + +/ { + aliases { + test-comp = &comp1; + }; + + zephyr,user { + /* connected also to green led and will toggle it */ + test-gpios = <&gpioa 5 GPIO_ACTIVE_HIGH>; + }; +}; + +/* + * IMPORTANT: CN8.A1 (PA1) shall be connected to CN5.D13 (PA5) by a jumper wire + */ + +&comp1 { + status = "okay"; + pinctrl-0 = <&comp1_inp_pa1 &comp1_out_pa6>; + pinctrl-names = "default"; + positive-input = "IN0"; + negative-input = "1_4VREFINT"; + invert-output = "NONINVERTED"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/boards/nucleo_h745zi_q_stm32h745xx_m7.overlay b/tests/drivers/comparator/gpio_loopback/boards/nucleo_h745zi_q_stm32h745xx_m7.overlay new file mode 100644 index 0000000000000..ca1b5de57e485 --- /dev/null +++ b/tests/drivers/comparator/gpio_loopback/boards/nucleo_h745zi_q_stm32h745xx_m7.overlay @@ -0,0 +1,30 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright (c) 2025 Alexander Kozhinov + */ + + #include + +/* + * IMPORTANT: D33 (PB0) shall be connected to D27 (PB2) by a jumper wire + */ + +/ { + aliases { + test-comp = &comp1_ch1; + }; + + zephyr,user { + /* connected also to green led and will toggle it */ + test-gpios = <&gpiob 0 GPIO_ACTIVE_HIGH>; + }; +}; + +&comp1_ch1 { + status = "okay"; + pinctrl-0 = <&comp1_inp_pb2 &comp1_out_pe12>; + pinctrl-names = "default"; + positive-input = "IN1"; + negative-input = "1_4VREFINT"; + invert-output = "NONINVERTED"; +}; diff --git a/tests/drivers/comparator/gpio_loopback/testcase.yaml b/tests/drivers/comparator/gpio_loopback/testcase.yaml index dfebf3644756c..acec903991b18 100644 --- a/tests/drivers/comparator/gpio_loopback/testcase.yaml +++ b/tests/drivers/comparator/gpio_loopback/testcase.yaml @@ -37,3 +37,7 @@ tests: - nrf54l15dk/nrf54l15/cpuapp - nrf54lm20dk/nrf54lm20a/cpuapp - ophelia4ev/nrf54l15/cpuapp + drivers.comparator.gpio_loopback.stm32_comp: + platform_allow: + - nucleo_h745zi_q/stm32h745xx/m7 + - nucleo_g474re/stm32g474xx