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:
bogdanm
Date:
Mon Aug 19 18:17:02 2013 +0300
Revision:
19:398f4c622e1b
Child:
20:4263a77256ae
Sync with official mbed library release 66

Who changed what in which revision?

UserRevisionLine numberNew contents of line
bogdanm 19:398f4c622e1b 1 /* mbed Microcontroller Library
bogdanm 19:398f4c622e1b 2 * Copyright (c) 2006-2013 ARM Limited
bogdanm 19:398f4c622e1b 3 *
bogdanm 19:398f4c622e1b 4 * Licensed under the Apache License, Version 2.0 (the "License");
bogdanm 19:398f4c622e1b 5 * you may not use this file except in compliance with the License.
bogdanm 19:398f4c622e1b 6 * You may obtain a copy of the License at
bogdanm 19:398f4c622e1b 7 *
bogdanm 19:398f4c622e1b 8 * http://www.apache.org/licenses/LICENSE-2.0
bogdanm 19:398f4c622e1b 9 *
bogdanm 19:398f4c622e1b 10 * Unless required by applicable law or agreed to in writing, software
bogdanm 19:398f4c622e1b 11 * distributed under the License is distributed on an "AS IS" BASIS,
bogdanm 19:398f4c622e1b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
bogdanm 19:398f4c622e1b 13 * See the License for the specific language governing permissions and
bogdanm 19:398f4c622e1b 14 * limitations under the License.
bogdanm 19:398f4c622e1b 15 */
bogdanm 19:398f4c622e1b 16 #include <stddef.h>
bogdanm 19:398f4c622e1b 17 #include "cmsis.h"
bogdanm 19:398f4c622e1b 18 #include "gpio_irq_api.h"
bogdanm 19:398f4c622e1b 19 #include "error.h"
bogdanm 19:398f4c622e1b 20 #include "gpio_api.h"
bogdanm 19:398f4c622e1b 21
bogdanm 19:398f4c622e1b 22 // The chip is capable of 4 external interrupts.
bogdanm 19:398f4c622e1b 23 #define CHANNEL_NUM 4
bogdanm 19:398f4c622e1b 24
bogdanm 19:398f4c622e1b 25 static uint32_t channel_ids[CHANNEL_NUM] = {0};
bogdanm 19:398f4c622e1b 26 static gpio_irq_handler irq_handler;
bogdanm 19:398f4c622e1b 27 static PinName pin_names[CHANNEL_NUM] = {};
bogdanm 19:398f4c622e1b 28 static uint8_t trigger_events[CHANNEL_NUM] = {};
bogdanm 19:398f4c622e1b 29
bogdanm 19:398f4c622e1b 30 static inline void handle_interrupt_in(uint32_t channel) {
bogdanm 19:398f4c622e1b 31 // Find out whether the interrupt has been triggered by a high or low value...
bogdanm 19:398f4c622e1b 32 // As the LPC1114 doesn't have a specific register for this, we'll just have to read
bogdanm 19:398f4c622e1b 33 // the level of the pin as if it were just a normal input...
bogdanm 19:398f4c622e1b 34
bogdanm 19:398f4c622e1b 35 // Get the number of the pin being used and the port typedef
bogdanm 19:398f4c622e1b 36 LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (((pin_names[channel] & 0xF000) >> PORT_SHIFT) * 0x10000)));
bogdanm 19:398f4c622e1b 37 uint8_t pin_num = (pin_names[channel] & (0x0f << PIN_SHIFT)) >> PIN_SHIFT;
bogdanm 19:398f4c622e1b 38 uint8_t trigger_event = trigger_events[channel];
bogdanm 19:398f4c622e1b 39
bogdanm 19:398f4c622e1b 40 if (trigger_event == 1)
bogdanm 19:398f4c622e1b 41 irq_handler(channel_ids[channel], IRQ_RISE);
bogdanm 19:398f4c622e1b 42 else if (trigger_event == 2)
bogdanm 19:398f4c622e1b 43 irq_handler(channel_ids[channel], IRQ_FALL);
bogdanm 19:398f4c622e1b 44 else {
bogdanm 19:398f4c622e1b 45 // In order to get an idea of which kind of event it is,
bogdanm 19:398f4c622e1b 46 // We need to read the logic level of the pin...
bogdanm 19:398f4c622e1b 47
bogdanm 19:398f4c622e1b 48 uint8_t logic = (port_reg->DATA & (1 << pin_num)) >> pin_num;
bogdanm 19:398f4c622e1b 49
bogdanm 19:398f4c622e1b 50 if (logic == 1)
bogdanm 19:398f4c622e1b 51 irq_handler(channel_ids[channel], IRQ_RISE);
bogdanm 19:398f4c622e1b 52 else
bogdanm 19:398f4c622e1b 53 irq_handler(channel_ids[channel], IRQ_FALL);
bogdanm 19:398f4c622e1b 54 }
bogdanm 19:398f4c622e1b 55
bogdanm 19:398f4c622e1b 56 // Clear the interrupt...
bogdanm 19:398f4c622e1b 57 port_reg->IC |= 1 << pin_num;
bogdanm 19:398f4c622e1b 58 }
bogdanm 19:398f4c622e1b 59
bogdanm 19:398f4c622e1b 60 void gpio_irq0(void) {handle_interrupt_in(0);}
bogdanm 19:398f4c622e1b 61 void gpio_irq1(void) {handle_interrupt_in(1);}
bogdanm 19:398f4c622e1b 62 void gpio_irq2(void) {handle_interrupt_in(2);}
bogdanm 19:398f4c622e1b 63 void gpio_irq3(void) {handle_interrupt_in(3);}
bogdanm 19:398f4c622e1b 64
bogdanm 19:398f4c622e1b 65 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
bogdanm 19:398f4c622e1b 66 if (pin == NC) return -1;
bogdanm 19:398f4c622e1b 67
bogdanm 19:398f4c622e1b 68 // Firstly, we'll put some data in *obj so we can keep track of stuff.
bogdanm 19:398f4c622e1b 69 obj->pin = pin;
bogdanm 19:398f4c622e1b 70
bogdanm 19:398f4c622e1b 71 // Set the handler to be the pointer at the top...
bogdanm 19:398f4c622e1b 72 irq_handler = handler;
bogdanm 19:398f4c622e1b 73
bogdanm 19:398f4c622e1b 74 // Which port are we using?
bogdanm 19:398f4c622e1b 75 int channel;
bogdanm 19:398f4c622e1b 76 uint32_t port_reg = (LPC_GPIO0_BASE + (((pin & 0xF000) >> PORT_SHIFT) * 0x10000));
bogdanm 19:398f4c622e1b 77
bogdanm 19:398f4c622e1b 78 switch (port_reg) {
bogdanm 19:398f4c622e1b 79 case LPC_GPIO0_BASE:
bogdanm 19:398f4c622e1b 80 NVIC_SetVector(EINT0_IRQn, (uint32_t)gpio_irq0);
bogdanm 19:398f4c622e1b 81 NVIC_EnableIRQ(EINT0_IRQn);
bogdanm 19:398f4c622e1b 82 channel = 0;
bogdanm 19:398f4c622e1b 83 break;
bogdanm 19:398f4c622e1b 84 case LPC_GPIO1_BASE:
bogdanm 19:398f4c622e1b 85 NVIC_SetVector(EINT1_IRQn, (uint32_t)gpio_irq1);
bogdanm 19:398f4c622e1b 86 NVIC_EnableIRQ(EINT1_IRQn);
bogdanm 19:398f4c622e1b 87 channel = 1;
bogdanm 19:398f4c622e1b 88 break;
bogdanm 19:398f4c622e1b 89 case LPC_GPIO2_BASE:
bogdanm 19:398f4c622e1b 90 NVIC_SetVector(EINT2_IRQn, (uint32_t)gpio_irq2);
bogdanm 19:398f4c622e1b 91 NVIC_EnableIRQ(EINT2_IRQn);
bogdanm 19:398f4c622e1b 92 channel = 2;
bogdanm 19:398f4c622e1b 93 break;
bogdanm 19:398f4c622e1b 94 case LPC_GPIO3_BASE:
bogdanm 19:398f4c622e1b 95 NVIC_SetVector(EINT3_IRQn, (uint32_t)gpio_irq3);
bogdanm 19:398f4c622e1b 96 NVIC_EnableIRQ(EINT3_IRQn);
bogdanm 19:398f4c622e1b 97 channel = 3;
bogdanm 19:398f4c622e1b 98 break;
bogdanm 19:398f4c622e1b 99 default:
bogdanm 19:398f4c622e1b 100 channel = -1;
bogdanm 19:398f4c622e1b 101 error("Invalid interrupt choice.");
bogdanm 19:398f4c622e1b 102 break;
bogdanm 19:398f4c622e1b 103 }
bogdanm 19:398f4c622e1b 104
bogdanm 19:398f4c622e1b 105 channel_ids[channel] = id;
bogdanm 19:398f4c622e1b 106 pin_names[channel] = pin;
bogdanm 19:398f4c622e1b 107 obj->ch = channel;
bogdanm 19:398f4c622e1b 108 return 0;
bogdanm 19:398f4c622e1b 109 }
bogdanm 19:398f4c622e1b 110
bogdanm 19:398f4c622e1b 111 void gpio_irq_free(gpio_irq_t *obj) {
bogdanm 19:398f4c622e1b 112 channel_ids[obj->ch] = 0;
bogdanm 19:398f4c622e1b 113 }
bogdanm 19:398f4c622e1b 114
bogdanm 19:398f4c622e1b 115 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
bogdanm 19:398f4c622e1b 116 // Firstly, check if there is an existing event stored...
bogdanm 19:398f4c622e1b 117
bogdanm 19:398f4c622e1b 118 LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (((obj->pin & 0xF000) >> PORT_SHIFT) * 0x10000)));
bogdanm 19:398f4c622e1b 119
bogdanm 19:398f4c622e1b 120 // Need to get the pin number of the pin, not the value of the enum
bogdanm 19:398f4c622e1b 121 uint8_t pin_num = (obj->pin & (0x0f << PIN_SHIFT)) >> PIN_SHIFT;
bogdanm 19:398f4c622e1b 122
bogdanm 19:398f4c622e1b 123
bogdanm 19:398f4c622e1b 124 if (trigger_events[obj->ch] != 0) {
bogdanm 19:398f4c622e1b 125 // We have an event.
bogdanm 19:398f4c622e1b 126 // Enable both edge interrupts.
bogdanm 19:398f4c622e1b 127
bogdanm 19:398f4c622e1b 128 if (enable) {
bogdanm 19:398f4c622e1b 129 trigger_events[obj->ch] = 3;
bogdanm 19:398f4c622e1b 130 port_reg->IBE |= 1 << pin_num;
bogdanm 19:398f4c622e1b 131 port_reg->IE |= 1 << pin_num;
bogdanm 19:398f4c622e1b 132 }
bogdanm 19:398f4c622e1b 133 else {
bogdanm 19:398f4c622e1b 134 // These all need to be opposite, to reenable the other one.
bogdanm 19:398f4c622e1b 135 trigger_events[obj->ch] = event == IRQ_RISE ? 2 : 1;
bogdanm 19:398f4c622e1b 136
bogdanm 19:398f4c622e1b 137 port_reg->IBE &= ~(1 << pin_num);
bogdanm 19:398f4c622e1b 138
bogdanm 19:398f4c622e1b 139 if (event == IRQ_RISE)
bogdanm 19:398f4c622e1b 140 port_reg->IEV &= ~(1 << pin_num);
bogdanm 19:398f4c622e1b 141 else
bogdanm 19:398f4c622e1b 142 port_reg->IEV |= 1 << pin_num;
bogdanm 19:398f4c622e1b 143
bogdanm 19:398f4c622e1b 144 port_reg->IE |= 1 << pin_num;
bogdanm 19:398f4c622e1b 145 }
bogdanm 19:398f4c622e1b 146 }
bogdanm 19:398f4c622e1b 147 else {
bogdanm 19:398f4c622e1b 148 if (enable) {
bogdanm 19:398f4c622e1b 149 trigger_events[obj->ch] = event == IRQ_RISE ? 1 : 2;
bogdanm 19:398f4c622e1b 150 port_reg->IE |= 1 << pin_num;
bogdanm 19:398f4c622e1b 151 }
bogdanm 19:398f4c622e1b 152 // One edge
bogdanm 19:398f4c622e1b 153 port_reg->IBE &= ~(1 << pin_num);
bogdanm 19:398f4c622e1b 154 // Rising/falling?
bogdanm 19:398f4c622e1b 155 if (event == IRQ_RISE)
bogdanm 19:398f4c622e1b 156 port_reg->IEV |= 1 << pin_num;
bogdanm 19:398f4c622e1b 157 else
bogdanm 19:398f4c622e1b 158 port_reg->IEV &= ~(1 << pin_num);
bogdanm 19:398f4c622e1b 159 }
bogdanm 19:398f4c622e1b 160
bogdanm 19:398f4c622e1b 161 // Clear
bogdanm 19:398f4c622e1b 162 port_reg->IC |= 1 << pin_num;
bogdanm 19:398f4c622e1b 163
bogdanm 19:398f4c622e1b 164 // Make it edge sensitive.
bogdanm 19:398f4c622e1b 165 port_reg->IS &= ~(1 << pin_num);
bogdanm 19:398f4c622e1b 166 }