Skip to content

Commit c56d1a5

Browse files
committed
Fully implemented GPIO_IRQ
* Removed unused variables/comments. * As of yet, untested...
1 parent 819ca55 commit c56d1a5

File tree

2 files changed

+80
-86
lines changed

2 files changed

+80
-86
lines changed

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

Lines changed: 79 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,31 @@
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-
static uint32_t channel = 0;
27-
28-
#warning (matthewelse) This code isn't working yet, so don't rely on it, or try to use it.
26+
static int channel = 0;
27+
static PinName pin_names[CHANNEL_NUM] = {};
2928

3029
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...
3133

32-
#error (matthewelse) There's no way this code will work now...
33-
uint32_t ch_bit = (1 << channel);
34-
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (channel * 0x10000)));
35-
34+
// Get the number of the pin being used and the port typedef
35+
uint8_t pin_number = (pin_names[channel] & (0x0f << 8)) >> 8;
36+
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (((pin & 0xF000) >> PORT_SHIFT) * 0x10000)));
37+
38+
if ((port_reg->MASKED_ACCESS & (1 << pin_number)) >> pin_number) {
39+
// High, therefore rising edge...
40+
irq_handler(channel_ids[channel], IRQ_RISE);
41+
}
42+
else {
43+
// Low, therefore falling edge...
44+
irq_handler(channel_ids[channel], IRQ_FALL);
45+
}
3646
}
3747

3848
void gpio_irq0(void) {handle_interrupt_in(0);}
@@ -43,17 +53,43 @@ void gpio_irq3(void) {handle_interrupt_in(3);}
4353
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
4454
if (pin == NC) return -1;
4555

46-
channel_ids[channel] = id;
47-
irq_handler = handler;
56+
// Firstly, we'll put some data in *obj so we can keep track of stuff.
57+
obj->pin = pin;
4858

49-
//obj->pin = pin;
59+
/*
60+
If there are any ports or pins that aren't able to handle interrupts, put them here and uncomment.
61+
62+
if (pin == ... ||
63+
pin == ...) {
64+
error("This pin does not suppor interrupts.");
65+
return -1;
66+
}
67+
*/
68+
69+
channel_ids[channnel] = id;
70+
pin_names[channel] = pin;
5071
obj->ch = channel;
51-
52-
NVIC_EnableIRQ(EINT0_IRQn);
53-
NVIC_EnableIRQ(EINT1_IRQn);
54-
NVIC_EnableIRQ(EINT2_IRQn);
55-
NVIC_EnableIRQ(EINT3_IRQn);
56-
72+
73+
// Which port are we using?
74+
switch (channel) {
75+
case 0:
76+
NVIC_SetVector(EINT0_IRQn, (uint32_t)gpio_irq0);
77+
NVIC_EnableIrq(EINT0_IRQn);
78+
break;
79+
case 1:
80+
NVIC_SetVector(EINT1_IRQn, (uint32_t)gpio_irq1);
81+
NVIC_EnableIrq(EINT1_IRQn);
82+
break;
83+
case 2:
84+
NVIC_SetVector(EINT2_IRQn, (uint32_t)gpio_irq2);
85+
NVIC_EnableIrq(EINT2_IRQn);
86+
break;
87+
case 3:
88+
NVIC_SetVector(EINT3_IRQn, (uint32_t)gpio_irq3);
89+
NVIC_EnableIrq(EINT3_IRQn);
90+
break;
91+
}
92+
5793
channel++;
5894
return 0;
5995
}
@@ -63,71 +99,30 @@ void gpio_irq_free(gpio_irq_t *obj) {
6399
}
64100

65101
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
66-
// TODO: Debug this to find out what data is put in the obj object at runtime...
67-
68-
LPC_GPIO_TypeDef *gpioReg;
69-
70-
// Firstly, clear the interrupts for this pin.
71-
// Then, let the registers know whether we're looking for edge detection...
72-
// And enable the interrupt
73-
// And set it to only respond to interrupts on one edge.
74-
switch (obj->port) {
75-
case LPC_GPIO0_BASE:
76-
// Clear
77-
LPC_GPIO0->IC |= 1 << obj->pin;
78-
79-
// Edge
80-
LPC_GPIO0->IS &= ~(1 << obj->pin);
81-
82-
// Enable
83-
if (enable) LPC_GPIO0->IE |= 1 << obj->pin;
84-
else LPC_GPIO0->IE &= ~(1 << obj->pin);
85-
86-
// One edge
87-
LPC_GPIO0->IBE &= ~(1 << obj->pin);
88-
89-
// Rising/falling?
90-
if (event == IRQ_RISE) LPC_GPIO0->IEV |= 1 << obj->pin;
91-
else LPC_GPIO0->IEV &= ~(1 << obj->pin);
92-
break;
93-
case LPC_GPIO1_BASE:
94-
LPC_GPIO1->IC |= 1 << obj->pin;
95-
96-
LPC_GPIO1->IS &= ~(1 << obj->pin);
97-
98-
if (enable) LPC_GPIO1->IE |= 1 << obj->pin;
99-
else LPC_GPIO1->IE &= ~(1 << obj->pin);
100-
101-
LPC_GPIO1->IBE &= ~(1 << obj->pin);
102-
103-
if (event == IRQ_RISE) LPC_GPIO0->IEV |= 1 << obj->pin;
104-
else LPC_GPIO0->IEV &= ~(1 << obj->pin);
105-
break;
106-
case LPC_GPIO2_BASE:
107-
LPC_GPIO2->IC |= 1 << obj->pin;
108-
109-
LPC_GPIO2->IS &= ~(1 << obj->pin);
110-
111-
if (enable) LPC_GPIO2->IE |= 1 << obj->pin;
112-
else LPC_GPIO2->IE &= ~(1 << obj->pin);
113-
114-
LPC_GPIO2->IBE &= ~(1 << obj->pin);
115-
116-
if (event == IRQ_RISE) LPC_GPIO0->IEV |= 1 << obj->pin;
117-
else LPC_GPIO0->IEV &= ~(1 << obj->pin);
118-
break;
119-
case LPC_GPIO3_BASE:
120-
LPC_GPIO3->IC |= 1 << obj->pin;
121-
122-
LPC_GPIO3->IC &= ~(1 << obj->pin);
123-
124-
if (enable) LPC_GPIO3->IE |= 1 << obj->pin;
125-
else LPC_GPIO3->IE &= ~(1 << obj->pin);
126-
127-
LPC_GPIO3->IBE &= ~(1 << obj->pin);
128-
129-
if (event == IRQ_RISE) LPC_GPIO0->IEV |= 1 << obj->pin;
130-
else LPC_GPIO0->IEV &= ~(1 << obj->pin);
131-
break;
132-
}
102+
pin = obj->pin;
103+
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (((pin & 0xF000) >> PORT_SHIFT) * 0x10000)));
104+
105+
/*
106+
Firstly, clear the interrupts for this pin,
107+
Then, let the registers know whether we're looking for edge detection,
108+
Enable the interrupt,
109+
And set it to only respond to interrupts on one edge.
110+
*/
111+
112+
// Clear
113+
port_reg->IC |= 1 << obj->pin;
114+
115+
// Edge
116+
port_reg->IS &= ~(1 << obj->pin);
117+
118+
// Enable
119+
if (enable) port_reg->IE |= 1 << obj->pin;
120+
else port_reg->IE &= ~(1 << obj->pin);
121+
122+
// One edge
123+
port_reg->IBE &= ~(1 << obj->pin);
124+
125+
// Rising/falling?
126+
if (event == IRQ_RISE) port_reg->IEV |= 1 << obj->pin;
127+
else port_reg->IEV &= ~(1 << obj->pin);
133128
}

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

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

2828
struct gpio_irq_s {
2929
uint32_t ch;
30-
uint32_t port;
31-
uint32_t pin;
30+
PinName pin;
3231
};
3332

3433
struct port_s {

0 commit comments

Comments
 (0)