mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
187:0387e8f68319
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
AnnaBridge 187:0387e8f68319 1 /* mbed Microcontroller Library
AnnaBridge 187:0387e8f68319 2 * Copyright (c) 2017-2018 Nuvoton
AnnaBridge 187:0387e8f68319 3 *
AnnaBridge 187:0387e8f68319 4 * Licensed under the Apache License, Version 2.0 (the "License");
AnnaBridge 187:0387e8f68319 5 * you may not use this file except in compliance with the License.
AnnaBridge 187:0387e8f68319 6 * You may obtain a copy of the License at
AnnaBridge 187:0387e8f68319 7 *
AnnaBridge 187:0387e8f68319 8 * http://www.apache.org/licenses/LICENSE-2.0
AnnaBridge 187:0387e8f68319 9 *
AnnaBridge 187:0387e8f68319 10 * Unless required by applicable law or agreed to in writing, software
AnnaBridge 187:0387e8f68319 11 * distributed under the License is distributed on an "AS IS" BASIS,
AnnaBridge 187:0387e8f68319 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
AnnaBridge 187:0387e8f68319 13 * See the License for the specific language governing permissions and
AnnaBridge 187:0387e8f68319 14 * limitations under the License.
AnnaBridge 187:0387e8f68319 15 */
AnnaBridge 187:0387e8f68319 16
AnnaBridge 187:0387e8f68319 17 #include "gpio_irq_api.h"
AnnaBridge 187:0387e8f68319 18
AnnaBridge 187:0387e8f68319 19 #if DEVICE_INTERRUPTIN
AnnaBridge 187:0387e8f68319 20
AnnaBridge 187:0387e8f68319 21 #include "gpio_api.h"
AnnaBridge 187:0387e8f68319 22 #include "cmsis.h"
AnnaBridge 187:0387e8f68319 23 #include "pinmap.h"
AnnaBridge 187:0387e8f68319 24 #include "PeripheralPins.h"
AnnaBridge 187:0387e8f68319 25 #include "nu_bitutil.h"
AnnaBridge 187:0387e8f68319 26
AnnaBridge 187:0387e8f68319 27 #define NU_MAX_PIN_PER_PORT 16
AnnaBridge 187:0387e8f68319 28
AnnaBridge 187:0387e8f68319 29 struct nu_gpio_irq_var {
AnnaBridge 187:0387e8f68319 30 gpio_irq_t * obj_arr[NU_MAX_PIN_PER_PORT];
AnnaBridge 187:0387e8f68319 31 IRQn_Type irq_n;
AnnaBridge 187:0387e8f68319 32 void (*vec)(void);
AnnaBridge 187:0387e8f68319 33 uint32_t port_index;
AnnaBridge 187:0387e8f68319 34 };
AnnaBridge 187:0387e8f68319 35
AnnaBridge 187:0387e8f68319 36 static void gpio_irq_0_vec(void);
AnnaBridge 187:0387e8f68319 37 static void gpio_irq_1_vec(void);
AnnaBridge 187:0387e8f68319 38 static void gpio_irq_2_vec(void);
AnnaBridge 187:0387e8f68319 39 static void gpio_irq_3_vec(void);
AnnaBridge 187:0387e8f68319 40 static void gpio_irq_4_vec(void);
AnnaBridge 187:0387e8f68319 41 static void gpio_irq_5_vec(void);
AnnaBridge 187:0387e8f68319 42 static void gpio_irq_6_vec(void);
AnnaBridge 187:0387e8f68319 43 static void gpio_irq(struct nu_gpio_irq_var *var);
AnnaBridge 187:0387e8f68319 44
AnnaBridge 187:0387e8f68319 45 //EINT0_IRQn
AnnaBridge 187:0387e8f68319 46 static struct nu_gpio_irq_var gpio_irq_var_arr[] = {
AnnaBridge 187:0387e8f68319 47 {{NULL}, GPA_IRQn, gpio_irq_0_vec, 0},
AnnaBridge 187:0387e8f68319 48 {{NULL}, GPB_IRQn, gpio_irq_1_vec, 1},
AnnaBridge 187:0387e8f68319 49 {{NULL}, GPC_IRQn, gpio_irq_2_vec, 2},
AnnaBridge 187:0387e8f68319 50 {{NULL}, GPD_IRQn, gpio_irq_3_vec, 3},
AnnaBridge 187:0387e8f68319 51 {{NULL}, GPE_IRQn, gpio_irq_4_vec, 4},
AnnaBridge 187:0387e8f68319 52 {{NULL}, GPF_IRQn, gpio_irq_5_vec, 5},
AnnaBridge 187:0387e8f68319 53 {{NULL}, GPG_IRQn, gpio_irq_6_vec, 6},
AnnaBridge 187:0387e8f68319 54 };
AnnaBridge 187:0387e8f68319 55
AnnaBridge 187:0387e8f68319 56 #define NU_MAX_PORT (sizeof (gpio_irq_var_arr) / sizeof (gpio_irq_var_arr[0]))
AnnaBridge 187:0387e8f68319 57
AnnaBridge 187:0387e8f68319 58 #ifndef MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE
AnnaBridge 187:0387e8f68319 59 #define MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE 0
AnnaBridge 187:0387e8f68319 60 #endif
AnnaBridge 187:0387e8f68319 61
AnnaBridge 187:0387e8f68319 62 #ifndef MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE_LIST
AnnaBridge 187:0387e8f68319 63 #define MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE_LIST NC
AnnaBridge 187:0387e8f68319 64 #endif
AnnaBridge 187:0387e8f68319 65 static PinName gpio_irq_debounce_arr[] = {
AnnaBridge 187:0387e8f68319 66 MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE_LIST
AnnaBridge 187:0387e8f68319 67 };
AnnaBridge 187:0387e8f68319 68
AnnaBridge 187:0387e8f68319 69 #ifndef MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE
AnnaBridge 187:0387e8f68319 70 #define MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE GPIO_DBCTL_DBCLKSRC_LIRC
AnnaBridge 187:0387e8f68319 71 #endif
AnnaBridge 187:0387e8f68319 72
AnnaBridge 187:0387e8f68319 73 #ifndef MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE
AnnaBridge 187:0387e8f68319 74 #define MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE GPIO_DBCTL_DBCLKSEL_16
AnnaBridge 187:0387e8f68319 75 #endif
AnnaBridge 187:0387e8f68319 76
AnnaBridge 187:0387e8f68319 77 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
AnnaBridge 187:0387e8f68319 78 {
AnnaBridge 187:0387e8f68319 79 if (pin == NC) {
AnnaBridge 187:0387e8f68319 80 return -1;
AnnaBridge 187:0387e8f68319 81 }
AnnaBridge 187:0387e8f68319 82
AnnaBridge 187:0387e8f68319 83 uint32_t pin_index = NU_PINNAME_TO_PIN(pin);
AnnaBridge 187:0387e8f68319 84 uint32_t port_index = NU_PINNAME_TO_PORT(pin);
AnnaBridge 187:0387e8f68319 85 if (pin_index >= NU_MAX_PIN_PER_PORT || port_index >= NU_MAX_PORT) {
AnnaBridge 187:0387e8f68319 86 return -1;
AnnaBridge 187:0387e8f68319 87 }
AnnaBridge 187:0387e8f68319 88
AnnaBridge 187:0387e8f68319 89 obj->pin = pin;
AnnaBridge 187:0387e8f68319 90 obj->irq_handler = (uint32_t) handler;
AnnaBridge 187:0387e8f68319 91 obj->irq_id = id;
AnnaBridge 187:0387e8f68319 92
AnnaBridge 187:0387e8f68319 93 GPIO_T *gpio_base = NU_PORT_BASE(port_index);
AnnaBridge 187:0387e8f68319 94 // NOTE: In InterruptIn constructor, gpio_irq_init() is called with gpio_init_in() which is responsible for multi-function pin setting.
AnnaBridge 187:0387e8f68319 95 // There is no need to call gpio_set() redundantly.
AnnaBridge 187:0387e8f68319 96
AnnaBridge 187:0387e8f68319 97 {
AnnaBridge 187:0387e8f68319 98 #if MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_ENABLE
AnnaBridge 187:0387e8f68319 99 // Suppress compiler warning
AnnaBridge 187:0387e8f68319 100 (void) gpio_irq_debounce_arr;
AnnaBridge 187:0387e8f68319 101
AnnaBridge 187:0387e8f68319 102 // Configure de-bounce clock source and sampling cycle time
AnnaBridge 187:0387e8f68319 103 GPIO_SET_DEBOUNCE_TIME(gpio_base, MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE, MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE);
AnnaBridge 187:0387e8f68319 104 GPIO_ENABLE_DEBOUNCE(gpio_base, 1 << pin_index);
AnnaBridge 187:0387e8f68319 105 #else
AnnaBridge 187:0387e8f68319 106 // Enable de-bounce if the pin is in the de-bounce enable list
AnnaBridge 187:0387e8f68319 107
AnnaBridge 187:0387e8f68319 108 // De-bounce defaults to disabled.
AnnaBridge 187:0387e8f68319 109 GPIO_DISABLE_DEBOUNCE(gpio_base, 1 << pin_index);
AnnaBridge 187:0387e8f68319 110
AnnaBridge 187:0387e8f68319 111 PinName *debounce_pos = gpio_irq_debounce_arr;
AnnaBridge 187:0387e8f68319 112 PinName *debounce_end = gpio_irq_debounce_arr + sizeof (gpio_irq_debounce_arr) / sizeof (gpio_irq_debounce_arr[0]);
AnnaBridge 187:0387e8f68319 113 for (; debounce_pos != debounce_end && *debounce_pos != NC; debounce_pos ++) {
AnnaBridge 187:0387e8f68319 114 uint32_t pin_index_debunce = NU_PINNAME_TO_PIN(*debounce_pos);
AnnaBridge 187:0387e8f68319 115 uint32_t port_index_debounce = NU_PINNAME_TO_PORT(*debounce_pos);
AnnaBridge 187:0387e8f68319 116
AnnaBridge 187:0387e8f68319 117 if (pin_index == pin_index_debunce &&
AnnaBridge 187:0387e8f68319 118 port_index == port_index_debounce) {
AnnaBridge 187:0387e8f68319 119 // Configure de-bounce clock source and sampling cycle time
AnnaBridge 187:0387e8f68319 120 GPIO_SET_DEBOUNCE_TIME(gpio_base, MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_CLOCK_SOURCE, MBED_CONF_TARGET_GPIO_IRQ_DEBOUNCE_SAMPLE_RATE);
AnnaBridge 187:0387e8f68319 121 GPIO_ENABLE_DEBOUNCE(gpio_base, 1 << pin_index);
AnnaBridge 187:0387e8f68319 122 break;
AnnaBridge 187:0387e8f68319 123 }
AnnaBridge 187:0387e8f68319 124 }
AnnaBridge 187:0387e8f68319 125 #endif
AnnaBridge 187:0387e8f68319 126 }
AnnaBridge 187:0387e8f68319 127
AnnaBridge 187:0387e8f68319 128 struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index;
AnnaBridge 187:0387e8f68319 129
AnnaBridge 187:0387e8f68319 130 var->obj_arr[pin_index] = obj;
AnnaBridge 187:0387e8f68319 131
AnnaBridge 187:0387e8f68319 132 // NOTE: InterruptIn requires IRQ enabled by default.
AnnaBridge 187:0387e8f68319 133 gpio_irq_enable(obj);
AnnaBridge 187:0387e8f68319 134
AnnaBridge 187:0387e8f68319 135 return 0;
AnnaBridge 187:0387e8f68319 136 }
AnnaBridge 187:0387e8f68319 137
AnnaBridge 187:0387e8f68319 138 void gpio_irq_free(gpio_irq_t *obj)
AnnaBridge 187:0387e8f68319 139 {
AnnaBridge 187:0387e8f68319 140 uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
AnnaBridge 187:0387e8f68319 141 uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
AnnaBridge 187:0387e8f68319 142 struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index;
AnnaBridge 187:0387e8f68319 143
AnnaBridge 187:0387e8f68319 144 NVIC_DisableIRQ(var->irq_n);
AnnaBridge 187:0387e8f68319 145 NU_PORT_BASE(port_index)->INTEN = 0;
AnnaBridge 187:0387e8f68319 146
AnnaBridge 187:0387e8f68319 147 MBED_ASSERT(pin_index < NU_MAX_PIN_PER_PORT);
AnnaBridge 187:0387e8f68319 148 var->obj_arr[pin_index] = NULL;
AnnaBridge 187:0387e8f68319 149 }
AnnaBridge 187:0387e8f68319 150
AnnaBridge 187:0387e8f68319 151 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
AnnaBridge 187:0387e8f68319 152 {
AnnaBridge 187:0387e8f68319 153 uint32_t pin_index = NU_PINNAME_TO_PIN(obj->pin);
AnnaBridge 187:0387e8f68319 154 uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
AnnaBridge 187:0387e8f68319 155 GPIO_T *gpio_base = NU_PORT_BASE(port_index);
AnnaBridge 187:0387e8f68319 156
AnnaBridge 187:0387e8f68319 157 switch (event) {
AnnaBridge 187:0387e8f68319 158 case IRQ_RISE:
AnnaBridge 187:0387e8f68319 159 if (enable) {
AnnaBridge 187:0387e8f68319 160 GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_RISING);
AnnaBridge 187:0387e8f68319 161 } else {
AnnaBridge 187:0387e8f68319 162 gpio_base->INTEN &= ~(GPIO_INT_RISING << pin_index);
AnnaBridge 187:0387e8f68319 163 }
AnnaBridge 187:0387e8f68319 164 break;
AnnaBridge 187:0387e8f68319 165
AnnaBridge 187:0387e8f68319 166 case IRQ_FALL:
AnnaBridge 187:0387e8f68319 167 if (enable) {
AnnaBridge 187:0387e8f68319 168 GPIO_EnableInt(gpio_base, pin_index, GPIO_INT_FALLING);
AnnaBridge 187:0387e8f68319 169 } else {
AnnaBridge 187:0387e8f68319 170 gpio_base->INTEN &= ~(GPIO_INT_FALLING << pin_index);
AnnaBridge 187:0387e8f68319 171 }
AnnaBridge 187:0387e8f68319 172 break;
AnnaBridge 187:0387e8f68319 173
AnnaBridge 187:0387e8f68319 174 case IRQ_NONE:
AnnaBridge 187:0387e8f68319 175 default:
AnnaBridge 187:0387e8f68319 176 break;
AnnaBridge 187:0387e8f68319 177 }
AnnaBridge 187:0387e8f68319 178 }
AnnaBridge 187:0387e8f68319 179
AnnaBridge 187:0387e8f68319 180 void gpio_irq_enable(gpio_irq_t *obj)
AnnaBridge 187:0387e8f68319 181 {
AnnaBridge 187:0387e8f68319 182 uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
AnnaBridge 187:0387e8f68319 183 struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index;
AnnaBridge 187:0387e8f68319 184
AnnaBridge 187:0387e8f68319 185 NVIC_SetVector(var->irq_n, (uint32_t) var->vec);
AnnaBridge 187:0387e8f68319 186 NVIC_EnableIRQ(var->irq_n);
AnnaBridge 187:0387e8f68319 187 }
AnnaBridge 187:0387e8f68319 188
AnnaBridge 187:0387e8f68319 189 void gpio_irq_disable(gpio_irq_t *obj)
AnnaBridge 187:0387e8f68319 190 {
AnnaBridge 187:0387e8f68319 191 uint32_t port_index = NU_PINNAME_TO_PORT(obj->pin);
AnnaBridge 187:0387e8f68319 192 struct nu_gpio_irq_var *var = gpio_irq_var_arr + port_index;
AnnaBridge 187:0387e8f68319 193
AnnaBridge 187:0387e8f68319 194 NVIC_DisableIRQ(var->irq_n);
AnnaBridge 187:0387e8f68319 195 }
AnnaBridge 187:0387e8f68319 196
AnnaBridge 187:0387e8f68319 197 static void gpio_irq_0_vec(void)
AnnaBridge 187:0387e8f68319 198 {
AnnaBridge 187:0387e8f68319 199 gpio_irq(gpio_irq_var_arr + 0);
AnnaBridge 187:0387e8f68319 200 }
AnnaBridge 187:0387e8f68319 201 static void gpio_irq_1_vec(void)
AnnaBridge 187:0387e8f68319 202 {
AnnaBridge 187:0387e8f68319 203 gpio_irq(gpio_irq_var_arr + 1);
AnnaBridge 187:0387e8f68319 204 }
AnnaBridge 187:0387e8f68319 205 static void gpio_irq_2_vec(void)
AnnaBridge 187:0387e8f68319 206 {
AnnaBridge 187:0387e8f68319 207 gpio_irq(gpio_irq_var_arr + 2);
AnnaBridge 187:0387e8f68319 208 }
AnnaBridge 187:0387e8f68319 209 static void gpio_irq_3_vec(void)
AnnaBridge 187:0387e8f68319 210 {
AnnaBridge 187:0387e8f68319 211 gpio_irq(gpio_irq_var_arr + 3);
AnnaBridge 187:0387e8f68319 212 }
AnnaBridge 187:0387e8f68319 213 static void gpio_irq_4_vec(void)
AnnaBridge 187:0387e8f68319 214 {
AnnaBridge 187:0387e8f68319 215 gpio_irq(gpio_irq_var_arr + 4);
AnnaBridge 187:0387e8f68319 216 }
AnnaBridge 187:0387e8f68319 217 static void gpio_irq_5_vec(void)
AnnaBridge 187:0387e8f68319 218 {
AnnaBridge 187:0387e8f68319 219 gpio_irq(gpio_irq_var_arr + 5);
AnnaBridge 187:0387e8f68319 220 }
AnnaBridge 187:0387e8f68319 221 static void gpio_irq_6_vec(void)
AnnaBridge 187:0387e8f68319 222 {
AnnaBridge 187:0387e8f68319 223 gpio_irq(gpio_irq_var_arr + 6);
AnnaBridge 187:0387e8f68319 224 }
AnnaBridge 187:0387e8f68319 225
AnnaBridge 187:0387e8f68319 226 static void gpio_irq(struct nu_gpio_irq_var *var)
AnnaBridge 187:0387e8f68319 227 {
AnnaBridge 187:0387e8f68319 228 // NOTE: GPA_IRQn, GPB_IRQn, ... are not arranged sequentially, so we cannot calculate out port_index through offset from GPA_IRQn.
AnnaBridge 187:0387e8f68319 229 // Instead, we add port_index into gpio_irq_var_arr table.
AnnaBridge 187:0387e8f68319 230 uint32_t port_index = var->port_index;
AnnaBridge 187:0387e8f68319 231 GPIO_T *gpio_base = NU_PORT_BASE(port_index);
AnnaBridge 187:0387e8f68319 232
AnnaBridge 187:0387e8f68319 233 uint32_t intsrc = gpio_base->INTSRC;
AnnaBridge 187:0387e8f68319 234 uint32_t inten = gpio_base->INTEN;
AnnaBridge 187:0387e8f68319 235 while (intsrc) {
AnnaBridge 187:0387e8f68319 236 int pin_index = nu_ctz(intsrc);
AnnaBridge 187:0387e8f68319 237 gpio_irq_t *obj = var->obj_arr[pin_index];
AnnaBridge 187:0387e8f68319 238 if (inten & (GPIO_INT_RISING << pin_index)) {
AnnaBridge 187:0387e8f68319 239 if (NU_GET_GPIO_PIN_DATA(port_index, pin_index)) {
AnnaBridge 187:0387e8f68319 240 if (obj->irq_handler) {
AnnaBridge 187:0387e8f68319 241 ((gpio_irq_handler) obj->irq_handler)(obj->irq_id, IRQ_RISE);
AnnaBridge 187:0387e8f68319 242 }
AnnaBridge 187:0387e8f68319 243 }
AnnaBridge 187:0387e8f68319 244 }
AnnaBridge 187:0387e8f68319 245
AnnaBridge 187:0387e8f68319 246 if (inten & (GPIO_INT_FALLING << pin_index)) {
AnnaBridge 187:0387e8f68319 247 if (! NU_GET_GPIO_PIN_DATA(port_index, pin_index)) {
AnnaBridge 187:0387e8f68319 248 if (obj->irq_handler) {
AnnaBridge 187:0387e8f68319 249 ((gpio_irq_handler) obj->irq_handler)(obj->irq_id, IRQ_FALL);
AnnaBridge 187:0387e8f68319 250 }
AnnaBridge 187:0387e8f68319 251 }
AnnaBridge 187:0387e8f68319 252 }
AnnaBridge 187:0387e8f68319 253
AnnaBridge 187:0387e8f68319 254 intsrc &= ~(1 << pin_index);
AnnaBridge 187:0387e8f68319 255 }
AnnaBridge 187:0387e8f68319 256 // Clear all interrupt flags
AnnaBridge 187:0387e8f68319 257 gpio_base->INTSRC = gpio_base->INTSRC;
AnnaBridge 187:0387e8f68319 258 }
AnnaBridge 187:0387e8f68319 259
AnnaBridge 187:0387e8f68319 260 #endif