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 Oct 21 11:45:04 2013 +0100
Revision:
35:371630885ad6
Parent:
20:4263a77256ae
Synchronized with git revision 38eb79e9cce7811dee9a4d2b30c4bba468323393

Who changed what in which revision?

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