diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c index fba80fbc5c..3857a496fb 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/gpio_irq_api.c @@ -39,62 +39,125 @@ #define EDGE_BOTH (3) #define CHANNEL_NUM (7) +// Max pins for one line (max with EXTI10_15) +#define MAX_PIN_LINE (6) -static uint32_t channel_ids[CHANNEL_NUM] = {0, 0, 0, 0, 0, 0, 0}; -static uint32_t channel_gpio[CHANNEL_NUM] = {0, 0, 0, 0, 0, 0, 0}; -static uint32_t channel_pin[CHANNEL_NUM] = {0, 0, 0, 0, 0, 0, 0}; +typedef struct gpio_channel { + uint32_t pin_mask; // bitmask representing which pins are configured for receiving interrupts + uint32_t channel_ids[MAX_PIN_LINE]; // mbed "gpio_irq_t gpio_irq" field of instance + uint32_t channel_gpio[MAX_PIN_LINE]; // base address of gpio port group + uint32_t channel_pin[MAX_PIN_LINE]; // pin number in port group +} gpio_channel_t; + +static gpio_channel_t channels[CHANNEL_NUM] = { + {.pin_mask = 0}, + {.pin_mask = 0}, + {.pin_mask = 0}, + {.pin_mask = 0}, + {.pin_mask = 0}, + {.pin_mask = 0}, + {.pin_mask = 0} +}; + +// Used to return the index for channels array. +static uint32_t pin_base_nr[16] = { + // EXTI0 + 0, // pin 0 + // EXTI1 + 0, // pin 1 + // EXTI2 + 0, // pin 2 + // EXTI3 + 0, // pin 3 + // EXTI4 + 0, // pin 4 + // EXTI5_9 + 0, // pin 5 + 1, // pin 6 + 2, // pin 7 + 3, // pin 8 + 4, // pin 9 + // EXTI10_15 + 0, // pin 10 + 1, // pin 11 + 2, // pin 12 + 3, // pin 13 + 4, // pin 14 + 5 // pin 15 +}; static gpio_irq_handler irq_handler; -static void handle_interrupt_in(uint32_t irq_index) +static void handle_interrupt_in(uint32_t irq_index, uint32_t max_num_pin_line) { - // Retrieve the gpio and pin that generate the irq - GPIO_TypeDef *gpio = (GPIO_TypeDef *)(channel_gpio[irq_index]); - uint32_t pin = (uint32_t)(1 << channel_pin[irq_index]); + gpio_channel_t *gpio_channel = &channels[irq_index]; + uint32_t gpio_idx; - // Clear interrupt flag - if (EXTI_GetITStatus(pin) != RESET) { - EXTI_ClearITPendingBit(pin); - } + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); - if (channel_ids[irq_index] == 0) return; + if (gpio_channel->pin_mask & current_mask) { + // Retrieve the gpio and pin that generate the irq + GPIO_TypeDef *gpio = (GPIO_TypeDef *)(gpio_channel->channel_gpio[gpio_idx]); + uint32_t pin = (uint32_t)(1 << (gpio_channel->channel_pin[gpio_idx])); - // Check which edge has generated the irq - if ((gpio->IDR & pin) == 0) { - irq_handler(channel_ids[irq_index], IRQ_FALL); - } else { - irq_handler(channel_ids[irq_index], IRQ_RISE); + // Clear interrupt flag + if (EXTI_GetITStatus(pin) != RESET) { + EXTI_ClearITPendingBit(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; + + // Check which edge has generated the irq + if ((gpio->IDR & pin) == 0) { + irq_handler(gpio_channel->channel_ids[gpio_idx], IRQ_FALL); + } else { + irq_handler(gpio_channel->channel_ids[gpio_idx], IRQ_RISE); + } + } + } } } -// The irq_index is passed to the function +// EXTI line 0 static void gpio_irq0(void) { - handle_interrupt_in(0); // EXTI line 0 + handle_interrupt_in(0, 1); } + +// EXTI line 1 static void gpio_irq1(void) { - handle_interrupt_in(1); // EXTI line 1 + handle_interrupt_in(1, 1); } + +// EXTI line 2 static void gpio_irq2(void) { - handle_interrupt_in(2); // EXTI line 2 + handle_interrupt_in(2, 1); } + +// EXTI line 3 static void gpio_irq3(void) { - handle_interrupt_in(3); // EXTI line 3 + handle_interrupt_in(3, 1); } + +// EXTI line 4 static void gpio_irq4(void) { - handle_interrupt_in(4); // EXTI line 4 + handle_interrupt_in(4, 1); } + +// EXTI lines 5 to 9 static void gpio_irq5(void) { - handle_interrupt_in(5); // EXTI lines 5 to 9 + handle_interrupt_in(5, 5); } + +// EXTI lines 10 to 15 static void gpio_irq6(void) { - handle_interrupt_in(6); // EXTI lines 10 to 15 + handle_interrupt_in(6, 6); } extern uint32_t Set_GPIO_Clock(uint32_t port_idx); @@ -104,6 +167,8 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 IRQn_Type irq_n = (IRQn_Type)0; uint32_t vector = 0; uint32_t irq_index; + gpio_channel_t *gpio_channel; + uint32_t gpio_idx; if (pin == NC) return -1; @@ -193,9 +258,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 obj->irq_n = irq_n; obj->irq_index = irq_index; obj->event = EDGE_NONE; - channel_ids[irq_index] = id; - channel_gpio[irq_index] = gpio_add; - channel_pin[irq_index] = pin_index; + + gpio_channel = &channels[irq_index]; + gpio_idx = pin_base_nr[pin_index]; + gpio_channel->pin_mask |= (1 << gpio_idx); + gpio_channel->channel_ids[gpio_idx] = id; + gpio_channel->channel_gpio[gpio_idx] = gpio_add; + gpio_channel->channel_pin[gpio_idx] = pin_index; irq_handler = handler; @@ -204,9 +273,15 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32 void gpio_irq_free(gpio_irq_t *obj) { - channel_ids[obj->irq_index] = 0; - channel_gpio[obj->irq_index] = 0; - channel_pin[obj->irq_index] = 0; + gpio_channel_t *gpio_channel = &channels[obj->irq_index]; + uint32_t pin_index = STM_PIN(obj->pin); + uint32_t gpio_idx = pin_base_nr[pin_index]; + + gpio_channel->pin_mask &= ~(1 << gpio_idx); + gpio_channel->channel_ids[gpio_idx] = 0; + gpio_channel->channel_gpio[gpio_idx] = 0; + gpio_channel->channel_pin[gpio_idx] = 0; + // Disable EXTI line EXTI_InitTypeDef EXTI_InitStructure; EXTI_StructInit(&EXTI_InitStructure); @@ -217,8 +292,7 @@ void gpio_irq_free(gpio_irq_t *obj) void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { EXTI_InitTypeDef EXTI_InitStructure; - - uint32_t pin_index = channel_pin[obj->irq_index]; + uint32_t pin_index = STM_PIN(obj->pin); EXTI_InitStructure.EXTI_Line = (uint32_t)(1 << pin_index); EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; diff --git a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h index 3b8a442be8..162117e03d 100644 --- a/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h +++ b/libraries/mbed/targets/hal/TARGET_STM/TARGET_NUCLEO_F103RB/objects.h @@ -43,6 +43,7 @@ struct gpio_irq_s { IRQn_Type irq_n; uint32_t irq_index; uint32_t event; + PinName pin; }; struct port_s {