[NUCLEOs] Improvement of gpio_irq hal

Now it is possible to have multiple interrupt pins on EXTI vectors.
Example:
EXTI0 -> PA_0 or PB_0 or PC_0, ... only 1 pin
EXTI5_9 -> PA_5 and PA_6 and PB_7 and PC_8 and PC_9: up to 5 pins
EXTI10_15: PA_10 and PB_11 and PB_12, ... : up to 6 pins
pull/720/head
bcostm 2014-11-18 12:28:30 +01:00
parent ff85a88b7b
commit 20177c912b
9 changed files with 864 additions and 291 deletions

View File

@ -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;
// Clear interrupt flag
if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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);
}
}
}
}
}
// 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 @@ 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;
@ -130,9 +178,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
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 @@ 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
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
obj->event = EDGE_NONE;

View File

@ -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;
// Clear interrupt flag
if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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);
}
}
}
}
}
// 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 @@ 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;
@ -130,9 +178,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
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 @@ 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
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
obj->event = EDGE_NONE;

View File

@ -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;
// Clear interrupt flag
if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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);
}
}
}
}
}
// 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 @@ 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;
@ -130,9 +178,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
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 @@ 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
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
obj->event = EDGE_NONE;

View File

@ -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;
// Clear interrupt flag
if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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);
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 @@ 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;
@ -183,9 +243,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
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 @@ 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
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
obj->event = EDGE_NONE;

View File

@ -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;
// Clear interrupt flag
if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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);
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 @@ 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;
@ -183,9 +243,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
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 @@ 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
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
obj->event = EDGE_NONE;

View File

@ -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;
// Clear interrupt flag
if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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);
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 @@ 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;
@ -183,9 +243,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
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 @@ 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
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
obj->event = EDGE_NONE;
@ -204,13 +274,10 @@ void gpio_irq_free(gpio_irq_t *obj)
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 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
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 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
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;
}
}

View File

@ -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;
// Clear interrupt flag
if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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);
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 @@ 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;
@ -183,9 +243,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
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 @@ 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
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
obj->event = EDGE_NONE;
@ -204,13 +274,10 @@ void gpio_irq_free(gpio_irq_t *obj)
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 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
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 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
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;
}
}

View File

@ -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;
// Clear interrupt flag
if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 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 @@ 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;
@ -130,9 +178,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
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 @@ 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
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
obj->event = EDGE_NONE;

View File

@ -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;
// Clear interrupt flag
if (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 (__HAL_GPIO_EXTI_GET_FLAG(pin) != RESET) {
__HAL_GPIO_EXTI_CLEAR_FLAG(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 +169,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;
@ -176,9 +243,13 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
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 @@ 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
pin_function(obj->pin, STM_PIN_DATA(STM_MODE_INPUT, GPIO_NOPULL, 0));
obj->event = EDGE_NONE;