From 71afed1a70d1b783d104d29878be3c44fae7cbcf Mon Sep 17 00:00:00 2001 From: iabdalkader Date: Wed, 13 Apr 2022 16:54:01 +0200 Subject: [PATCH] stm32/mphalport: Fix I/O glitches when switching GPIO mode to alt-func. To avoid any I/O glitches in mp_hal_pin_config, make sure a valid alternate function is set in AFR first before switching the pin mode. When switching from AF to INPUT or OUTPUT, the AF in AFR will remain valid up until the pin mode is switched. --- ports/stm32/mphalport.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 2025388413..9961c3d998 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -114,6 +114,12 @@ void mp_hal_pin_config(mp_hal_pin_obj_t pin_obj, uint32_t mode, uint32_t pull, u GPIO_TypeDef *gpio = pin_obj->gpio; uint32_t pin = pin_obj->pin; mp_hal_gpio_clock_enable(gpio); + if (mode == MP_HAL_PIN_MODE_ALT || mode == MP_HAL_PIN_MODE_ALT_OPEN_DRAIN) { + // To avoid any I/O glitches, make sure a valid alternate function is set in + // AFR first before switching the pin mode. When switching from AF to INPUT or + // OUTPUT, the AF in AFR will remain valid up until the pin mode is switched. + gpio->AFR[pin >> 3] = (gpio->AFR[pin >> 3] & ~(15 << (4 * (pin & 7)))) | (alt << (4 * (pin & 7))); + } gpio->MODER = (gpio->MODER & ~(3 << (2 * pin))) | ((mode & 3) << (2 * pin)); #if defined(GPIO_ASCR_ASC0) // The L4 has a special analog switch to connect the GPIO to the ADC @@ -124,7 +130,6 @@ void mp_hal_pin_config(mp_hal_pin_obj_t pin_obj, uint32_t mode, uint32_t pull, u #endif gpio->OSPEEDR = (gpio->OSPEEDR & ~(3 << (2 * pin))) | (2 << (2 * pin)); // full speed gpio->PUPDR = (gpio->PUPDR & ~(3 << (2 * pin))) | (pull << (2 * pin)); - gpio->AFR[pin >> 3] = (gpio->AFR[pin >> 3] & ~(15 << (4 * (pin & 7)))) | (alt << (4 * (pin & 7))); } bool mp_hal_pin_config_alt(mp_hal_pin_obj_t pin, uint32_t mode, uint32_t pull, uint8_t fn, uint8_t unit) {