diff --git a/targets/TARGET_Silicon_Labs/TARGET_EFM32/gpio_irq_api.c b/targets/TARGET_Silicon_Labs/TARGET_EFM32/gpio_irq_api.c index 4816d0f25e..f2aa6172cc 100644 --- a/targets/TARGET_Silicon_Labs/TARGET_EFM32/gpio_irq_api.c +++ b/targets/TARGET_Silicon_Labs/TARGET_EFM32/gpio_irq_api.c @@ -61,12 +61,26 @@ static void handle_interrupt_in(uint8_t pin) return; } - // Get trigger event + // trying to discern which GPIO IRQ we got gpio_irq_event event = IRQ_NONE; - if (GPIO->EXTIFALL & (1 << pin)) { + if (((GPIO->EXTIFALL & (1 << pin)) != 0) && ((GPIO->EXTIRISE & (1 << pin)) == 0)) { + // Only the fall handler is active, so this must be a falling edge event = IRQ_FALL; - } else if (GPIO->EXTIRISE & (1 << pin)) { + } else if (((GPIO->EXTIFALL & (1 << pin)) == 0) && ((GPIO->EXTIRISE & (1 << pin)) != 0)) { + // Only the rise handler is active, so this must be a rising edge event = IRQ_RISE; + } else { + // Ambiguous as to which IRQ we've received. Poll the pin to check which one to fire. + // NOTE: If trying to detect a pulse where the width is shorter than this handler's + // reaction time, there will only be one callback (for the trailing edge) called. + + // we are storing two ports in each uint8, so we must acquire the one we want. + // If pin is odd, the port is encoded in the 4 most significant bits. + // If pin is even, the port is encoded in the 4 least significant bits + uint8_t isRise = GPIO_PinInGet((pin & 0x1) ? + channel_ports[(pin>>1) & 0x7] >> 4 & 0xF : + channel_ports[(pin>>1) & 0x7] >> 0 & 0xF, pin); + event = (isRise == 1 ? IRQ_RISE : IRQ_FALL); } GPIO_IntClear(pin); irq_handler(channel_ids[pin], event); @@ -132,9 +146,6 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) /* Disable, set config and enable */ gpio_irq_disable(obj); - bool was_disabled = false; - if(GPIO->IEN == 0) was_disabled = true; - GPIO_IntConfig((GPIO_Port_TypeDef)((obj->pin >> 4) & 0xF), obj->pin &0xF, obj->risingEdge, obj->fallingEdge, obj->risingEdge || obj->fallingEdge); }