From 363900be5d964479a345f5e07da769330734886d Mon Sep 17 00:00:00 2001 From: Dave Hylands Date: Wed, 13 Feb 2019 11:41:54 -0800 Subject: [PATCH] stm32/extint: Fix ExtInt to work with non-GPIO pins. --- ports/stm32/extint.c | 83 ++++++++++++++++++++++++++++++-------------- ports/stm32/extint.h | 1 + 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index fedb60d139..cdfa1a1e18 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -93,18 +93,24 @@ // The L4 MCU supports 40 Events/IRQs lines of the type configurable and direct. // Here we only support configurable line types. Details, see page 330 of RM0351, Rev 1. // The USB_FS_WAKUP event is a direct type and there is no support for it. -#define EXTI_Mode_Interrupt offsetof(EXTI_TypeDef, IMR1) -#define EXTI_Mode_Event offsetof(EXTI_TypeDef, EMR1) +#define EXTI_Mode_Interrupt offsetof(EXTI_TypeDef, IMR1) +#define EXTI_Mode_Event offsetof(EXTI_TypeDef, EMR1) +#define EXTI_Trigger_Rising offsetof(EXTI_TypeDef, RTSR1) +#define EXTI_Trigger_Falling offsetof(EXTI_TypeDef, FTSR1) #define EXTI_RTSR EXTI->RTSR1 #define EXTI_FTSR EXTI->FTSR1 #elif defined(STM32H7) -#define EXTI_Mode_Interrupt offsetof(EXTI_Core_TypeDef, IMR1) -#define EXTI_Mode_Event offsetof(EXTI_Core_TypeDef, EMR1) +#define EXTI_Mode_Interrupt offsetof(EXTI_Core_TypeDef, IMR1) +#define EXTI_Mode_Event offsetof(EXTI_Core_TypeDef, EMR1) +#define EXTI_Trigger_Rising offsetof(EXTI_Core_TypeDef, RTSR1) +#define EXTI_Trigger_Falling offsetof(EXTI_Core_TypeDef, FTSR1) #define EXTI_RTSR EXTI->RTSR1 #define EXTI_FTSR EXTI->FTSR1 #else -#define EXTI_Mode_Interrupt offsetof(EXTI_TypeDef, IMR) -#define EXTI_Mode_Event offsetof(EXTI_TypeDef, EMR) +#define EXTI_Mode_Interrupt offsetof(EXTI_TypeDef, IMR) +#define EXTI_Mode_Event offsetof(EXTI_TypeDef, EMR) +#define EXTI_Trigger_Rising offsetof(EXTI_TypeDef, RTSR) +#define EXTI_Trigger_Falling offsetof(EXTI_TypeDef, FTSR) #define EXTI_RTSR EXTI->RTSR #define EXTI_FTSR EXTI->FTSR #endif @@ -210,15 +216,21 @@ uint extint_register(mp_obj_t pin_obj, uint32_t mode, uint32_t pull, mp_obj_t ca pyb_extint_hard_irq[v_line] = true; pyb_extint_callback_arg[v_line] = MP_OBJ_NEW_SMALL_INT(v_line); - mp_hal_gpio_clock_enable(pin->gpio); - GPIO_InitTypeDef exti; - exti.Pin = pin->pin_mask; - exti.Mode = mode; - exti.Pull = pull; - exti.Speed = GPIO_SPEED_FREQ_HIGH; - HAL_GPIO_Init(pin->gpio, &exti); + if (pin == NULL) { + // pin will be NULL for non GPIO EXTI lines + extint_trigger_mode(v_line, mode); + extint_enable(v_line); + } else { + mp_hal_gpio_clock_enable(pin->gpio); + GPIO_InitTypeDef exti; + exti.Pin = pin->pin_mask; + exti.Mode = mode; + exti.Pull = pull; + exti.Speed = GPIO_SPEED_FREQ_HIGH; + HAL_GPIO_Init(pin->gpio, &exti); - // Calling HAL_GPIO_Init does an implicit extint_enable + // Calling HAL_GPIO_Init does an implicit extint_enable + } /* Enable and set NVIC Interrupt to the lowest priority */ NVIC_SetPriority(IRQn_NONNEG(nvic_irq_channel[v_line]), IRQ_PRI_EXTINT); @@ -262,19 +274,7 @@ void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_ (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); - // Enable or disable the rising detector - if ((mode & GPIO_MODE_IT_RISING) == GPIO_MODE_IT_RISING) { - EXTI_RTSR |= 1 << line; - } else { - EXTI_RTSR &= ~(1 << line); - } - - // Enable or disable the falling detector - if ((mode & GPIO_MODE_IT_FALLING) == GPIO_MODE_IT_FALLING) { - EXTI_FTSR |= 1 << line; - } else { - EXTI_FTSR &= ~(1 << line); - } + extint_trigger_mode(line, mode); // Configure the NVIC NVIC_SetPriority(IRQn_NONNEG(nvic_irq_channel[line]), IRQ_PRI_EXTINT); @@ -353,6 +353,35 @@ void extint_swint(uint line) { #endif } +void extint_trigger_mode(uint line, uint32_t mode) { + if (line >= EXTI_NUM_VECTORS) { + return; + } + #if defined(STM32F0) || defined(STM32F7) || defined(STM32H7) + // The Cortex-M7 doesn't have bitband support. + mp_uint_t irq_state = disable_irq(); + // Enable or disable the rising detector + if ((mode & GPIO_MODE_IT_RISING) == GPIO_MODE_IT_RISING) { + EXTI_RTSR |= (1 << line); + } else { + EXTI_RTSR &= ~(1 << line); + } + // Enable or disable the falling detector + if ((mode & GPIO_MODE_IT_FALLING) == GPIO_MODE_IT_FALLING) { + EXTI_FTSR |= 1 << line; + } else { + EXTI_FTSR &= ~(1 << line); + } + enable_irq(irq_state); + #else + // Since manipulating FTSR/RTSR is a read-modify-write, and we want this to + // be atomic, we use the bit-band area to just affect the bit we're + // interested in. + EXTI_MODE_BB(EXTI_Trigger_Rising, line) = (mode & GPIO_MODE_IT_RISING) == GPIO_MODE_IT_RISING; + EXTI_MODE_BB(EXTI_Trigger_Falling, line) = (mode & GPIO_MODE_IT_FALLING) == GPIO_MODE_IT_FALLING; + #endif +} + /// \method line() /// Return the line number that the pin is mapped to. STATIC mp_obj_t extint_obj_line(mp_obj_t self_in) { diff --git a/ports/stm32/extint.h b/ports/stm32/extint.h index 7646df731c..924b48a8bf 100644 --- a/ports/stm32/extint.h +++ b/ports/stm32/extint.h @@ -69,6 +69,7 @@ void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_ void extint_enable(uint line); void extint_disable(uint line); void extint_swint(uint line); +void extint_trigger_mode(uint line, uint32_t mode); void Handle_EXTI_Irq(uint32_t line);