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) {