1 /* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include "gpio_irq_api.h"
17 #include "mbed_error.h"
21 #define CHANNEL_NUM 48
23 static uint32_t channel_ids
[CHANNEL_NUM
] = {0};
24 static gpio_irq_handler irq_handler
;
26 static void handle_interrupt_in(void) {
27 // Read in all current interrupt registers. We do this once as the
28 // GPIO interrupt registers are on the APB bus, and this is slow.
29 uint32_t rise0
= LPC_GPIOINT
->IO0IntStatR
;
30 uint32_t fall0
= LPC_GPIOINT
->IO0IntStatF
;
31 uint32_t rise2
= LPC_GPIOINT
->IO2IntStatR
;
32 uint32_t fall2
= LPC_GPIOINT
->IO2IntStatF
;
38 for (i
= 0; i
< 32; i
++) {
39 uint32_t pmask
= (1 << i
);
42 if (channel_ids
[i
] != 0)
43 irq_handler(channel_ids
[i
], IRQ_RISE
);
47 if (channel_ids
[i
] != 0)
48 irq_handler(channel_ids
[i
], IRQ_FALL
);
53 for (i
= 0; i
< 16; i
++) {
54 uint32_t pmask
= (1 << i
);
55 int channel_index
= i
+ 32;
58 if (channel_ids
[channel_index
] != 0)
59 irq_handler(channel_ids
[channel_index
], IRQ_RISE
);
63 if (channel_ids
[channel_index
] != 0)
64 irq_handler(channel_ids
[channel_index
], IRQ_FALL
);
68 // Clear the interrupts we just handled
69 LPC_GPIOINT
->IO0IntClr
= mask0
;
70 LPC_GPIOINT
->IO2IntClr
= mask2
;
73 int gpio_irq_init(gpio_irq_t
*obj
, PinName pin
, gpio_irq_handler handler
, uint32_t id
) {
74 if (pin
== NC
) return -1;
76 irq_handler
= handler
;
78 obj
->port
= (int)pin
& ~0x1F;
79 obj
->pin
= (int)pin
& 0x1F;
81 // Interrupts available only on GPIO0 and GPIO2
82 if (obj
->port
!= LPC_GPIO0_BASE
&& obj
->port
!= LPC_GPIO2_BASE
) {
83 error("pins on this port cannot generate interrupts");
86 // put us in the interrupt table
87 int index
= (obj
->port
== LPC_GPIO0_BASE
) ? obj
->pin
: obj
->pin
+ 32;
88 channel_ids
[index
] = id
;
91 NVIC_SetVector(EINT3_IRQn
, (uint32_t)handle_interrupt_in
);
92 NVIC_EnableIRQ(EINT3_IRQn
);
97 void gpio_irq_free(gpio_irq_t
*obj
) {
98 channel_ids
[obj
->ch
] = 0;
101 void gpio_irq_set(gpio_irq_t
*obj
, gpio_irq_event event
, uint32_t enable
) {
102 // ensure nothing is pending
104 case LPC_GPIO0_BASE
: LPC_GPIOINT
->IO0IntClr
= 1 << obj
->pin
; break;
105 case LPC_GPIO2_BASE
: LPC_GPIOINT
->IO2IntClr
= 1 << obj
->pin
; break;
108 // enable the pin interrupt
109 if (event
== IRQ_RISE
) {
113 LPC_GPIOINT
->IO0IntEnR
|= 1 << obj
->pin
;
115 LPC_GPIOINT
->IO0IntEnR
&= ~(1 << obj
->pin
);
120 LPC_GPIOINT
->IO2IntEnR
|= 1 << obj
->pin
;
122 LPC_GPIOINT
->IO2IntEnR
&= ~(1 << obj
->pin
);
130 LPC_GPIOINT
->IO0IntEnF
|= 1 << obj
->pin
;
132 LPC_GPIOINT
->IO0IntEnF
&= ~(1 << obj
->pin
);
138 LPC_GPIOINT
->IO2IntEnF
|= 1 << obj
->pin
;
140 LPC_GPIOINT
->IO2IntEnF
&= ~(1 << obj
->pin
);
147 void gpio_irq_enable(gpio_irq_t
*obj
) {
148 NVIC_EnableIRQ(EINT3_IRQn
);
151 void gpio_irq_disable(gpio_irq_t
*obj
) {
152 NVIC_DisableIRQ(EINT3_IRQn
);