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
175190void 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
0 commit comments