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
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 #include "gpio_irq_api.h" 00018 #include "error.h" 00019 #include "cmsis.h" 00020 00021 #define CHANNEL_NUM 64 00022 00023 static uint32_t channel_ids[CHANNEL_NUM] = {0}; 00024 static gpio_irq_handler irq_handler; 00025 00026 static void handle_interrupt_in(void) { 00027 // Read in all current interrupt registers. We do this once as the 00028 // GPIO interrupt registers are on the APB bus, and this is slow. 00029 uint32_t rise0 = LPC_GPIOINT->IO0IntStatR; 00030 uint32_t fall0 = LPC_GPIOINT->IO0IntStatF; 00031 uint32_t rise2 = LPC_GPIOINT->IO2IntStatR; 00032 uint32_t fall2 = LPC_GPIOINT->IO2IntStatF; 00033 uint32_t mask0 = 0; 00034 uint32_t mask2 = 0; 00035 int i; 00036 00037 // P0.0-0.31 00038 for (i = 0; i < 32; i++) { 00039 uint32_t pmask = (1 << i); 00040 if (rise0 & pmask) { 00041 mask0 |= pmask; 00042 if (channel_ids[i] != 0) 00043 irq_handler(channel_ids[i], IRQ_RISE); 00044 } 00045 if (fall0 & pmask) { 00046 mask0 |= pmask; 00047 if (channel_ids[i] != 0) 00048 irq_handler(channel_ids[i], IRQ_FALL); 00049 } 00050 } 00051 00052 // P2.0-2.31 00053 for (i = 0; i < 32; i++) { 00054 uint32_t pmask = (1 << i); 00055 int channel_index = i + 32; 00056 if (rise2 & pmask) { 00057 mask2 |= pmask; 00058 if (channel_ids[channel_index] != 0) 00059 irq_handler(channel_ids[channel_index], IRQ_RISE); 00060 } 00061 if (fall2 & pmask) { 00062 mask2 |= pmask; 00063 if (channel_ids[channel_index] != 0) 00064 irq_handler(channel_ids[channel_index], IRQ_FALL); 00065 } 00066 } 00067 00068 // Clear the interrupts we just handled 00069 LPC_GPIOINT->IO0IntClr = mask0; 00070 LPC_GPIOINT->IO2IntClr = mask2; 00071 } 00072 00073 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) { 00074 if (pin == NC) return -1; 00075 00076 irq_handler = handler; 00077 00078 obj->port = ((int)(LPC_GPIO0_BASE+pin) & ~0x1F); 00079 obj->pin = (int)pin % 32; 00080 00081 // Interrupts available only on GPIO0 and GPIO2 00082 if (obj->port != LPC_GPIO0_BASE && obj->port != LPC_GPIO2_BASE) { 00083 error("pins on this port cannot generate interrupts\n"); 00084 } 00085 00086 // put us in the interrupt table 00087 int index = (obj->port == LPC_GPIO0_BASE) ? obj->pin : obj->pin + 32; 00088 channel_ids[index] = id; 00089 obj->ch = index; 00090 00091 NVIC_SetVector(GPIO_IRQn , (uint32_t)handle_interrupt_in); 00092 NVIC_EnableIRQ(GPIO_IRQn ); 00093 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 }
Generated on Tue Jul 12 2022 13:47:01 by 1.7.2