Skip to content

Commit 05b42af

Browse files
committed
Merge pull request #40 from ytsuboi/master
Fixed error handling and cleanup
2 parents d4e5206 + 1ff64de commit 05b42af

File tree

3 files changed

+102
-71
lines changed

3 files changed

+102
-71
lines changed

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,14 +44,14 @@ void analogin_init(analogin_t *obj, PinName pin) {
4444
obj->adc = (ADCName)pinmap_peripheral(pin, PinMap_ADC);
4545
if (obj->adc == (uint32_t)NC) {
4646
error("ADC pin mapping failed");
47+
return;
4748
}
4849

4950
// Power up ADC
50-
LPC_SYSCON->PDRUNCFG &= ~ (1 << 4);
51+
LPC_SYSCON->PDRUNCFG &= ~(1 << 4);
5152
LPC_SYSCON->SYSAHBCLKCTRL |= ((uint32_t)1 << 13);
5253

53-
uint32_t offset = (uint32_t)pin & 0xff;
54-
__IO uint32_t *reg = (__IO uint32_t*)(LPC_IOCON_BASE + offset);
54+
__IO uint32_t *reg = (__IO uint32_t*)(LPC_IOCON_BASE + (pin & 0xff));
5555

5656
// set pin to ADC mode
5757
*reg &= ~(1 << 7); // set ADMODE = 0 (analog mode)

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

Lines changed: 78 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -19,42 +19,52 @@
1919
#include "error.h"
2020
#include "gpio_api.h"
2121

22-
// The chip is capable of 4 external interrupts.
23-
#define CHANNEL_NUM 4
22+
// The chip is capable of 42 GPIO interrupts.
23+
// PIO0_0..PIO0_11, PIO1_0..PIO1_11, PIO2_0..PIO2_11, PIO3_0..PIO3_5
24+
#define CHANNEL_NUM 42
2425

2526
static uint32_t channel_ids[CHANNEL_NUM] = {0};
2627
static gpio_irq_handler irq_handler;
27-
static PinName pin_names[CHANNEL_NUM] = {};
28-
static uint8_t trigger_events[CHANNEL_NUM] = {};
2928

30-
static inline void handle_interrupt_in(uint32_t channel) {
29+
static inline int numofbits(uint32_t bits)
30+
{
31+
// Count number of bits
32+
bits = (bits & 0x55555555) + (bits >> 1 & 0x55555555);
33+
bits = (bits & 0x33333333) + (bits >> 2 & 0x33333333);
34+
bits = (bits & 0x0f0f0f0f) + (bits >> 4 & 0x0f0f0f0f);
35+
bits = (bits & 0x00ff00ff) + (bits >> 8 & 0x00ff00ff);
36+
return (bits & 0x0000ffff) + (bits >>16 & 0x0000ffff);
37+
}
38+
39+
static inline void handle_interrupt_in(uint32_t port) {
3140
// Find out whether the interrupt has been triggered by a high or low value...
3241
// As the LPC1114 doesn't have a specific register for this, we'll just have to read
3342
// the level of the pin as if it were just a normal input...
34-
43+
44+
uint32_t channel;
45+
3546
// Get the number of the pin being used and the port typedef
36-
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (((pin_names[channel] & 0xF000) >> PORT_SHIFT) * 0x10000)));
37-
uint8_t pin_num = (pin_names[channel] & (0x0f << PIN_SHIFT)) >> PIN_SHIFT;
38-
uint8_t trigger_event = trigger_events[channel];
39-
40-
if (trigger_event == 1)
41-
irq_handler(channel_ids[channel], IRQ_RISE);
42-
else if (trigger_event == 2)
43-
irq_handler(channel_ids[channel], IRQ_FALL);
44-
else {
45-
// In order to get an idea of which kind of event it is,
46-
// We need to read the logic level of the pin...
47-
48-
uint8_t logic = (port_reg->DATA & (1 << pin_num)) >> pin_num;
49-
50-
if (logic == 1)
47+
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (port * 0x10000)));
48+
49+
// Get index of function table from Mask Interrupt Status register
50+
channel = numofbits(port_reg->MIS - 1);
51+
52+
if (port_reg->MIS & port_reg->IBE) {
53+
// both edge, read the level of pin
54+
if ((port_reg->DATA & port_reg->MIS) != 0)
5155
irq_handler(channel_ids[channel], IRQ_RISE);
5256
else
5357
irq_handler(channel_ids[channel], IRQ_FALL);
5458
}
59+
else if (port_reg->MIS & port_reg->IEV) {
60+
irq_handler(channel_ids[channel], IRQ_RISE);
61+
}
62+
else {
63+
irq_handler(channel_ids[channel], IRQ_FALL);
64+
}
5565

5666
// Clear the interrupt...
57-
port_reg->IC |= 1 << pin_num;
67+
port_reg->IC = port_reg->MIS;
5868
}
5969

6070
void gpio_irq0(void) {handle_interrupt_in(0);}
@@ -63,48 +73,51 @@ void gpio_irq2(void) {handle_interrupt_in(2);}
6373
void gpio_irq3(void) {handle_interrupt_in(3);}
6474

6575
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {
76+
int channel;
77+
uint32_t port_num;
78+
6679
if (pin == NC) return -1;
6780

6881
// Firstly, we'll put some data in *obj so we can keep track of stuff.
6982
obj->pin = pin;
70-
71-
// Set the handler to be the pointer at the top...
72-
irq_handler = handler;
73-
83+
84+
// Set the handler to be the pointer at the top...
85+
irq_handler = handler;
86+
7487
// Which port are we using?
75-
int channel;
76-
uint32_t port_reg = (LPC_GPIO0_BASE + (((pin & 0xF000) >> PORT_SHIFT) * 0x10000));
77-
78-
switch (port_reg) {
79-
case LPC_GPIO0_BASE:
88+
port_num = ((pin & 0xF000) >> PORT_SHIFT);
89+
90+
switch (port_num) {
91+
case 0:
8092
NVIC_SetVector(EINT0_IRQn, (uint32_t)gpio_irq0);
8193
NVIC_EnableIRQ(EINT0_IRQn);
82-
channel = 0;
8394
break;
84-
case LPC_GPIO1_BASE:
95+
case 1:
8596
NVIC_SetVector(EINT1_IRQn, (uint32_t)gpio_irq1);
8697
NVIC_EnableIRQ(EINT1_IRQn);
87-
channel = 1;
8898
break;
89-
case LPC_GPIO2_BASE:
99+
case 2:
90100
NVIC_SetVector(EINT2_IRQn, (uint32_t)gpio_irq2);
91101
NVIC_EnableIRQ(EINT2_IRQn);
92-
channel = 2;
93102
break;
94-
case LPC_GPIO3_BASE:
103+
case 3:
95104
NVIC_SetVector(EINT3_IRQn, (uint32_t)gpio_irq3);
96105
NVIC_EnableIRQ(EINT3_IRQn);
97-
channel = 3;
98106
break;
99107
default:
100-
channel = -1;
101-
error("Invalid interrupt choice.");
102-
break;
108+
return -1;
103109
}
104-
110+
111+
// Generate index of function pointer table
112+
// PIO0_0 - PIO0_11 : 0..11
113+
// PIO1_0 - PIO1_11 : 12..23
114+
// PIO2_0 - PIO2_11 : 24..35
115+
// PIO3_0 - PIO3_5 : 36..41
116+
channel = (port_num * 12) + ((pin & 0x0F00) >> PIN_SHIFT);
117+
105118
channel_ids[channel] = id;
106-
pin_names[channel] = pin;
107119
obj->ch = channel;
120+
108121
return 0;
109122
}
110123

@@ -118,49 +131,46 @@ void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) {
118131
LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (((obj->pin & 0xF000) >> PORT_SHIFT) * 0x10000)));
119132

120133
// Need to get the pin number of the pin, not the value of the enum
121-
uint8_t pin_num = (obj->pin & (0x0f << PIN_SHIFT)) >> PIN_SHIFT;
134+
uint32_t pin_num = (1 << ((obj->pin & 0x0f00) >> PIN_SHIFT));
122135

136+
// Clear
137+
port_reg->IC |= pin_num;
138+
139+
// Make it edge sensitive.
140+
port_reg->IS &= ~pin_num;
123141

124-
if (trigger_events[obj->ch] != 0) {
125-
// We have an event.
126-
// Enable both edge interrupts.
142+
if ( (port_reg->IE & pin_num) != 0) {
143+
// We have an event.
144+
// Enable both edge interrupts.
127145

128146
if (enable) {
129-
trigger_events[obj->ch] = 3;
130-
port_reg->IBE |= 1 << pin_num;
131-
port_reg->IE |= 1 << pin_num;
147+
port_reg->IBE |= pin_num;
148+
port_reg->IE |= pin_num;
132149
}
133150
else {
134151
// These all need to be opposite, to reenable the other one.
135-
trigger_events[obj->ch] = event == IRQ_RISE ? 2 : 1;
136-
137-
port_reg->IBE &= ~(1 << pin_num);
152+
port_reg->IBE &= ~pin_num;
138153

139154
if (event == IRQ_RISE)
140-
port_reg->IEV &= ~(1 << pin_num);
155+
port_reg->IEV &= ~pin_num;
141156
else
142-
port_reg->IEV |= 1 << pin_num;
157+
port_reg->IEV |= pin_num;
143158

144-
port_reg->IE |= 1 << pin_num;
159+
port_reg->IE |= pin_num;
145160
}
146161
}
147162
else {
148-
if (enable) {
149-
trigger_events[obj->ch] = event == IRQ_RISE ? 1 : 2;
150-
port_reg->IE |= 1 << pin_num;
151-
}
152163
// One edge
153-
port_reg->IBE &= ~(1 << pin_num);
164+
port_reg->IBE &= ~pin_num;
154165
// Rising/falling?
155166
if (event == IRQ_RISE)
156-
port_reg->IEV |= 1 << pin_num;
167+
port_reg->IEV |= pin_num;
157168
else
158-
port_reg->IEV &= ~(1 << pin_num);
169+
port_reg->IEV &= ~pin_num;
170+
171+
if (enable) {
172+
port_reg->IE |= pin_num;
173+
}
159174
}
160175

161-
// Clear
162-
port_reg->IC |= 1 << pin_num;
163-
164-
// Make it edge sensitive.
165-
port_reg->IS &= ~(1 << pin_num);
166176
}

libraries/tests/mbed/interruptin_2/main.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,21 @@ InterruptIn button8(p10);
1313
InterruptIn button9(p9);
1414
DigitalOut led(LED1);
1515
DigitalOut flash(LED4);
16+
17+
#elif defined(TARGET_LPC1114)
18+
InterruptIn button(p30); // SW2 (User switch)
19+
InterruptIn button1(p5);
20+
InterruptIn button2(p6);
21+
InterruptIn button3(p7);
22+
InterruptIn button4(p9);
23+
InterruptIn button5(p10);
24+
InterruptIn button6(p12);
25+
InterruptIn button7(p13);
26+
InterruptIn button8(p14);
27+
InterruptIn button9(p15);
28+
DigitalOut led(LED1);
29+
DigitalOut flash(LED2);
30+
1631
#else
1732
InterruptIn button(p30);
1833
InterruptIn button1(p29);
@@ -33,6 +48,11 @@ void flip() {
3348
}
3449

3550
int main() {
51+
flash = 0;
52+
led = 0;
53+
#if defined(TARGET_LPC1114)
54+
button.mode(PullUp);
55+
#endif
3656
button.rise(&flip); // attach the address of the flip function to the rising edge
3757
button1.rise(&flip);
3858
button2.rise(&flip);
@@ -43,6 +63,7 @@ int main() {
4363
button7.rise(&flip);
4464
button8.rise(&flip);
4565
button9.rise(&flip);
66+
4667
while(1) { // wait around, interrupts will interrupt this!
4768
flash = !flash;
4869
wait(0.25);

0 commit comments

Comments
 (0)