mbed library sources that still uses the stm standard peripheral library
Fork of mbed-src by
Revision 414:ee28a0bed4ad, committed 2014-11-24
- Comitter:
- mbed_official
- Date:
- Mon Nov 24 07:30:07 2014 +0000
- Parent:
- 413:b8e8b58d8bcd
- Child:
- 415:4ec4c5b614b0
- Commit message:
- Synchronized with git revision 814740f86e7c9011336699456f32595b6c414b86
Full URL: https://github.com/mbedmicro/mbed/commit/814740f86e7c9011336699456f32595b6c414b86/
Targets: NUCLEOs - Improvement of gpio_irq hal
Changed in this revision
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8/gpio_irq_api.c Mon Nov 24 06:30:07 2014 +0000 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F030R8/gpio_irq_api.c Mon Nov 24 07:30:07 2014 +0000 @@ -38,50 +38,96 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) -// EXTI lines: 0-1, 2-3 and 4-15 +// Number of EXTI irq vectors (EXTI0_1, EXTI2_3, EXTI4_15) #define CHANNEL_NUM (3) -static uint32_t channel_ids[CHANNEL_NUM] = {0, 0, 0}; -static uint32_t channel_gpio[CHANNEL_NUM] = {0, 0, 0}; -static uint32_t channel_pin[CHANNEL_NUM] = {0, 0, 0}; +// Max pins for one line (max with EXTI4_15) +#define MAX_PIN_LINE (12) + +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} +}; + +// Used to return the index for channels array. +static uint32_t pin_base_nr[16] = { + // EXTI0_1 + 0, // pin 0 + 1, // pin 1 + // EXTI2_3 + 0, // pin 2 + 1, // pin 3 + // EXTI4_15 + 0, // pin 4 + 1, // pin 5 + 2, // pin 6 + 3, // pin 7 + 4, // pin 8 + 5, // pin 9 + 6, // pin 10 + 7, // pin 11 + 8, // pin 12 + 9, // pin 13 + 10, // pin 14 + 11 // 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; + + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); + + 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])); - // Clear interrupt flag - if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { - __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - } + // Clear interrupt flag + if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { + __HAL_GPIO_EXTI_CLEAR_FLAG(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; - if (channel_ids[irq_index] == 0) return; - - // 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); + // 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); + } + } + } } } // EXTI lines 0 to 1 static void gpio_irq0(void) { - handle_interrupt_in(0); + handle_interrupt_in(0, 2); } + // EXTI lines 2 to 3 static void gpio_irq1(void) { - handle_interrupt_in(1); + handle_interrupt_in(1, 2); } + // EXTI lines 4 to 15 static void gpio_irq2(void) { - handle_interrupt_in(2); + handle_interrupt_in(2, 12); } extern uint32_t Set_GPIO_Clock(uint32_t port_idx); @@ -91,6 +137,8 @@ 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; @@ -130,9 +178,13 @@ obj->irq_index = irq_index; obj->event = EDGE_NONE; obj->pin = pin; - 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; @@ -141,9 +193,15 @@ 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 pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); obj->event = EDGE_NONE;
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F072RB/gpio_irq_api.c Mon Nov 24 06:30:07 2014 +0000 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F072RB/gpio_irq_api.c Mon Nov 24 07:30:07 2014 +0000 @@ -38,50 +38,96 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) -// EXTI lines: 0-1, 2-3 and 4-15 +// Number of EXTI irq vectors (EXTI0_1, EXTI2_3, EXTI4_15) #define CHANNEL_NUM (3) -static uint32_t channel_ids[CHANNEL_NUM] = {0, 0, 0}; -static uint32_t channel_gpio[CHANNEL_NUM] = {0, 0, 0}; -static uint32_t channel_pin[CHANNEL_NUM] = {0, 0, 0}; +// Max pins for one line (max with EXTI4_15) +#define MAX_PIN_LINE (12) + +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} +}; + +// Used to return the index for channels array. +static uint32_t pin_base_nr[16] = { + // EXTI0_1 + 0, // pin 0 + 1, // pin 1 + // EXTI2_3 + 0, // pin 2 + 1, // pin 3 + // EXTI4_15 + 0, // pin 4 + 1, // pin 5 + 2, // pin 6 + 3, // pin 7 + 4, // pin 8 + 5, // pin 9 + 6, // pin 10 + 7, // pin 11 + 8, // pin 12 + 9, // pin 13 + 10, // pin 14 + 11 // 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; + + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); + + 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])); - // Clear interrupt flag - if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { - __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - } + // Clear interrupt flag + if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { + __HAL_GPIO_EXTI_CLEAR_FLAG(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; - if (channel_ids[irq_index] == 0) return; - - // 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); + // 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); + } + } + } } } // EXTI lines 0 to 1 static void gpio_irq0(void) { - handle_interrupt_in(0); + handle_interrupt_in(0, 2); } + // EXTI lines 2 to 3 static void gpio_irq1(void) { - handle_interrupt_in(1); + handle_interrupt_in(1, 2); } + // EXTI lines 4 to 15 static void gpio_irq2(void) { - handle_interrupt_in(2); + handle_interrupt_in(2, 12); } extern uint32_t Set_GPIO_Clock(uint32_t port_idx); @@ -91,6 +137,8 @@ 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; @@ -130,9 +178,13 @@ obj->irq_index = irq_index; obj->event = EDGE_NONE; obj->pin = pin; - 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; @@ -141,9 +193,15 @@ 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 pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); obj->event = EDGE_NONE;
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F091RC/gpio_irq_api.c Mon Nov 24 06:30:07 2014 +0000 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F091RC/gpio_irq_api.c Mon Nov 24 07:30:07 2014 +0000 @@ -38,50 +38,96 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) -// EXTI lines: 0-1, 2-3 and 4-15 +// Number of EXTI irq vectors (EXTI0_1, EXTI2_3, EXTI4_15) #define CHANNEL_NUM (3) -static uint32_t channel_ids[CHANNEL_NUM] = {0, 0, 0}; -static uint32_t channel_gpio[CHANNEL_NUM] = {0, 0, 0}; -static uint32_t channel_pin[CHANNEL_NUM] = {0, 0, 0}; +// Max pins for one line (max with EXTI4_15) +#define MAX_PIN_LINE (12) + +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} +}; + +// Used to return the index for channels array. +static uint32_t pin_base_nr[16] = { + // EXTI0_1 + 0, // pin 0 + 1, // pin 1 + // EXTI2_3 + 0, // pin 2 + 1, // pin 3 + // EXTI4_15 + 0, // pin 4 + 1, // pin 5 + 2, // pin 6 + 3, // pin 7 + 4, // pin 8 + 5, // pin 9 + 6, // pin 10 + 7, // pin 11 + 8, // pin 12 + 9, // pin 13 + 10, // pin 14 + 11 // 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; + + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); + + 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])); - // Clear interrupt flag - if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { - __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - } + // Clear interrupt flag + if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { + __HAL_GPIO_EXTI_CLEAR_FLAG(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; - if (channel_ids[irq_index] == 0) return; - - // 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); + // 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); + } + } + } } } // EXTI lines 0 to 1 static void gpio_irq0(void) { - handle_interrupt_in(0); + handle_interrupt_in(0, 2); } + // EXTI lines 2 to 3 static void gpio_irq1(void) { - handle_interrupt_in(1); + handle_interrupt_in(1, 2); } + // EXTI lines 4 to 15 static void gpio_irq2(void) { - handle_interrupt_in(2); + handle_interrupt_in(2, 12); } extern uint32_t Set_GPIO_Clock(uint32_t port_idx); @@ -91,6 +137,8 @@ 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; @@ -130,9 +178,13 @@ obj->irq_index = irq_index; obj->event = EDGE_NONE; obj->pin = pin; - 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; @@ -141,9 +193,15 @@ 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 pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); obj->event = EDGE_NONE;
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F302R8/gpio_irq_api.c Mon Nov 24 06:30:07 2014 +0000 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F302R8/gpio_irq_api.c Mon Nov 24 07:30:07 2014 +0000 @@ -38,70 +38,128 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) +// Number of EXTI irq vectors (EXTI0, EXTI1, EXTI2, EXTI3, EXTI4, EXTI5_9, EXTI10_15) #define CHANNEL_NUM (7) -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}; +// Max pins for one line (max with EXTI10_15) +#define MAX_PIN_LINE (6) + +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; + + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); + + 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])); - // Clear interrupt flag - if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { - __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - } + // Clear interrupt flag + if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { + __HAL_GPIO_EXTI_CLEAR_FLAG(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; - if (channel_ids[irq_index] == 0) return; - - // 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); + // 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); + handle_interrupt_in(0, 1); } + // EXTI line 1 static void gpio_irq1(void) { - handle_interrupt_in(1); + handle_interrupt_in(1, 1); } + // EXTI line 2 static void gpio_irq2(void) { - handle_interrupt_in(2); + handle_interrupt_in(2, 1); } + // EXTI line 3 static void gpio_irq3(void) { - handle_interrupt_in(3); + handle_interrupt_in(3, 1); } + // EXTI line 4 static void gpio_irq4(void) { - handle_interrupt_in(4); + handle_interrupt_in(4, 1); } + // EXTI lines 5 to 9 static void gpio_irq5(void) { - handle_interrupt_in(5); + handle_interrupt_in(5, 5); } + // EXTI lines 10 to 15 static void gpio_irq6(void) { - handle_interrupt_in(6); + handle_interrupt_in(6, 6); } extern uint32_t Set_GPIO_Clock(uint32_t port_idx); @@ -111,6 +169,8 @@ 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; @@ -183,9 +243,13 @@ obj->irq_index = irq_index; obj->event = EDGE_NONE; obj->pin = pin; - 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; @@ -194,9 +258,15 @@ 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 pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); obj->event = EDGE_NONE;
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F334R8/gpio_irq_api.c Mon Nov 24 06:30:07 2014 +0000 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F334R8/gpio_irq_api.c Mon Nov 24 07:30:07 2014 +0000 @@ -38,70 +38,128 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) +// Number of EXTI irq vectors (EXTI0, EXTI1, EXTI2, EXTI3, EXTI4, EXTI5_9, EXTI10_15) #define CHANNEL_NUM (7) -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}; +// Max pins for one line (max with EXTI10_15) +#define MAX_PIN_LINE (6) + +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; + + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); + + 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])); - // Clear interrupt flag - if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { - __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - } + // Clear interrupt flag + if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { + __HAL_GPIO_EXTI_CLEAR_FLAG(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; - if (channel_ids[irq_index] == 0) return; - - // 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); + // 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); + handle_interrupt_in(0, 1); } + // EXTI line 1 static void gpio_irq1(void) { - handle_interrupt_in(1); + handle_interrupt_in(1, 1); } + // EXTI line 2 static void gpio_irq2(void) { - handle_interrupt_in(2); + handle_interrupt_in(2, 1); } + // EXTI line 3 static void gpio_irq3(void) { - handle_interrupt_in(3); + handle_interrupt_in(3, 1); } + // EXTI line 4 static void gpio_irq4(void) { - handle_interrupt_in(4); + handle_interrupt_in(4, 1); } + // EXTI lines 5 to 9 static void gpio_irq5(void) { - handle_interrupt_in(5); + handle_interrupt_in(5, 5); } + // EXTI lines 10 to 15 static void gpio_irq6(void) { - handle_interrupt_in(6); + handle_interrupt_in(6, 6); } extern uint32_t Set_GPIO_Clock(uint32_t port_idx); @@ -111,6 +169,8 @@ 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; @@ -183,9 +243,13 @@ obj->irq_index = irq_index; obj->event = EDGE_NONE; obj->pin = pin; - 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; @@ -194,9 +258,15 @@ 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 pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); obj->event = EDGE_NONE;
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/gpio_irq_api.c Mon Nov 24 06:30:07 2014 +0000 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F401RE/gpio_irq_api.c Mon Nov 24 07:30:07 2014 +0000 @@ -38,70 +38,128 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) +// Number of EXTI irq vectors (EXTI0, EXTI1, EXTI2, EXTI3, EXTI4, EXTI5_9, EXTI10_15) #define CHANNEL_NUM (7) -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}; +// Max pins for one line (max with EXTI10_15) +#define MAX_PIN_LINE (6) + +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; + + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); + + 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])); - // Clear interrupt flag - if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { - __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - } + // Clear interrupt flag + if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { + __HAL_GPIO_EXTI_CLEAR_FLAG(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; - if (channel_ids[irq_index] == 0) return; - - // 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); + // 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); + handle_interrupt_in(0, 1); } + // EXTI line 1 static void gpio_irq1(void) { - handle_interrupt_in(1); + handle_interrupt_in(1, 1); } + // EXTI line 2 static void gpio_irq2(void) { - handle_interrupt_in(2); + handle_interrupt_in(2, 1); } + // EXTI line 3 static void gpio_irq3(void) { - handle_interrupt_in(3); + handle_interrupt_in(3, 1); } + // EXTI line 4 static void gpio_irq4(void) { - handle_interrupt_in(4); + handle_interrupt_in(4, 1); } + // EXTI lines 5 to 9 static void gpio_irq5(void) { - handle_interrupt_in(5); + handle_interrupt_in(5, 5); } + // EXTI lines 10 to 15 static void gpio_irq6(void) { - handle_interrupt_in(6); + handle_interrupt_in(6, 6); } extern uint32_t Set_GPIO_Clock(uint32_t port_idx); @@ -111,6 +169,8 @@ 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; @@ -183,9 +243,13 @@ obj->irq_index = irq_index; obj->event = EDGE_NONE; obj->pin = pin; - 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; @@ -194,9 +258,15 @@ 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 pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); obj->event = EDGE_NONE; @@ -204,13 +274,10 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { - uint32_t mode = STM_MODE_INPUT; + uint32_t mode = STM_MODE_IT_EVT_RESET; uint32_t pull = GPIO_NOPULL; if (enable) { - - pull = GPIO_NOPULL; - if (event == IRQ_RISE) { if ((obj->event == EDGE_FALL) || (obj->event == EDGE_BOTH)) { mode = STM_MODE_IT_RISING_FALLING; @@ -220,7 +287,6 @@ obj->event = EDGE_RISE; } } - if (event == IRQ_FALL) { if ((obj->event == EDGE_RISE) || (obj->event == EDGE_BOTH)) { mode = STM_MODE_IT_RISING_FALLING; @@ -230,28 +296,24 @@ obj->event = EDGE_FALL; } } - } else { - mode = STM_MODE_INPUT; - pull = GPIO_NOPULL; + } else { // Disable if (event == IRQ_RISE) { if ((obj->event == EDGE_FALL) || (obj->event == EDGE_BOTH)) { mode = STM_MODE_IT_FALLING; obj->event = EDGE_FALL; - } else if (obj->event == EDGE_RISE) { + } else { // NONE or RISE mode = STM_MODE_IT_EVT_RESET; obj->event = EDGE_NONE; } - } else if (event == IRQ_FALL) { + } + if (event == IRQ_FALL) { if ((obj->event == EDGE_RISE) || (obj->event == EDGE_BOTH)) { mode = STM_MODE_IT_RISING; obj->event = EDGE_RISE; - } else if (obj->event == IRQ_FALL) { + } else { // NONE or FALL mode = STM_MODE_IT_EVT_RESET; obj->event = EDGE_NONE; } - } else { - mode = STM_MODE_IT_EVT_RESET; - obj->event = EDGE_NONE; } }
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_F411RE/gpio_irq_api.c Mon Nov 24 06:30:07 2014 +0000 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_F411RE/gpio_irq_api.c Mon Nov 24 07:30:07 2014 +0000 @@ -38,70 +38,128 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) +// Number of EXTI irq vectors (EXTI0, EXTI1, EXTI2, EXTI3, EXTI4, EXTI5_9, EXTI10_15) #define CHANNEL_NUM (7) -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}; +// Max pins for one line (max with EXTI10_15) +#define MAX_PIN_LINE (6) + +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; + + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); + + 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])); - // Clear interrupt flag - if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { - __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - } + // Clear interrupt flag + if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { + __HAL_GPIO_EXTI_CLEAR_FLAG(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; - if (channel_ids[irq_index] == 0) return; - - // 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); + // 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); + handle_interrupt_in(0, 1); } + // EXTI line 1 static void gpio_irq1(void) { - handle_interrupt_in(1); + handle_interrupt_in(1, 1); } + // EXTI line 2 static void gpio_irq2(void) { - handle_interrupt_in(2); + handle_interrupt_in(2, 1); } + // EXTI line 3 static void gpio_irq3(void) { - handle_interrupt_in(3); + handle_interrupt_in(3, 1); } + // EXTI line 4 static void gpio_irq4(void) { - handle_interrupt_in(4); + handle_interrupt_in(4, 1); } + // EXTI lines 5 to 9 static void gpio_irq5(void) { - handle_interrupt_in(5); + handle_interrupt_in(5, 5); } + // EXTI lines 10 to 15 static void gpio_irq6(void) { - handle_interrupt_in(6); + handle_interrupt_in(6, 6); } extern uint32_t Set_GPIO_Clock(uint32_t port_idx); @@ -111,6 +169,8 @@ 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; @@ -183,9 +243,13 @@ obj->irq_index = irq_index; obj->event = EDGE_NONE; obj->pin = pin; - 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; @@ -194,9 +258,15 @@ 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 pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); obj->event = EDGE_NONE; @@ -204,13 +274,10 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { - uint32_t mode = STM_MODE_INPUT; + uint32_t mode = STM_MODE_IT_EVT_RESET; uint32_t pull = GPIO_NOPULL; if (enable) { - - pull = GPIO_NOPULL; - if (event == IRQ_RISE) { if ((obj->event == EDGE_FALL) || (obj->event == EDGE_BOTH)) { mode = STM_MODE_IT_RISING_FALLING; @@ -220,7 +287,6 @@ obj->event = EDGE_RISE; } } - if (event == IRQ_FALL) { if ((obj->event == EDGE_RISE) || (obj->event == EDGE_BOTH)) { mode = STM_MODE_IT_RISING_FALLING; @@ -230,28 +296,24 @@ obj->event = EDGE_FALL; } } - } else { - mode = STM_MODE_INPUT; - pull = GPIO_NOPULL; + } else { // Disable if (event == IRQ_RISE) { if ((obj->event == EDGE_FALL) || (obj->event == EDGE_BOTH)) { mode = STM_MODE_IT_FALLING; obj->event = EDGE_FALL; - } else if (obj->event == EDGE_RISE) { + } else { // NONE or RISE mode = STM_MODE_IT_EVT_RESET; obj->event = EDGE_NONE; } - } else if (event == IRQ_FALL) { + } + if (event == IRQ_FALL) { if ((obj->event == EDGE_RISE) || (obj->event == EDGE_BOTH)) { mode = STM_MODE_IT_RISING; obj->event = EDGE_RISE; - } else if (obj->event == IRQ_FALL) { + } else { // NONE or FALL mode = STM_MODE_IT_EVT_RESET; obj->event = EDGE_NONE; } - } else { - mode = STM_MODE_IT_EVT_RESET; - obj->event = EDGE_NONE; } }
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_L053R8/gpio_irq_api.c Mon Nov 24 06:30:07 2014 +0000 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_L053R8/gpio_irq_api.c Mon Nov 24 07:30:07 2014 +0000 @@ -38,50 +38,96 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) +// Number of EXTI irq vectors (EXTI0_1, EXTI2_3, EXTI4_15) #define CHANNEL_NUM (3) -static uint32_t channel_ids[CHANNEL_NUM] = {0, 0, 0}; -static uint32_t channel_gpio[CHANNEL_NUM] = {0, 0, 0}; -static uint32_t channel_pin[CHANNEL_NUM] = {0, 0, 0}; +// Max pins for one line (max with EXTI4_15) +#define MAX_PIN_LINE (12) + +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} +}; + +// Used to return the index for channels array. +static uint32_t pin_base_nr[16] = { + // EXTI0_1 + 0, // pin 0 + 1, // pin 1 + // EXTI2_3 + 0, // pin 2 + 1, // pin 3 + // EXTI4_15 + 0, // pin 4 + 1, // pin 5 + 2, // pin 6 + 3, // pin 7 + 4, // pin 8 + 5, // pin 9 + 6, // pin 10 + 7, // pin 11 + 8, // pin 12 + 9, // pin 13 + 10, // pin 14 + 11 // 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; + + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); + + 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])); - // Clear interrupt flag - if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { - __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - } + // Clear interrupt flag + if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { + __HAL_GPIO_EXTI_CLEAR_FLAG(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; - if (channel_ids[irq_index] == 0) return; - - // 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); + // 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 lines 0 to 1 static void gpio_irq0(void) { - handle_interrupt_in(0); + handle_interrupt_in(0, 2); } + // EXTI lines 2 to 3 static void gpio_irq1(void) { - handle_interrupt_in(1); + handle_interrupt_in(1, 2); } + // EXTI lines 4 to 15 static void gpio_irq2(void) { - handle_interrupt_in(2); + handle_interrupt_in(2, 12); } extern uint32_t Set_GPIO_Clock(uint32_t port_idx); @@ -91,6 +137,8 @@ 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; @@ -130,9 +178,13 @@ obj->irq_index = irq_index; obj->event = EDGE_NONE; obj->pin = pin; - 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; @@ -141,9 +193,15 @@ 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 pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); obj->event = EDGE_NONE;
--- a/targets/hal/TARGET_STM/TARGET_NUCLEO_L152RE/gpio_irq_api.c Mon Nov 24 06:30:07 2014 +0000 +++ b/targets/hal/TARGET_STM/TARGET_NUCLEO_L152RE/gpio_irq_api.c Mon Nov 24 07:30:07 2014 +0000 @@ -38,63 +38,128 @@ #define EDGE_FALL (2) #define EDGE_BOTH (3) +// Number of EXTI irq vectors (EXTI0, EXTI1, EXTI2, EXTI3, EXTI4, EXTI5_9, EXTI10_15) #define CHANNEL_NUM (7) -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}; +// Max pins for one line (max with EXTI10_15) +#define MAX_PIN_LINE (6) + +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; + + for (gpio_idx = 0; gpio_idx < max_num_pin_line; gpio_idx++) { + uint32_t current_mask = (1 << gpio_idx); + + 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])); - // Clear interrupt flag - if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { - __HAL_GPIO_EXTI_CLEAR_FLAG(pin); - } + // Clear interrupt flag + if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) { + __HAL_GPIO_EXTI_CLEAR_FLAG(pin); + + if (gpio_channel->channel_ids[gpio_idx] == 0) continue; - if (channel_ids[irq_index] == 0) return; - - // 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); + // 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 +169,8 @@ 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; @@ -176,9 +243,13 @@ obj->irq_index = irq_index; obj->event = EDGE_NONE; obj->pin = pin; - 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; @@ -187,9 +258,15 @@ 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 pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0)); obj->event = EDGE_NONE;