mbed library sources

Dependents:   Encrypted my_mbed lklk CyaSSL_DTLS_Cellular ... more

Superseded

This library was superseded by mbed-dev - https://os.mbed.com/users/mbed_official/code/mbed-dev/.

Development branch of the mbed library sources. This library is kept in synch with the latest changes from the mbed SDK and it is not guaranteed to work.

If you are looking for a stable and tested release, please import one of the official mbed library releases:

Import librarymbed

The official Mbed 2 C/C++ SDK provides the software platform and libraries to build your applications.

Committer:
mbed_official
Date:
Thu Mar 06 10:00:06 2014 +0000
Revision:
111:ae4891ca7084
Parent:
86:26fc69fd3b6c
Child:
113:65a335a675de
Synchronized with git revision 955bd9a5c9e042f1cf30bbae2a99afaab8eb4cbf

Full URL: https://github.com/mbedmicro/mbed/commit/955bd9a5c9e042f1cf30bbae2a99afaab8eb4cbf/

Who changed what in which revision?

UserRevisionLine numberNew contents of line
emilmont 10:3bc89ef62ce7 1 /* mbed Microcontroller Library
emilmont 10:3bc89ef62ce7 2 * Copyright (c) 2006-2013 ARM Limited
emilmont 10:3bc89ef62ce7 3 *
emilmont 10:3bc89ef62ce7 4 * Licensed under the Apache License, Version 2.0 (the "License");
emilmont 10:3bc89ef62ce7 5 * you may not use this file except in compliance with the License.
emilmont 10:3bc89ef62ce7 6 * You may obtain a copy of the License at
emilmont 10:3bc89ef62ce7 7 *
emilmont 10:3bc89ef62ce7 8 * http://www.apache.org/licenses/LICENSE-2.0
emilmont 10:3bc89ef62ce7 9 *
emilmont 10:3bc89ef62ce7 10 * Unless required by applicable law or agreed to in writing, software
emilmont 10:3bc89ef62ce7 11 * distributed under the License is distributed on an "AS IS" BASIS,
emilmont 10:3bc89ef62ce7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
emilmont 10:3bc89ef62ce7 13 * See the License for the specific language governing permissions and
emilmont 10:3bc89ef62ce7 14 * limitations under the License.
emilmont 10:3bc89ef62ce7 15 */
emilmont 10:3bc89ef62ce7 16 #include <stddef.h>
emilmont 10:3bc89ef62ce7 17 #include "cmsis.h"
emilmont 10:3bc89ef62ce7 18
emilmont 10:3bc89ef62ce7 19 #include "gpio_irq_api.h"
emilmont 10:3bc89ef62ce7 20 #include "error.h"
emilmont 10:3bc89ef62ce7 21
emilmont 10:3bc89ef62ce7 22 #define CHANNEL_NUM 64
emilmont 10:3bc89ef62ce7 23
emilmont 10:3bc89ef62ce7 24 static uint32_t channel_ids[CHANNEL_NUM] = {0};
emilmont 10:3bc89ef62ce7 25 static gpio_irq_handler irq_handler;
emilmont 10:3bc89ef62ce7 26
emilmont 10:3bc89ef62ce7 27 #define IRQ_DISABLED (0)
emilmont 10:3bc89ef62ce7 28 #define IRQ_RAISING_EDGE PORT_PCR_IRQC(9)
emilmont 10:3bc89ef62ce7 29 #define IRQ_FALLING_EDGE PORT_PCR_IRQC(10)
emilmont 10:3bc89ef62ce7 30 #define IRQ_EITHER_EDGE PORT_PCR_IRQC(11)
emilmont 10:3bc89ef62ce7 31
emilmont 10:3bc89ef62ce7 32 static void handle_interrupt_in(PORT_Type *port, int ch_base) {
emilmont 10:3bc89ef62ce7 33 uint32_t mask = 0, i;
emilmont 10:3bc89ef62ce7 34
emilmont 10:3bc89ef62ce7 35 for (i = 0; i < 32; i++) {
emilmont 10:3bc89ef62ce7 36 uint32_t pmask = (1 << i);
emilmont 10:3bc89ef62ce7 37 if (port->ISFR & pmask) {
emilmont 10:3bc89ef62ce7 38 mask |= pmask;
emilmont 10:3bc89ef62ce7 39 uint32_t id = channel_ids[ch_base + i];
mbed_official 86:26fc69fd3b6c 40 if (id == 0) {
mbed_official 86:26fc69fd3b6c 41 continue;
mbed_official 86:26fc69fd3b6c 42 }
emilmont 10:3bc89ef62ce7 43
emilmont 10:3bc89ef62ce7 44 FGPIO_Type *gpio;
emilmont 10:3bc89ef62ce7 45 gpio_irq_event event = IRQ_NONE;
emilmont 10:3bc89ef62ce7 46 switch (port->PCR[i] & PORT_PCR_IRQC_MASK) {
emilmont 10:3bc89ef62ce7 47 case IRQ_RAISING_EDGE:
emilmont 10:3bc89ef62ce7 48 event = IRQ_RISE;
emilmont 10:3bc89ef62ce7 49 break;
emilmont 10:3bc89ef62ce7 50
emilmont 10:3bc89ef62ce7 51 case IRQ_FALLING_EDGE:
emilmont 10:3bc89ef62ce7 52 event = IRQ_FALL;
emilmont 10:3bc89ef62ce7 53 break;
emilmont 10:3bc89ef62ce7 54
emilmont 10:3bc89ef62ce7 55 case IRQ_EITHER_EDGE:
emilmont 10:3bc89ef62ce7 56 gpio = (port == PORTA) ? (FPTA) : (FPTD);
emilmont 10:3bc89ef62ce7 57 event = (gpio->PDIR & pmask) ? (IRQ_RISE) : (IRQ_FALL);
emilmont 10:3bc89ef62ce7 58 break;
emilmont 10:3bc89ef62ce7 59 }
mbed_official 86:26fc69fd3b6c 60 if (event != IRQ_NONE) {
emilmont 10:3bc89ef62ce7 61 irq_handler(id, event);
mbed_official 86:26fc69fd3b6c 62 }
emilmont 10:3bc89ef62ce7 63 }
emilmont 10:3bc89ef62ce7 64 }
emilmont 10:3bc89ef62ce7 65 port->ISFR = mask;
emilmont 10:3bc89ef62ce7 66 }
emilmont 10:3bc89ef62ce7 67
emilmont 10:3bc89ef62ce7 68 void gpio_irqA(void) {handle_interrupt_in(PORTA, 0);}
emilmont 10:3bc89ef62ce7 69 void gpio_irqD(void) {handle_interrupt_in(PORTD, 32);}
emilmont 10:3bc89ef62ce7 70
emilmont 10:3bc89ef62ce7 71 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
emilmont 10:3bc89ef62ce7 72 if (pin == NC) return -1;
emilmont 10:3bc89ef62ce7 73
emilmont 10:3bc89ef62ce7 74 irq_handler = handler;
emilmont 10:3bc89ef62ce7 75
emilmont 10:3bc89ef62ce7 76 obj->port = pin >> PORT_SHIFT;
emilmont 10:3bc89ef62ce7 77 obj->pin = (pin & 0x7F) >> 2;
emilmont 10:3bc89ef62ce7 78
emilmont 10:3bc89ef62ce7 79 uint32_t ch_base, vector;
emilmont 10:3bc89ef62ce7 80 IRQn_Type irq_n;
emilmont 10:3bc89ef62ce7 81 switch (obj->port) {
emilmont 10:3bc89ef62ce7 82 case PortA:
emilmont 10:3bc89ef62ce7 83 ch_base = 0; irq_n = PORTA_IRQn; vector = (uint32_t)gpio_irqA;
emilmont 10:3bc89ef62ce7 84 break;
emilmont 10:3bc89ef62ce7 85
emilmont 10:3bc89ef62ce7 86 case PortD:
emilmont 10:3bc89ef62ce7 87 ch_base = 32; irq_n = PORTD_IRQn; vector = (uint32_t)gpio_irqD;
emilmont 10:3bc89ef62ce7 88 break;
emilmont 10:3bc89ef62ce7 89
emilmont 10:3bc89ef62ce7 90 default:
emilmont 10:3bc89ef62ce7 91 error("gpio_irq only supported on port A and D\n");
emilmont 10:3bc89ef62ce7 92 break;
emilmont 10:3bc89ef62ce7 93 }
emilmont 10:3bc89ef62ce7 94 NVIC_SetVector(irq_n, vector);
emilmont 10:3bc89ef62ce7 95 NVIC_EnableIRQ(irq_n);
emilmont 10:3bc89ef62ce7 96
emilmont 10:3bc89ef62ce7 97 obj->ch = ch_base + obj->pin;
emilmont 10:3bc89ef62ce7 98 channel_ids[obj->ch] = id;
emilmont 10:3bc89ef62ce7 99
emilmont 10:3bc89ef62ce7 100 return 0;
emilmont 10:3bc89ef62ce7 101 }
emilmont 10:3bc89ef62ce7 102
emilmont 10:3bc89ef62ce7 103 void gpio_irq_free(gpio_irq_t *obj) {
emilmont 10:3bc89ef62ce7 104 channel_ids[obj->ch] = 0;
emilmont 10:3bc89ef62ce7 105 }
emilmont 10:3bc89ef62ce7 106
emilmont 10:3bc89ef62ce7 107 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
emilmont 10:3bc89ef62ce7 108 PORT_Type *port = (PORT_Type *)(PORTA_BASE + 0x1000 * obj->port);
emilmont 10:3bc89ef62ce7 109
emilmont 10:3bc89ef62ce7 110 uint32_t irq_settings = IRQ_DISABLED;
emilmont 10:3bc89ef62ce7 111
emilmont 10:3bc89ef62ce7 112 switch (port->PCR[obj->pin] & PORT_PCR_IRQC_MASK) {
emilmont 10:3bc89ef62ce7 113 case IRQ_DISABLED:
emilmont 10:3bc89ef62ce7 114 if (enable) {
emilmont 10:3bc89ef62ce7 115 irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_FALLING_EDGE);
emilmont 10:3bc89ef62ce7 116 }
emilmont 10:3bc89ef62ce7 117 break;
emilmont 10:3bc89ef62ce7 118
emilmont 10:3bc89ef62ce7 119 case IRQ_RAISING_EDGE:
emilmont 10:3bc89ef62ce7 120 if (enable) {
emilmont 10:3bc89ef62ce7 121 irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_EITHER_EDGE);
emilmont 10:3bc89ef62ce7 122 } else {
emilmont 10:3bc89ef62ce7 123 if (event == IRQ_FALL)
emilmont 10:3bc89ef62ce7 124 irq_settings = IRQ_RAISING_EDGE;
emilmont 10:3bc89ef62ce7 125 }
emilmont 10:3bc89ef62ce7 126 break;
emilmont 10:3bc89ef62ce7 127
emilmont 10:3bc89ef62ce7 128 case IRQ_FALLING_EDGE:
emilmont 10:3bc89ef62ce7 129 if (enable) {
emilmont 10:3bc89ef62ce7 130 irq_settings = (event == IRQ_FALL) ? (IRQ_FALLING_EDGE) : (IRQ_EITHER_EDGE);
emilmont 10:3bc89ef62ce7 131 } else {
emilmont 10:3bc89ef62ce7 132 if (event == IRQ_RISE)
emilmont 10:3bc89ef62ce7 133 irq_settings = IRQ_FALLING_EDGE;
emilmont 10:3bc89ef62ce7 134 }
emilmont 10:3bc89ef62ce7 135 break;
emilmont 10:3bc89ef62ce7 136
emilmont 10:3bc89ef62ce7 137 case IRQ_EITHER_EDGE:
emilmont 10:3bc89ef62ce7 138 if (enable) {
emilmont 10:3bc89ef62ce7 139 irq_settings = IRQ_EITHER_EDGE;
emilmont 10:3bc89ef62ce7 140 } else {
emilmont 10:3bc89ef62ce7 141 irq_settings = (event == IRQ_RISE) ? (IRQ_FALLING_EDGE) : (IRQ_RAISING_EDGE);
emilmont 10:3bc89ef62ce7 142 }
emilmont 10:3bc89ef62ce7 143 break;
emilmont 10:3bc89ef62ce7 144 }
emilmont 10:3bc89ef62ce7 145
emilmont 10:3bc89ef62ce7 146 // Interrupt configuration and clear interrupt
emilmont 10:3bc89ef62ce7 147 port->PCR[obj->pin] = (port->PCR[obj->pin] & ~PORT_PCR_IRQC_MASK) | irq_settings | PORT_PCR_ISF_MASK;
emilmont 10:3bc89ef62ce7 148 }
mbed_official 35:371630885ad6 149
mbed_official 35:371630885ad6 150 void gpio_irq_enable(gpio_irq_t *obj) {
mbed_official 35:371630885ad6 151 if (obj->port == PortA) {
mbed_official 35:371630885ad6 152 NVIC_EnableIRQ(PORTA_IRQn);
mbed_official 35:371630885ad6 153 } else if (obj->port == PortD) {
mbed_official 35:371630885ad6 154 NVIC_EnableIRQ(PORTD_IRQn);
mbed_official 35:371630885ad6 155 }
mbed_official 35:371630885ad6 156 }
mbed_official 35:371630885ad6 157
mbed_official 35:371630885ad6 158 void gpio_irq_disable(gpio_irq_t *obj) {
mbed_official 35:371630885ad6 159 if (obj->port == PortA) {
mbed_official 35:371630885ad6 160 NVIC_DisableIRQ(PORTA_IRQn);
mbed_official 35:371630885ad6 161 } else if (obj->port == PortD) {
mbed_official 35:371630885ad6 162 NVIC_DisableIRQ(PORTD_IRQn);
mbed_official 35:371630885ad6 163 }
mbed_official 35:371630885ad6 164 }
mbed_official 86:26fc69fd3b6c 165
mbed_official 86:26fc69fd3b6c 166 // Change the NMI pin to an input. This allows NMI pin to
mbed_official 86:26fc69fd3b6c 167 // be used as a low power mode wakeup. The application will
mbed_official 86:26fc69fd3b6c 168 // need to change the pin back to NMI_b or wakeup only occurs once!
mbed_official 86:26fc69fd3b6c 169 extern void gpio_init(gpio_t *obj, PinName pin, PinDirection direction);
mbed_official 86:26fc69fd3b6c 170 void NMI_Handler(void)
mbed_official 86:26fc69fd3b6c 171 {
mbed_official 86:26fc69fd3b6c 172 gpio_t gpio;
mbed_official 86:26fc69fd3b6c 173 gpio_init(&gpio, PTA4, PIN_INPUT);
mbed_official 86:26fc69fd3b6c 174 }