Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 "cmsis.h" 00018 #include "gpio_irq_api.h" 00019 #include "error.h" 00020 00021 #define CHANNEL_NUM 8 00022 #define LPC_GPIO_X LPC_GPIO_PIN_INT 00023 #define PININT_IRQ 0 00024 00025 static uint32_t channel_ids[CHANNEL_NUM] = {0}; 00026 static gpio_irq_handler irq_handler; 00027 00028 static inline void handle_interrupt_in(uint32_t channel) { 00029 uint32_t ch_bit = (1 << channel); 00030 // Return immediately if: 00031 // * The interrupt was already served 00032 // * There is no user handler 00033 // * It is a level interrupt, not an edge interrupt 00034 if ( ((LPC_GPIO_X->IST & ch_bit) == 0) || 00035 (channel_ids[channel] == 0 ) || 00036 (LPC_GPIO_X->ISEL & ch_bit ) ) return; 00037 00038 if ((LPC_GPIO_X->IENR & ch_bit) && (LPC_GPIO_X->RISE & ch_bit)) { 00039 irq_handler(channel_ids[channel], IRQ_RISE); 00040 LPC_GPIO_X->RISE = ch_bit; 00041 } 00042 if ((LPC_GPIO_X->IENF & ch_bit) && (LPC_GPIO_X->FALL & ch_bit)) { 00043 irq_handler(channel_ids[channel], IRQ_FALL); 00044 } 00045 LPC_GPIO_X->IST = ch_bit; 00046 } 00047 00048 void gpio_irq0(void) {handle_interrupt_in(0);} 00049 void gpio_irq1(void) {handle_interrupt_in(1);} 00050 void gpio_irq2(void) {handle_interrupt_in(2);} 00051 void gpio_irq3(void) {handle_interrupt_in(3);} 00052 void gpio_irq4(void) {handle_interrupt_in(4);} 00053 void gpio_irq5(void) {handle_interrupt_in(5);} 00054 void gpio_irq6(void) {handle_interrupt_in(6);} 00055 void gpio_irq7(void) {handle_interrupt_in(7);} 00056 00057 int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) { 00058 if (pin == NC) return -1; 00059 00060 irq_handler = handler; 00061 00062 int found_free_channel = 0; 00063 int i = 0; 00064 for (i=0; i<CHANNEL_NUM; i++) { 00065 if (channel_ids[i] == 0) { 00066 channel_ids[i] = id; 00067 obj->ch = i; 00068 found_free_channel = 1; 00069 break; 00070 } 00071 } 00072 if (!found_free_channel) return -1; 00073 00074 /* Enable AHB clock to the GPIO domain. */ 00075 LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6); 00076 00077 /* Enable AHB clock to the FlexInt, GroupedInt domain. */ 00078 LPC_SYSCON->SYSAHBCLKCTRL |= ((1<<19) | (1<<23) | (1<<24)); 00079 00080 /* To select a pin for any of the eight pin interrupts, write the pin number 00081 * as 0 to 23 for pins PIO0_0 to PIO0_23 and 24 to 55. 00082 * @see: mbed_capi/PinNames.h 00083 */ 00084 LPC_SYSCON->PINTSEL[obj->ch] = (pin >> 5) ? (pin - 8) : (pin); 00085 00086 // Interrupt Wake-Up Enable 00087 LPC_SYSCON->STARTERP0 |= 1 << obj->ch; 00088 00089 void (*channels_irq)(void) = NULL; 00090 switch (obj->ch) { 00091 case 0: channels_irq = &gpio_irq0; break; 00092 case 1: channels_irq = &gpio_irq1; break; 00093 case 2: channels_irq = &gpio_irq2; break; 00094 case 3: channels_irq = &gpio_irq3; break; 00095 case 4: channels_irq = &gpio_irq4; break; 00096 case 5: channels_irq = &gpio_irq5; break; 00097 case 6: channels_irq = &gpio_irq6; break; 00098 case 7: channels_irq = &gpio_irq7; break; 00099 } 00100 NVIC_SetVector((IRQn_Type )(PININT_IRQ + obj->ch), (uint32_t)channels_irq); 00101 NVIC_EnableIRQ((IRQn_Type )(PININT_IRQ + obj->ch)); 00102 00103 return 0; 00104 } 00105 00106 void gpio_irq_free(gpio_irq_t *obj) { 00107 channel_ids[obj->ch] = 0; 00108 LPC_SYSCON->STARTERP0 &= ~(1 << obj->ch); 00109 } 00110 00111 void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { 00112 unsigned int ch_bit = (1 << obj->ch); 00113 00114 // Clear interrupt 00115 if (!(LPC_GPIO_X->ISEL & ch_bit)) 00116 LPC_GPIO_X->IST = ch_bit; 00117 00118 // Edge trigger 00119 LPC_GPIO_X->ISEL &= ~ch_bit; 00120 if (event == IRQ_RISE) { 00121 if (enable) { 00122 LPC_GPIO_X->IENR |= ch_bit; 00123 } else { 00124 LPC_GPIO_X->IENR &= ~ch_bit; 00125 } 00126 } else { 00127 if (enable) { 00128 LPC_GPIO_X->IENF |= ch_bit; 00129 } else { 00130 LPC_GPIO_X->IENF &= ~ch_bit; 00131 } 00132 } 00133 }
Generated on Tue Jul 12 2022 13:47:01 by
1.7.2
