BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:55:34 2018 +0000
Revision:
2:798925c9e4a8
Parent:
1:9c5af431a1f1
bluetooth

Who changed what in which revision?

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