Skip to content

Commit 86fcae5

Browse files
committed
Nuvoton: Fix GPIO rising/falling edge interrupts cannot exist simultaneously
This is to pass mbed_hal_fpga_ci_test_shield-gpio_irq test. Update targets: - NUMAKER_PFM_NANO130 - NUMAKER_PFM_NUC472 - NUMAKER_PFM_M453 - NUMAKER_PFM_M487/NUMAKER_IOT_M487 - NUMAKER_M252KG - NUMAKER_IOT_M263A
1 parent 69a2803 commit 86fcae5

File tree

12 files changed

+197
-110
lines changed

12 files changed

+197
-110
lines changed

targets/TARGET_NUVOTON/TARGET_M251/gpio_irq_api.c

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "pinmap.h"
2626
#include "PeripheralPins.h"
2727
#include "nu_bitutil.h"
28+
#include "mbed_assert.h"
2829

2930
#define NU_MAX_PIN_PER_PORT 16
3031

@@ -87,6 +88,7 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
8788
}
8889

8990
obj->pin = pin;
91+
obj->irq_types = 0;
9092
obj->irq_handler = (uint32_t) handler;
9193
obj->irq_id = id;
9294

@@ -154,27 +156,38 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
154156
uint32_t port_index = NU_PINPORT(obj->pin);
155157
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
156158

159+
/* We assume BSP has such coding so that we can easily add/remove either irq type. */
160+
MBED_STATIC_ASSERT(GPIO_INT_BOTH_EDGE == (GPIO_INT_RISING | GPIO_INT_FALLING),
161+
"GPIO_INT_BOTH_EDGE must be bitwise OR of GPIO_INT_RISING and GPIO_INT_FALLING");
162+
uint32_t irq_type;
157163
switch (event) {
158-
case IRQ_RISE:
159-
if (enable) {
160-
GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_RISING);
161-
} else {
162-
gpio_base->INTEN &= ~(GPIO_INT_RISING << pin_index);
163-
}
164-
break;
164+
case IRQ_RISE:
165+
irq_type = GPIO_INT_RISING;
166+
break;
165167

166-
case IRQ_FALL:
167-
if (enable) {
168-
GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_FALLING);
169-
} else {
170-
gpio_base->INTEN &= ~(GPIO_INT_FALLING << pin_index);
171-
}
172-
break;
168+
case IRQ_FALL:
169+
irq_type = GPIO_INT_FALLING;
170+
break;
173171

174-
case IRQ_NONE:
175-
default:
176-
break;
172+
default:
173+
irq_type = 0;
177174
}
175+
176+
/* We can handle invalid/null irq type. */
177+
if (enable) {
178+
obj->irq_types |= irq_type;
179+
} else {
180+
obj->irq_types &= ~irq_type;
181+
}
182+
183+
/* Update irq types:
184+
*
185+
* Implementations of GPIO_EnableInt(...) are inconsistent: disable or not irq type not enabled.
186+
* For consistency, disable GPIO_INT_BOTH_EDGE and then enable OR'ed irq types, GPIO_INT_RISING,
187+
* GPIO_INT_FALLING, or both.
188+
*/
189+
GPIO_DisableInt(gpio_base, pin_index);
190+
GPIO_EnableInt(gpio_base, pin_index, obj->irq_types);
178191
}
179192

180193
void gpio_irq_enable(gpio_irq_t *obj)

targets/TARGET_NUVOTON/TARGET_M251/objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ extern "C" {
3131

3232
struct gpio_irq_s {
3333
PinName pin;
34+
uint32_t irq_types;
3435
uint32_t irq_handler;
3536
uint32_t irq_id;
3637
struct gpio_irq_s *next;

targets/TARGET_NUVOTON/TARGET_M261/gpio_irq_api.c

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "pinmap.h"
2525
#include "PeripheralPins.h"
2626
#include "nu_bitutil.h"
27+
#include "mbed_assert.h"
2728

2829
#define NU_MAX_PIN_PER_PORT 16
2930

@@ -88,6 +89,7 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
8889
}
8990

9091
obj->pin = pin;
92+
obj->irq_types = 0;
9193
obj->irq_handler = (uint32_t) handler;
9294
obj->irq_id = id;
9395

@@ -155,27 +157,38 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
155157
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
156158
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
157159

160+
/* We assume BSP has such coding so that we can easily add/remove either irq type. */
161+
MBED_STATIC_ASSERT(GPIO_INT_BOTH_EDGE == (GPIO_INT_RISING | GPIO_INT_FALLING),
162+
"GPIO_INT_BOTH_EDGE must be bitwise OR of GPIO_INT_RISING and GPIO_INT_FALLING");
163+
uint32_t irq_type;
158164
switch (event) {
159-
case IRQ_RISE:
160-
if (enable) {
161-
GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_RISING);
162-
} else {
163-
gpio_base->INTEN &= ~(GPIO_INT_RISING << pin_index);
164-
}
165-
break;
165+
case IRQ_RISE:
166+
irq_type = GPIO_INT_RISING;
167+
break;
166168

167-
case IRQ_FALL:
168-
if (enable) {
169-
GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_FALLING);
170-
} else {
171-
gpio_base->INTEN &= ~(GPIO_INT_FALLING << pin_index);
172-
}
173-
break;
169+
case IRQ_FALL:
170+
irq_type = GPIO_INT_FALLING;
171+
break;
174172

175-
case IRQ_NONE:
176-
default:
177-
break;
173+
default:
174+
irq_type = 0;
178175
}
176+
177+
/* We can handle invalid/null irq type. */
178+
if (enable) {
179+
obj->irq_types |= irq_type;
180+
} else {
181+
obj->irq_types &= ~irq_type;
182+
}
183+
184+
/* Update irq types:
185+
*
186+
* Implementations of GPIO_EnableInt(...) are inconsistent: disable or not irq type not enabled.
187+
* For consistency, disable GPIO_INT_BOTH_EDGE and then enable OR'ed irq types, GPIO_INT_RISING,
188+
* GPIO_INT_FALLING, or both.
189+
*/
190+
GPIO_DisableInt(gpio_base, pin_index);
191+
GPIO_EnableInt(gpio_base, pin_index, obj->irq_types);
179192
}
180193

181194
void gpio_irq_enable(gpio_irq_t *obj)

targets/TARGET_NUVOTON/TARGET_M261/objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ extern "C" {
3030

3131
struct gpio_irq_s {
3232
PinName pin;
33+
uint32_t irq_types;
3334
uint32_t irq_handler;
3435
uint32_t irq_id;
3536
struct gpio_irq_s *next;

targets/TARGET_NUVOTON/TARGET_M451/gpio_irq_api.c

Lines changed: 44 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "pinmap.h"
2424
#include "PeripheralPins.h"
2525
#include "nu_bitutil.h"
26+
#include "mbed_assert.h"
2627

2728
#define NU_MAX_PIN_PER_PORT 16
2829

@@ -76,14 +77,15 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
7677
if (pin == NC) {
7778
return -1;
7879
}
79-
80+
8081
uint32_t pin_index = NU_PINNAME_TO_PIN(pin);
8182
uint32_t port_index = NU_PINNAME_TO_PORT(pin);
8283
if (pin_index >= NU_MAX_PIN_PER_PORT || port_index >= NU_MAX_PORT) {
8384
return -1;
8485
}
85-
86+
8687
obj->pin = pin;
88+
obj->irq_types = 0;
8789
obj->irq_handler = (uint32_t) handler;
8890
obj->irq_id = id;
8991

@@ -101,16 +103,16 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
101103
GPIO_ENABLE_DEBOUNCE(gpio_base, 1 << pin_index);
102104
#else
103105
// Enable de-bounce if the pin is in the de-bounce enable list
104-
106+
105107
// De-bounce defaults to disabled.
106108
GPIO_DISABLE_DEBOUNCE(gpio_base, 1 << pin_index);
107-
109+
108110
PinName *debounce_pos = gpio_irq_debounce_arr;
109111
PinName *debounce_end = gpio_irq_debounce_arr + sizeof (gpio_irq_debounce_arr) / sizeof (gpio_irq_debounce_arr[0]);
110112
for (; debounce_pos != debounce_end && *debounce_pos != NC; debounce_pos ++) {
111113
uint32_t pin_index_debunce = NU_PINNAME_TO_PIN(*debounce_pos);
112114
uint32_t port_index_debounce = NU_PINNAME_TO_PORT(*debounce_pos);
113-
115+
114116
if (pin_index == pin_index_debunce &&
115117
port_index == port_index_debounce) {
116118
// Configure de-bounce clock source and sampling cycle time
@@ -121,14 +123,14 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
121123
}
122124
#endif
123125
}
124-
126+
125127
struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index;
126128

127129
var->obj_arr[pin_index] = obj;
128-
130+
129131
// NOTE: InterruptIn requires IRQ enabled by default.
130132
gpio_irq_enable(obj);
131-
133+
132134
return 0;
133135
}
134136

@@ -137,10 +139,10 @@ void gpio_irq_free(gpio_irq_t *obj)
137139
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
138140
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
139141
struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index;
140-
142+
141143
NVIC_DisableIRQ(var->irq_n);
142144
NU_PORT_BASE(port_index)->INTEN = 0;
143-
145+
144146
MBED_ASSERT(pin_index < NU_MAX_PIN_PER_PORT);
145147
var->obj_arr[pin_index] = NULL;
146148
}
@@ -150,34 +152,47 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
150152
uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
151153
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
152154
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
153-
155+
156+
/* We assume BSP has such coding so that we can easily add/remove either irq type. */
157+
MBED_STATIC_ASSERT(GPIO_INT_BOTH_EDGE == (GPIO_INT_RISING | GPIO_INT_FALLING),
158+
"GPIO_INT_BOTH_EDGE must be bitwise OR of GPIO_INT_RISING and GPIO_INT_FALLING");
159+
uint32_t irq_type;
154160
switch (event) {
155161
case IRQ_RISE:
156-
if (enable) {
157-
GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_RISING);
158-
}
159-
else {
160-
gpio_base->INTEN &= ~(GPIO_INT_RISING << pin_index);
161-
}
162+
irq_type = GPIO_INT_RISING;
162163
break;
163-
164+
164165
case IRQ_FALL:
165-
if (enable) {
166-
GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_FALLING);
167-
}
168-
else {
169-
gpio_base->INTEN &= ~(GPIO_INT_FALLING << pin_index);
170-
}
166+
irq_type = GPIO_INT_FALLING;
171167
break;
168+
169+
default:
170+
irq_type = 0;
171+
}
172+
173+
/* We can handle invalid/null irq type. */
174+
if (enable) {
175+
obj->irq_types |= irq_type;
176+
} else {
177+
obj->irq_types &= ~irq_type;
172178
}
179+
180+
/* Update irq types:
181+
*
182+
* Implementations of GPIO_EnableInt(...) are inconsistent: disable or not irq type not enabled.
183+
* For consistency, disable GPIO_INT_BOTH_EDGE and then enable OR'ed irq types, GPIO_INT_RISING,
184+
* GPIO_INT_FALLING, or both.
185+
*/
186+
GPIO_DisableInt(gpio_base, pin_index);
187+
GPIO_EnableInt(gpio_base, pin_index, obj->irq_types);
173188
}
174189

175190
void gpio_irq_enable(gpio_irq_t *obj)
176191
{
177192
//uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
178193
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
179194
struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index;
180-
195+
181196
NVIC_SetVector(var->irq_n, (uint32_t) var->vec);
182197
NVIC_EnableIRQ(var->irq_n);
183198
}
@@ -187,7 +202,7 @@ void gpio_irq_disable(gpio_irq_t *obj)
187202
//uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
188203
uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
189204
struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index;
190-
205+
191206
NVIC_DisableIRQ(var->irq_n);
192207
}
193208

@@ -220,7 +235,7 @@ static void gpio_irq(struct nu_gpio_irq_var *var)
220235
{
221236
uint32_t port_index = var->irq_n - GPA_IRQn;
222237
GPIO_T *gpio_base = NU_PORT_BASE(port_index);
223-
238+
224239
uint32_t intsrc = gpio_base->INTSRC;
225240
uint32_t inten = gpio_base->INTEN;
226241
while (intsrc) {
@@ -233,15 +248,15 @@ static void gpio_irq(struct nu_gpio_irq_var *var)
233248
}
234249
}
235250
}
236-
251+
237252
if (inten & (GPIO_INT_FALLING << pin_index)) {
238253
if (! GPIO_PIN_DATA(port_index, pin_index)) {
239254
if (obj->irq_handler) {
240255
((gpio_irq_handler) obj->irq_handler)(obj->irq_id, IRQ_FALL);
241256
}
242257
}
243258
}
244-
259+
245260
intsrc &= ~(1 << pin_index);
246261
}
247262
// Clear all interrupt flags

targets/TARGET_NUVOTON/TARGET_M451/objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ extern "C" {
2929

3030
struct gpio_irq_s {
3131
PinName pin;
32+
uint32_t irq_types;
3233
uint32_t irq_handler;
3334
uint32_t irq_id;
3435
};

0 commit comments

Comments
 (0)