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:
Mon Mar 10 11:30:07 2014 +0000
Revision:
113:65a335a675de
Parent:
86:26fc69fd3b6c
Child:
134:4fb64af58963
Synchronized with git revision 423ddcb86e83e2e0d599ca7106d436eb3c47e6dd

Full URL: https://github.com/mbedmicro/mbed/commit/423ddcb86e83e2e0d599ca7106d436eb3c47e6dd/

proposed change of gpio_api (new update pull request)

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"
mbed_official 113:65a335a675de 20 #include "gpio_api.h"
emilmont 10:3bc89ef62ce7 21 #include "error.h"
emilmont 10:3bc89ef62ce7 22
emilmont 10:3bc89ef62ce7 23 #define CHANNEL_NUM 64
emilmont 10:3bc89ef62ce7 24
emilmont 10:3bc89ef62ce7 25 static uint32_t channel_ids[CHANNEL_NUM] = {0};
emilmont 10:3bc89ef62ce7 26 static gpio_irq_handler irq_handler;
emilmont 10:3bc89ef62ce7 27
emilmont 10:3bc89ef62ce7 28 #define IRQ_DISABLED (0)
emilmont 10:3bc89ef62ce7 29 #define IRQ_RAISING_EDGE PORT_PCR_IRQC(9)
emilmont 10:3bc89ef62ce7 30 #define IRQ_FALLING_EDGE PORT_PCR_IRQC(10)
emilmont 10:3bc89ef62ce7 31 #define IRQ_EITHER_EDGE PORT_PCR_IRQC(11)
emilmont 10:3bc89ef62ce7 32
emilmont 10:3bc89ef62ce7 33 static void handle_interrupt_in(PORT_Type *port, int ch_base) {
emilmont 10:3bc89ef62ce7 34 uint32_t mask = 0, i;
emilmont 10:3bc89ef62ce7 35
emilmont 10:3bc89ef62ce7 36 for (i = 0; i < 32; i++) {
emilmont 10:3bc89ef62ce7 37 uint32_t pmask = (1 << i);
emilmont 10:3bc89ef62ce7 38 if (port->ISFR & pmask) {
emilmont 10:3bc89ef62ce7 39 mask |= pmask;
emilmont 10:3bc89ef62ce7 40 uint32_t id = channel_ids[ch_base + i];
mbed_official 86:26fc69fd3b6c 41 if (id == 0) {
mbed_official 86:26fc69fd3b6c 42 continue;
mbed_official 86:26fc69fd3b6c 43 }
emilmont 10:3bc89ef62ce7 44
emilmont 10:3bc89ef62ce7 45 FGPIO_Type *gpio;
emilmont 10:3bc89ef62ce7 46 gpio_irq_event event = IRQ_NONE;
emilmont 10:3bc89ef62ce7 47 switch (port->PCR[i] & PORT_PCR_IRQC_MASK) {
emilmont 10:3bc89ef62ce7 48 case IRQ_RAISING_EDGE:
emilmont 10:3bc89ef62ce7 49 event = IRQ_RISE;
emilmont 10:3bc89ef62ce7 50 break;
emilmont 10:3bc89ef62ce7 51
emilmont 10:3bc89ef62ce7 52 case IRQ_FALLING_EDGE:
emilmont 10:3bc89ef62ce7 53 event = IRQ_FALL;
emilmont 10:3bc89ef62ce7 54 break;
emilmont 10:3bc89ef62ce7 55
emilmont 10:3bc89ef62ce7 56 case IRQ_EITHER_EDGE:
emilmont 10:3bc89ef62ce7 57 gpio = (port == PORTA) ? (FPTA) : (FPTD);
emilmont 10:3bc89ef62ce7 58 event = (gpio->PDIR & pmask) ? (IRQ_RISE) : (IRQ_FALL);
emilmont 10:3bc89ef62ce7 59 break;
emilmont 10:3bc89ef62ce7 60 }
mbed_official 86:26fc69fd3b6c 61 if (event != IRQ_NONE) {
emilmont 10:3bc89ef62ce7 62 irq_handler(id, event);
mbed_official 86:26fc69fd3b6c 63 }
emilmont 10:3bc89ef62ce7 64 }
emilmont 10:3bc89ef62ce7 65 }
emilmont 10:3bc89ef62ce7 66 port->ISFR = mask;
emilmont 10:3bc89ef62ce7 67 }
emilmont 10:3bc89ef62ce7 68
emilmont 10:3bc89ef62ce7 69 void gpio_irqA(void) {handle_interrupt_in(PORTA, 0);}
emilmont 10:3bc89ef62ce7 70 void gpio_irqD(void) {handle_interrupt_in(PORTD, 32);}
emilmont 10:3bc89ef62ce7 71
emilmont 10:3bc89ef62ce7 72 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
emilmont 10:3bc89ef62ce7 73 if (pin == NC) return -1;
emilmont 10:3bc89ef62ce7 74
emilmont 10:3bc89ef62ce7 75 irq_handler = handler;
emilmont 10:3bc89ef62ce7 76
emilmont 10:3bc89ef62ce7 77 obj->port = pin >> PORT_SHIFT;
emilmont 10:3bc89ef62ce7 78 obj->pin = (pin & 0x7F) >> 2;
emilmont 10:3bc89ef62ce7 79
emilmont 10:3bc89ef62ce7 80 uint32_t ch_base, vector;
emilmont 10:3bc89ef62ce7 81 IRQn_Type irq_n;
emilmont 10:3bc89ef62ce7 82 switch (obj->port) {
emilmont 10:3bc89ef62ce7 83 case PortA:
emilmont 10:3bc89ef62ce7 84 ch_base = 0; irq_n = PORTA_IRQn; vector = (uint32_t)gpio_irqA;
emilmont 10:3bc89ef62ce7 85 break;
emilmont 10:3bc89ef62ce7 86
emilmont 10:3bc89ef62ce7 87 case PortD:
emilmont 10:3bc89ef62ce7 88 ch_base = 32; irq_n = PORTD_IRQn; vector = (uint32_t)gpio_irqD;
emilmont 10:3bc89ef62ce7 89 break;
emilmont 10:3bc89ef62ce7 90
emilmont 10:3bc89ef62ce7 91 default:
emilmont 10:3bc89ef62ce7 92 error("gpio_irq only supported on port A and D\n");
emilmont 10:3bc89ef62ce7 93 break;
emilmont 10:3bc89ef62ce7 94 }
emilmont 10:3bc89ef62ce7 95 NVIC_SetVector(irq_n, vector);
emilmont 10:3bc89ef62ce7 96 NVIC_EnableIRQ(irq_n);
emilmont 10:3bc89ef62ce7 97
emilmont 10:3bc89ef62ce7 98 obj->ch = ch_base + obj->pin;
emilmont 10:3bc89ef62ce7 99 channel_ids[obj->ch] = id;
emilmont 10:3bc89ef62ce7 100
emilmont 10:3bc89ef62ce7 101 return 0;
emilmont 10:3bc89ef62ce7 102 }
emilmont 10:3bc89ef62ce7 103
emilmont 10:3bc89ef62ce7 104 void gpio_irq_free(gpio_irq_t *obj) {
emilmont 10:3bc89ef62ce7 105 channel_ids[obj->ch] = 0;
emilmont 10:3bc89ef62ce7 106 }
emilmont 10:3bc89ef62ce7 107
emilmont 10:3bc89ef62ce7 108 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
emilmont 10:3bc89ef62ce7 109 PORT_Type *port = (PORT_Type *)(PORTA_BASE + 0x1000 * obj->port);
emilmont 10:3bc89ef62ce7 110
emilmont 10:3bc89ef62ce7 111 uint32_t irq_settings = IRQ_DISABLED;
emilmont 10:3bc89ef62ce7 112
emilmont 10:3bc89ef62ce7 113 switch (port->PCR[obj->pin] & PORT_PCR_IRQC_MASK) {
emilmont 10:3bc89ef62ce7 114 case IRQ_DISABLED:
emilmont 10:3bc89ef62ce7 115 if (enable) {
emilmont 10:3bc89ef62ce7 116 irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_FALLING_EDGE);
emilmont 10:3bc89ef62ce7 117 }
emilmont 10:3bc89ef62ce7 118 break;
emilmont 10:3bc89ef62ce7 119
emilmont 10:3bc89ef62ce7 120 case IRQ_RAISING_EDGE:
emilmont 10:3bc89ef62ce7 121 if (enable) {
emilmont 10:3bc89ef62ce7 122 irq_settings = (event == IRQ_RISE) ? (IRQ_RAISING_EDGE) : (IRQ_EITHER_EDGE);
emilmont 10:3bc89ef62ce7 123 } else {
emilmont 10:3bc89ef62ce7 124 if (event == IRQ_FALL)
emilmont 10:3bc89ef62ce7 125 irq_settings = IRQ_RAISING_EDGE;
emilmont 10:3bc89ef62ce7 126 }
emilmont 10:3bc89ef62ce7 127 break;
emilmont 10:3bc89ef62ce7 128
emilmont 10:3bc89ef62ce7 129 case IRQ_FALLING_EDGE:
emilmont 10:3bc89ef62ce7 130 if (enable) {
emilmont 10:3bc89ef62ce7 131 irq_settings = (event == IRQ_FALL) ? (IRQ_FALLING_EDGE) : (IRQ_EITHER_EDGE);
emilmont 10:3bc89ef62ce7 132 } else {
emilmont 10:3bc89ef62ce7 133 if (event == IRQ_RISE)
emilmont 10:3bc89ef62ce7 134 irq_settings = IRQ_FALLING_EDGE;
emilmont 10:3bc89ef62ce7 135 }
emilmont 10:3bc89ef62ce7 136 break;
emilmont 10:3bc89ef62ce7 137
emilmont 10:3bc89ef62ce7 138 case IRQ_EITHER_EDGE:
emilmont 10:3bc89ef62ce7 139 if (enable) {
emilmont 10:3bc89ef62ce7 140 irq_settings = IRQ_EITHER_EDGE;
emilmont 10:3bc89ef62ce7 141 } else {
emilmont 10:3bc89ef62ce7 142 irq_settings = (event == IRQ_RISE) ? (IRQ_FALLING_EDGE) : (IRQ_RAISING_EDGE);
emilmont 10:3bc89ef62ce7 143 }
emilmont 10:3bc89ef62ce7 144 break;
emilmont 10:3bc89ef62ce7 145 }
emilmont 10:3bc89ef62ce7 146
emilmont 10:3bc89ef62ce7 147 // Interrupt configuration and clear interrupt
emilmont 10:3bc89ef62ce7 148 port->PCR[obj->pin] = (port->PCR[obj->pin] & ~PORT_PCR_IRQC_MASK) | irq_settings | PORT_PCR_ISF_MASK;
emilmont 10:3bc89ef62ce7 149 }
mbed_official 35:371630885ad6 150
mbed_official 35:371630885ad6 151 void gpio_irq_enable(gpio_irq_t *obj) {
mbed_official 35:371630885ad6 152 if (obj->port == PortA) {
mbed_official 35:371630885ad6 153 NVIC_EnableIRQ(PORTA_IRQn);
mbed_official 35:371630885ad6 154 } else if (obj->port == PortD) {
mbed_official 35:371630885ad6 155 NVIC_EnableIRQ(PORTD_IRQn);
mbed_official 35:371630885ad6 156 }
mbed_official 35:371630885ad6 157 }
mbed_official 35:371630885ad6 158
mbed_official 35:371630885ad6 159 void gpio_irq_disable(gpio_irq_t *obj) {
mbed_official 35:371630885ad6 160 if (obj->port == PortA) {
mbed_official 35:371630885ad6 161 NVIC_DisableIRQ(PORTA_IRQn);
mbed_official 35:371630885ad6 162 } else if (obj->port == PortD) {
mbed_official 35:371630885ad6 163 NVIC_DisableIRQ(PORTD_IRQn);
mbed_official 35:371630885ad6 164 }
mbed_official 35:371630885ad6 165 }
mbed_official 86:26fc69fd3b6c 166
mbed_official 86:26fc69fd3b6c 167 // Change the NMI pin to an input. This allows NMI pin to
mbed_official 86:26fc69fd3b6c 168 // be used as a low power mode wakeup. The application will
mbed_official 86:26fc69fd3b6c 169 // need to change the pin back to NMI_b or wakeup only occurs once!
mbed_official 86:26fc69fd3b6c 170 void NMI_Handler(void)
mbed_official 86:26fc69fd3b6c 171 {
mbed_official 86:26fc69fd3b6c 172 gpio_t gpio;
mbed_official 113:65a335a675de 173 gpio_init_in(&gpio, PTA4);
mbed_official 86:26fc69fd3b6c 174 }