erkin yucel / mbed-os

Dependents:   BLE_file_test BLE_Blink ExternalEncoder

Committer:
elessair
Date:
Sun Oct 23 15:10:02 2016 +0000
Revision:
0:f269e3021894
Initial commit

Who changed what in which revision?

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