fix for mbed lib issue 3 (i2c problem) see also https://mbed.org/users/mbed_official/code/mbed/issues/3 affected implementations: LPC812, LPC11U24, LPC1768, LPC2368, LPC4088

Fork of mbed-src by mbed official

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers gpio_irq_api.c Source File

gpio_irq_api.c

00001 /* mbed Microcontroller Library
00002  * Copyright (c) 2006-2013 ARM Limited
00003  *
00004  * Licensed under the Apache License, Version 2.0 (the "License");
00005  * you may not use this file except in compliance with the License.
00006  * You may obtain a copy of the License at
00007  *
00008  *     http://www.apache.org/licenses/LICENSE-2.0
00009  *
00010  * Unless required by applicable law or agreed to in writing, software
00011  * distributed under the License is distributed on an "AS IS" BASIS,
00012  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
00013  * See the License for the specific language governing permissions and
00014  * limitations under the License.
00015  */
00016 #include <stddef.h>
00017 
00018 #include "gpio_irq_api.h"
00019 #include "error.h"
00020 #include "cmsis.h"
00021 
00022 #define CHANNEL_NUM     48
00023 
00024 static uint32_t channel_ids[CHANNEL_NUM] = {0};
00025 static gpio_irq_handler irq_handler;
00026 
00027 static void handle_interrupt_in(void) {
00028     // Read in all current interrupt registers. We do this once as the
00029     // GPIO interrupt registers are on the APB bus, and this is slow.
00030     uint32_t rise0 = LPC_GPIOINT->IO0IntStatR;
00031     uint32_t fall0 = LPC_GPIOINT->IO0IntStatF;
00032     uint32_t rise2 = LPC_GPIOINT->IO2IntStatR;
00033     uint32_t fall2 = LPC_GPIOINT->IO2IntStatF;
00034     uint32_t mask0 = 0;
00035     uint32_t mask2 = 0;
00036     int i;
00037 
00038     // P0.0-0.31
00039     for (i = 0; i < 32; i++) {
00040         uint32_t pmask = (1 << i);
00041         if (rise0 & pmask) {
00042             mask0 |= pmask;
00043             if (channel_ids[i] != 0)
00044                 irq_handler(channel_ids[i], IRQ_RISE);
00045         }
00046         if (fall0 & pmask) {
00047             mask0 |= pmask;
00048             if (channel_ids[i] != 0)
00049                 irq_handler(channel_ids[i], IRQ_FALL);
00050         }
00051     }
00052     
00053     // P2.0-2.15
00054     for (i = 0; i < 16; i++) {
00055         uint32_t pmask = (1 << i);
00056         int channel_index = i + 32;
00057         if (rise2 & pmask) {
00058             mask2 |= pmask;
00059             if (channel_ids[channel_index] != 0)
00060                 irq_handler(channel_ids[channel_index], IRQ_RISE);
00061         }
00062         if (fall2 & pmask) {
00063             mask2 |= pmask;
00064             if (channel_ids[channel_index] != 0)
00065                 irq_handler(channel_ids[channel_index], IRQ_FALL);
00066         }
00067     }
00068 
00069     // Clear the interrupts we just handled
00070     LPC_GPIOINT->IO0IntClr = mask0;
00071     LPC_GPIOINT->IO2IntClr = mask2;
00072 }
00073 
00074 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
00075     if (pin == NC) return -1;
00076     
00077     irq_handler = handler;
00078     
00079     obj->port = (int)pin & ~0x1F;
00080     obj->pin = (int)pin & 0x1F;
00081     
00082     // Interrupts available only on GPIO0 and GPIO2
00083     if (obj->port != LPC_GPIO0_BASE && obj->port != LPC_GPIO2_BASE) {
00084         error("pins on this port cannot generate interrupts\n");
00085     }
00086     
00087     // put us in the interrupt table
00088     int index = (obj->port == LPC_GPIO0_BASE) ? obj->pin : obj->pin + 32;
00089     channel_ids[index] = id;
00090     obj->ch = index;
00091     
00092     NVIC_SetVector(EINT3_IRQn , (uint32_t)handle_interrupt_in);
00093     NVIC_EnableIRQ(EINT3_IRQn );
00094     return 0;
00095 }
00096 
00097 void gpio_irq_free(gpio_irq_t *obj) {
00098     channel_ids[obj->ch] = 0;
00099 }
00100 
00101 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
00102     // ensure nothing is pending
00103     switch (obj->port) {
00104          case LPC_GPIO0_BASE: LPC_GPIOINT->IO0IntClr = 1 << obj->pin; break;
00105          case LPC_GPIO2_BASE: LPC_GPIOINT->IO2IntClr = 1 << obj->pin; break;
00106     }
00107 
00108     // enable the pin interrupt
00109     if (event == IRQ_RISE) {
00110         switch (obj->port) {
00111             case LPC_GPIO0_BASE:
00112                 if (enable) {
00113                     LPC_GPIOINT->IO0IntEnR |= 1 << obj->pin;
00114                 } else {
00115                     LPC_GPIOINT->IO0IntEnR &= ~(1 << obj->pin);
00116                 }
00117                 break;
00118             case LPC_GPIO2_BASE:
00119                 if (enable) {
00120                     LPC_GPIOINT->IO2IntEnR |= 1 << obj->pin;
00121                 } else {
00122                     LPC_GPIOINT->IO2IntEnR &= ~(1 << obj->pin);
00123                 }
00124                 break;
00125         }
00126     } else {
00127         switch (obj->port) {
00128             case LPC_GPIO0_BASE:
00129                 if (enable) {
00130                     LPC_GPIOINT->IO0IntEnF |= 1 << obj->pin;
00131                 } else {
00132                     LPC_GPIOINT->IO0IntEnF &= ~(1 << obj->pin);
00133                 }
00134                 break;
00135             case LPC_GPIO2_BASE:
00136                 if (enable) {
00137                     LPC_GPIOINT->IO2IntEnF |= 1 << obj->pin;
00138                 } else {
00139                     LPC_GPIOINT->IO2IntEnF &= ~(1 << obj->pin);
00140                 }
00141                 break;
00142         }
00143     }
00144 }