Skip to content

Commit 17678d2

Browse files
committed
Merge remote-tracking branch 'origin/gpiointerrupts'
2 parents 04a368c + 55f91f1 commit 17678d2

File tree

2 files changed

+76
-78
lines changed

2 files changed

+76
-78
lines changed

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/gpio_irq_api.c

Lines changed: 75 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -18,34 +18,33 @@
1818
#include "gpio_irq_api.h"
1919
#include "error.h"
2020

21+
// The chip is capable of 4 external interrupts.
2122
#define CHANNEL_NUM 4
22-
#define PININT_IRQ 28+3
2323

2424
static uint32_t channel_ids[CHANNEL_NUM] = {0};
2525
static gpio_irq_handler irq_handler;
26-
#warning TODO(@toyowata): need implimentation
27-
#if 0
28-
static inline void handle_interrupt_in(uint32_t channel) {
29-
uint32_t ch_bit = (1 << channel);
26+
static int channel = 0;
27+
static PinName pin_names[CHANNEL_NUM] = {};
3028

31-
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) LPC_GPIO0_BASE + (channel * 0x10000));
29+
static inline void handle_interrupt_in(uint32_t channel) {
30+
// Find out whether the interrupt has been triggered by a high or low value...
31+
// As the LPC1114 doesn't have a specific register for this, we'll just have to read
32+
// the level of the pin as if it were just a normal input...
3233

33-
// Return immediately if:
34-
// * The interrupt was already served
35-
// * There is no user handler
36-
// * It is a level interrupt, not an edge interrupt
37-
if ( ((&port_reg->IST & ch_bit) == 0) ||
38-
(channel_ids[channel] == 0 ) ||
39-
(&port_reg->ISEL & ch_bit ) ) return;
34+
// Get the number of the pin being used and the port typedef
35+
uint32_t pin = (pin_names[channel] & (0x0f << 8)) >> 8;
36+
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (((pin & 0xF000) >> PORT_SHIFT) * 0x10000)));
37+
uint32_t logiclevel = port_reg->DATA;
38+
logiclevel &= (uint32_t)(1 << pin) >> pin;
4039

41-
if ((&port_reg->IENR & ch_bit) && (&port_reg->RISE & ch_bit)) {
40+
if (logiclevel == 1) {
41+
// High, therefore rising edge...
4242
irq_handler(channel_ids[channel], IRQ_RISE);
43-
&port_reg->RISE = ch_bit;
4443
}
45-
if ((&port_reg->IENF & ch_bit) && (&port_reg->FALL & ch_bit)) {
44+
else {
45+
// Low, therefore falling edge...
4646
irq_handler(channel_ids[channel], IRQ_FALL);
4747
}
48-
&port_reg->IST = ch_bit;
4948
}
5049

5150
void gpio_irq0(void) {handle_interrupt_in(0);}
@@ -56,77 +55,75 @@ void gpio_irq3(void) {handle_interrupt_in(3);}
5655
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
5756
if (pin == NC) return -1;
5857

59-
irq_handler = handler;
60-
61-
int found_free_channel = 0;
62-
int i = 0;
63-
for (i=0; i<CHANNEL_NUM; i++) {
64-
if (channel_ids[i] == 0) {
65-
channel_ids[i] = id;
66-
obj->ch = i;
67-
found_free_channel = 1;
68-
break;
58+
// Firstly, we'll put some data in *obj so we can keep track of stuff.
59+
obj->pin = pin;
60+
61+
/*
62+
If there are any ports or pins that aren't able to handle interrupts, put them here and uncomment.
63+
64+
if (pin == ... ||
65+
pin == ...) {
66+
error("This pin does not suppor interrupts.");
67+
return -1;
6968
}
69+
*/
70+
71+
channel_ids[channel] = id;
72+
pin_names[channel] = pin;
73+
obj->ch = channel;
74+
75+
// Which port are we using?
76+
switch (channel) {
77+
case 0:
78+
NVIC_SetVector(EINT0_IRQn, (uint32_t)gpio_irq0);
79+
NVIC_EnableIRQ(EINT0_IRQn);
80+
break;
81+
case 1:
82+
NVIC_SetVector(EINT1_IRQn, (uint32_t)gpio_irq1);
83+
NVIC_EnableIRQ(EINT1_IRQn);
84+
break;
85+
case 2:
86+
NVIC_SetVector(EINT2_IRQn, (uint32_t)gpio_irq2);
87+
NVIC_EnableIRQ(EINT2_IRQn);
88+
break;
89+
case 3:
90+
NVIC_SetVector(EINT3_IRQn, (uint32_t)gpio_irq3);
91+
NVIC_EnableIRQ(EINT3_IRQn);
92+
break;
7093
}
71-
if (!found_free_channel) return -1;
72-
73-
/* Enable AHB clock to the GPIO domain. */
74-
LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);
75-
76-
/* Enable AHB clock to the FlexInt, GroupedInt domain. */
77-
LPC_SYSCON->SYSAHBCLKCTRL |= ((1<<19) | (1<<23) | (1<<24));
78-
79-
/* To select a pin for any of the eight pin interrupts, write the pin number
80-
* as 0 to 23 for pins PIO0_0 to PIO0_23 and 24 to 55.
81-
* @see: mbed_capi/PinNames.h
82-
*/
83-
LPC_SYSCON->PINTSEL[obj->ch] = (pin >> 5) ? (pin - 8) : (pin);
84-
85-
// Interrupt Wake-Up Enable
86-
LPC_SYSCON->STARTERP0 |= 1 << obj->ch;
87-
88-
void (*channels_irq)(void) = NULL;
89-
switch (obj->ch) {
90-
case 0: channels_irq = &gpio_irq0; break;
91-
case 1: channels_irq = &gpio_irq1; break;
92-
case 2: channels_irq = &gpio_irq2; break;
93-
case 3: channels_irq = &gpio_irq3; break;
94-
}
95-
NVIC_SetVector((IRQn_Type)(PININT_IRQ - obj->ch)), (uint32_t)channels_irq);
96-
NVIC_EnableIRQ((IRQn_Type)(PININT_IRQ - obj->ch));
97-
94+
95+
channel++;
9896
return 0;
9997
}
10098

10199
void gpio_irq_free(gpio_irq_t *obj) {
102100
channel_ids[obj->ch] = 0;
103-
LPC_SYSCON->STARTERP0 &= ~(1 << obj->ch);
104101
}
105102

106103
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
107-
unsigned int ch_bit = (1 << obj->ch);
108-
109-
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) LPC_GPIO0_BASE + (obj->ch * 0x10000));
104+
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (((obj->pin & 0xF000) >> PORT_SHIFT) * 0x10000)));
110105

111-
// Clear interrupt
112-
if (!(&port_reg->ISEL & ch_bit))
113-
&port_reg->IST = ch_bit;
106+
/*
107+
Firstly, clear the interrupts for this pin,
108+
Then, let the registers know whether we're looking for edge detection,
109+
Enable the interrupt,
110+
And set it to only respond to interrupts on one edge.
111+
*/
114112

115-
// Edge trigger
116-
&port_reg->ISEL &= ~ch_bit;
117-
if (event == IRQ_RISE) {
118-
if (enable) {
119-
&port_reg->IENR |= ch_bit;
120-
} else {
121-
&port_reg->IENR &= ~ch_bit;
122-
}
123-
} else {
124-
if (enable) {
125-
&port_reg->IENF |= ch_bit;
126-
} else {
127-
&port_reg->IENF &= ~ch_bit;
128-
}
129-
}
113+
// Clear
114+
port_reg->IC |= 1 << obj->pin;
115+
116+
// Edge
117+
port_reg->IS &= ~(1 << obj->pin);
118+
119+
// Enable
120+
if (enable) port_reg->IE |= 1 << obj->pin;
121+
else port_reg->IE &= ~(1 << obj->pin);
122+
123+
// One edge
124+
port_reg->IBE &= ~(1 << obj->pin);
125+
126+
// Rising/falling?
127+
if (event == IRQ_RISE) port_reg->IEV |= 1 << obj->pin;
128+
else port_reg->IEV &= ~(1 << obj->pin);
130129
}
131-
132-
#endif

libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/objects.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ extern "C" {
2727

2828
struct gpio_irq_s {
2929
uint32_t ch;
30+
PinName pin;
3031
};
3132

3233
struct port_s {

0 commit comments

Comments
 (0)