Alessandro Angelino / target-freescale-ksdk

Fork of target-freescale-ksdk by Morpheus

Committer:
Alessandro Angelino
Date:
Mon Apr 04 14:18:16 2016 +0100
Revision:
1:d01108809007
Parent:
0:e4d670b91a9a
Replace NVIC APIs with vIRQ ones

Who changed what in which revision?

UserRevisionLine numberNew contents of line
screamer 0:e4d670b91a9a 1 /* mbed Microcontroller Library
screamer 0:e4d670b91a9a 2 * Copyright (c) 2006-2013 ARM Limited
screamer 0:e4d670b91a9a 3 *
screamer 0:e4d670b91a9a 4 * Licensed under the Apache License, Version 2.0 (the "License");
screamer 0:e4d670b91a9a 5 * you may not use this file except in compliance with the License.
screamer 0:e4d670b91a9a 6 * You may obtain a copy of the License at
screamer 0:e4d670b91a9a 7 *
screamer 0:e4d670b91a9a 8 * http://www.apache.org/licenses/LICENSE-2.0
screamer 0:e4d670b91a9a 9 *
screamer 0:e4d670b91a9a 10 * Unless required by applicable law or agreed to in writing, software
screamer 0:e4d670b91a9a 11 * distributed under the License is distributed on an "AS IS" BASIS,
screamer 0:e4d670b91a9a 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
screamer 0:e4d670b91a9a 13 * See the License for the specific language governing permissions and
screamer 0:e4d670b91a9a 14 * limitations under the License.
screamer 0:e4d670b91a9a 15 */
screamer 0:e4d670b91a9a 16 #include <stddef.h>
screamer 0:e4d670b91a9a 17 #include "cmsis.h"
screamer 0:e4d670b91a9a 18
screamer 0:e4d670b91a9a 19 #include "gpio_irq_api.h"
screamer 0:e4d670b91a9a 20
screamer 0:e4d670b91a9a 21 #if DEVICE_INTERRUPTIN
screamer 0:e4d670b91a9a 22
screamer 0:e4d670b91a9a 23 #include "gpio_api.h"
screamer 0:e4d670b91a9a 24 #include "fsl_gpio_hal.h"
screamer 0:e4d670b91a9a 25 #include "fsl_port_hal.h"
screamer 0:e4d670b91a9a 26 #include "mbed_error.h"
screamer 0:e4d670b91a9a 27
screamer 0:e4d670b91a9a 28 #define CHANNEL_NUM 160
screamer 0:e4d670b91a9a 29
screamer 0:e4d670b91a9a 30 static uint32_t channel_ids[CHANNEL_NUM] = {0};
screamer 0:e4d670b91a9a 31 static gpio_irq_handler irq_handler;
screamer 0:e4d670b91a9a 32
screamer 0:e4d670b91a9a 33 #define IRQ_DISABLED (0)
screamer 0:e4d670b91a9a 34 #define IRQ_RAISING_EDGE (9)
screamer 0:e4d670b91a9a 35 #define IRQ_FALLING_EDGE (10)
screamer 0:e4d670b91a9a 36 #define IRQ_EITHER_EDGE (11)
screamer 0:e4d670b91a9a 37
screamer 0:e4d670b91a9a 38 static void handle_interrupt_in(PortName port, int ch_base) {
screamer 0:e4d670b91a9a 39 uint32_t i;
screamer 0:e4d670b91a9a 40 uint32_t port_addrs[] = PORT_BASE_ADDRS;
screamer 0:e4d670b91a9a 41
screamer 0:e4d670b91a9a 42 for (i = 0; i < 32; i++) {
screamer 0:e4d670b91a9a 43 if (PORT_HAL_IsPinIntPending(port_addrs[port], i)) {
screamer 0:e4d670b91a9a 44 uint32_t id = channel_ids[ch_base + i];
screamer 0:e4d670b91a9a 45 if (id == 0) {
screamer 0:e4d670b91a9a 46 continue;
screamer 0:e4d670b91a9a 47 }
screamer 0:e4d670b91a9a 48
screamer 0:e4d670b91a9a 49 gpio_irq_event event = IRQ_NONE;
screamer 0:e4d670b91a9a 50 uint32_t gpio_addrs[] = GPIO_BASE_ADDRS;
screamer 0:e4d670b91a9a 51 switch (BR_PORT_PCRn_IRQC(port_addrs[port], i)) {
screamer 0:e4d670b91a9a 52 case IRQ_RAISING_EDGE:
screamer 0:e4d670b91a9a 53 event = IRQ_RISE;
screamer 0:e4d670b91a9a 54 break;
screamer 0:e4d670b91a9a 55
screamer 0:e4d670b91a9a 56 case IRQ_FALLING_EDGE:
screamer 0:e4d670b91a9a 57 event = IRQ_FALL;
screamer 0:e4d670b91a9a 58 break;
screamer 0:e4d670b91a9a 59
screamer 0:e4d670b91a9a 60 case IRQ_EITHER_EDGE:
screamer 0:e4d670b91a9a 61 event = (GPIO_HAL_ReadPinInput(gpio_addrs[port], i)) ? (IRQ_RISE) : (IRQ_FALL);
screamer 0:e4d670b91a9a 62 break;
screamer 0:e4d670b91a9a 63 }
screamer 0:e4d670b91a9a 64 if (event != IRQ_NONE) {
screamer 0:e4d670b91a9a 65 irq_handler(id, event);
screamer 0:e4d670b91a9a 66 }
screamer 0:e4d670b91a9a 67 }
screamer 0:e4d670b91a9a 68 }
screamer 0:e4d670b91a9a 69 PORT_HAL_ClearPortIntFlag(port_addrs[port]);
screamer 0:e4d670b91a9a 70 }
screamer 0:e4d670b91a9a 71
screamer 0:e4d670b91a9a 72 void gpio_irqA(void) {handle_interrupt_in(PortA, 0);}
screamer 0:e4d670b91a9a 73 void gpio_irqB(void) {handle_interrupt_in(PortB, 32);}
screamer 0:e4d670b91a9a 74 void gpio_irqC(void) {handle_interrupt_in(PortC, 64);}
screamer 0:e4d670b91a9a 75 void gpio_irqD(void) {handle_interrupt_in(PortD, 96);}
screamer 0:e4d670b91a9a 76 void gpio_irqE(void) {handle_interrupt_in(PortE, 128);}
screamer 0:e4d670b91a9a 77
screamer 0:e4d670b91a9a 78 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
screamer 0:e4d670b91a9a 79 if (pin == NC) {
screamer 0:e4d670b91a9a 80 return -1;
screamer 0:e4d670b91a9a 81 }
screamer 0:e4d670b91a9a 82
screamer 0:e4d670b91a9a 83 irq_handler = handler;
screamer 0:e4d670b91a9a 84 obj->port = pin >> GPIO_PORT_SHIFT;
screamer 0:e4d670b91a9a 85 obj->pin = pin & 0x7F;
screamer 0:e4d670b91a9a 86
screamer 0:e4d670b91a9a 87 uint32_t ch_base = 0;
screamer 0:e4d670b91a9a 88 uint32_t vector = (uint32_t)gpio_irqA;
screamer 0:e4d670b91a9a 89 IRQn_Type irq_n = PORTA_IRQn;
screamer 0:e4d670b91a9a 90 switch (obj->port) {
screamer 0:e4d670b91a9a 91 case PortA:
screamer 0:e4d670b91a9a 92 ch_base = 0;
screamer 0:e4d670b91a9a 93 irq_n = PORTA_IRQn;
screamer 0:e4d670b91a9a 94 vector = (uint32_t)gpio_irqA;
screamer 0:e4d670b91a9a 95 break;
screamer 0:e4d670b91a9a 96 case PortB:
screamer 0:e4d670b91a9a 97 ch_base = 32;
screamer 0:e4d670b91a9a 98 irq_n = PORTB_IRQn;
screamer 0:e4d670b91a9a 99 vector = (uint32_t)gpio_irqB;
screamer 0:e4d670b91a9a 100 break;
screamer 0:e4d670b91a9a 101 case PortC:
screamer 0:e4d670b91a9a 102 ch_base = 64;
screamer 0:e4d670b91a9a 103 irq_n = PORTC_IRQn;
screamer 0:e4d670b91a9a 104 vector = (uint32_t)gpio_irqC;
screamer 0:e4d670b91a9a 105 break;
screamer 0:e4d670b91a9a 106 case PortD:
screamer 0:e4d670b91a9a 107 ch_base = 96;
screamer 0:e4d670b91a9a 108 irq_n = PORTD_IRQn;
screamer 0:e4d670b91a9a 109 vector = (uint32_t)gpio_irqD;
screamer 0:e4d670b91a9a 110 break;
screamer 0:e4d670b91a9a 111 case PortE:
screamer 0:e4d670b91a9a 112 ch_base = 128;
screamer 0:e4d670b91a9a 113 irq_n = PORTE_IRQn;
screamer 0:e4d670b91a9a 114 vector = (uint32_t)gpio_irqE;
screamer 0:e4d670b91a9a 115 break;
screamer 0:e4d670b91a9a 116
screamer 0:e4d670b91a9a 117 default:
screamer 0:e4d670b91a9a 118 error("gpio_irq only supported on port A-E.");
screamer 0:e4d670b91a9a 119 break;
screamer 0:e4d670b91a9a 120 }
Alessandro Angelino 1:d01108809007 121 vIRQ_SetVector(irq_n, vector);
Alessandro Angelino 1:d01108809007 122 vIRQ_EnableIRQ(irq_n);
screamer 0:e4d670b91a9a 123
screamer 0:e4d670b91a9a 124 obj->ch = ch_base + obj->pin;
screamer 0:e4d670b91a9a 125 channel_ids[obj->ch] = id;
screamer 0:e4d670b91a9a 126
screamer 0:e4d670b91a9a 127 return 0;
screamer 0:e4d670b91a9a 128 }
screamer 0:e4d670b91a9a 129
screamer 0:e4d670b91a9a 130 void gpio_irq_free(gpio_irq_t *obj) {
screamer 0:e4d670b91a9a 131 channel_ids[obj->ch] = 0;
screamer 0:e4d670b91a9a 132 }
screamer 0:e4d670b91a9a 133
screamer 0:e4d670b91a9a 134 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
screamer 0:e4d670b91a9a 135 uint32_t port_addrs[] = PORT_BASE_ADDRS;
screamer 0:e4d670b91a9a 136 port_interrupt_config_t irq_settings = kPortIntDisabled;
screamer 0:e4d670b91a9a 137
screamer 0:e4d670b91a9a 138 switch (BR_PORT_PCRn_IRQC(port_addrs[obj->port], obj->pin)) {
screamer 0:e4d670b91a9a 139 case IRQ_DISABLED:
screamer 0:e4d670b91a9a 140 if (enable)
screamer 0:e4d670b91a9a 141 irq_settings = (event == IRQ_RISE) ? (kPortIntRisingEdge) : (kPortIntFallingEdge);
screamer 0:e4d670b91a9a 142 break;
screamer 0:e4d670b91a9a 143
screamer 0:e4d670b91a9a 144 case IRQ_RAISING_EDGE:
screamer 0:e4d670b91a9a 145 if (enable) {
screamer 0:e4d670b91a9a 146 irq_settings = (event == IRQ_RISE) ? (kPortIntRisingEdge) : (kPortIntEitherEdge);
screamer 0:e4d670b91a9a 147 } else {
screamer 0:e4d670b91a9a 148 if (event == IRQ_FALL)
screamer 0:e4d670b91a9a 149 irq_settings = kPortIntRisingEdge;
screamer 0:e4d670b91a9a 150 }
screamer 0:e4d670b91a9a 151 break;
screamer 0:e4d670b91a9a 152
screamer 0:e4d670b91a9a 153 case IRQ_FALLING_EDGE:
screamer 0:e4d670b91a9a 154 if (enable) {
screamer 0:e4d670b91a9a 155 irq_settings = (event == IRQ_FALL) ? (kPortIntFallingEdge) : (kPortIntEitherEdge);
screamer 0:e4d670b91a9a 156 } else {
screamer 0:e4d670b91a9a 157 if (event == IRQ_RISE)
screamer 0:e4d670b91a9a 158 irq_settings = kPortIntFallingEdge;
screamer 0:e4d670b91a9a 159 }
screamer 0:e4d670b91a9a 160 break;
screamer 0:e4d670b91a9a 161
screamer 0:e4d670b91a9a 162 case IRQ_EITHER_EDGE:
screamer 0:e4d670b91a9a 163 if (enable) {
screamer 0:e4d670b91a9a 164 irq_settings = kPortIntEitherEdge;
screamer 0:e4d670b91a9a 165 } else {
screamer 0:e4d670b91a9a 166 irq_settings = (event == IRQ_RISE) ? (kPortIntFallingEdge) : (kPortIntRisingEdge);
screamer 0:e4d670b91a9a 167 }
screamer 0:e4d670b91a9a 168 break;
screamer 0:e4d670b91a9a 169 }
screamer 0:e4d670b91a9a 170
screamer 0:e4d670b91a9a 171 PORT_HAL_SetPinIntMode(port_addrs[obj->port], obj->pin, irq_settings);
screamer 0:e4d670b91a9a 172 PORT_HAL_ClearPinIntFlag(port_addrs[obj->port], obj->pin);
screamer 0:e4d670b91a9a 173 }
screamer 0:e4d670b91a9a 174
screamer 0:e4d670b91a9a 175 void gpio_irq_enable(gpio_irq_t *obj) {
screamer 0:e4d670b91a9a 176 switch (obj->port) {
screamer 0:e4d670b91a9a 177 case PortA:
Alessandro Angelino 1:d01108809007 178 vIRQ_EnableIRQ(PORTA_IRQn);
screamer 0:e4d670b91a9a 179 break;
screamer 0:e4d670b91a9a 180 case PortB:
Alessandro Angelino 1:d01108809007 181 vIRQ_EnableIRQ(PORTB_IRQn);
screamer 0:e4d670b91a9a 182 break;
screamer 0:e4d670b91a9a 183 case PortC:
Alessandro Angelino 1:d01108809007 184 vIRQ_EnableIRQ(PORTC_IRQn);
screamer 0:e4d670b91a9a 185 break;
screamer 0:e4d670b91a9a 186 case PortD:
Alessandro Angelino 1:d01108809007 187 vIRQ_EnableIRQ(PORTD_IRQn);
screamer 0:e4d670b91a9a 188 break;
screamer 0:e4d670b91a9a 189 case PortE:
Alessandro Angelino 1:d01108809007 190 vIRQ_EnableIRQ(PORTE_IRQn);
screamer 0:e4d670b91a9a 191 break;
screamer 0:e4d670b91a9a 192 }
screamer 0:e4d670b91a9a 193 }
screamer 0:e4d670b91a9a 194
screamer 0:e4d670b91a9a 195 void gpio_irq_disable(gpio_irq_t *obj) {
screamer 0:e4d670b91a9a 196 switch (obj->port) {
screamer 0:e4d670b91a9a 197 case PortA:
Alessandro Angelino 1:d01108809007 198 vIRQ_DisableIRQ(PORTA_IRQn);
screamer 0:e4d670b91a9a 199 break;
screamer 0:e4d670b91a9a 200 case PortB:
Alessandro Angelino 1:d01108809007 201 vIRQ_DisableIRQ(PORTB_IRQn);
screamer 0:e4d670b91a9a 202 break;
screamer 0:e4d670b91a9a 203 case PortC:
Alessandro Angelino 1:d01108809007 204 vIRQ_DisableIRQ(PORTC_IRQn);
screamer 0:e4d670b91a9a 205 break;
screamer 0:e4d670b91a9a 206 case PortD:
Alessandro Angelino 1:d01108809007 207 vIRQ_DisableIRQ(PORTD_IRQn);
screamer 0:e4d670b91a9a 208 break;
screamer 0:e4d670b91a9a 209 case PortE:
Alessandro Angelino 1:d01108809007 210 vIRQ_DisableIRQ(PORTE_IRQn);
screamer 0:e4d670b91a9a 211 break;
screamer 0:e4d670b91a9a 212 }
screamer 0:e4d670b91a9a 213 }
screamer 0:e4d670b91a9a 214
screamer 0:e4d670b91a9a 215 #endif