Skip to content

Commit 94ff741

Browse files
Erik OliemanBogdan Marinescu
authored andcommitted
LPC1768 InterruptIn speedup
Use __CLZ to speed up GPIO interrupt processing.
1 parent fc57741 commit 94ff741

File tree

1 file changed

+43
-35
lines changed

1 file changed

+43
-35
lines changed

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

Lines changed: 43 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -31,44 +31,52 @@ static void handle_interrupt_in(void) {
3131
uint32_t fall0 = LPC_GPIOINT->IO0IntStatF;
3232
uint32_t rise2 = LPC_GPIOINT->IO2IntStatR;
3333
uint32_t fall2 = LPC_GPIOINT->IO2IntStatF;
34-
uint32_t mask0 = 0;
35-
uint32_t mask2 = 0;
36-
int i;
37-
38-
// P0.0-0.31
39-
for (i = 0; i < 32; i++) {
40-
uint32_t pmask = (1 << i);
41-
if (rise0 & pmask) {
42-
mask0 |= pmask;
43-
if (channel_ids[i] != 0)
44-
irq_handler(channel_ids[i], IRQ_RISE);
45-
}
46-
if (fall0 & pmask) {
47-
mask0 |= pmask;
48-
if (channel_ids[i] != 0)
49-
irq_handler(channel_ids[i], IRQ_FALL);
50-
}
34+
uint8_t bitloc;
35+
36+
while(rise0 > 0) { //Continue as long as there are interrupts pending
37+
bitloc = 31 - __CLZ(rise0); //CLZ returns number of leading zeros, 31 minus that is location of first pending interrupt
38+
if (channel_ids[bitloc] != 0)
39+
irq_handler(channel_ids[bitloc], IRQ_RISE); //Run that interrupt
40+
41+
//Both clear the interrupt with clear register, and remove it from our local copy of the interrupt pending register
42+
LPC_GPIOINT->IO0IntClr = 1 << bitloc;
43+
rise0 -= 1<<bitloc;
5144
}
5245

53-
// P2.0-2.15
54-
for (i = 0; i < 16; i++) {
55-
uint32_t pmask = (1 << i);
56-
int channel_index = i + 32;
57-
if (rise2 & pmask) {
58-
mask2 |= pmask;
59-
if (channel_ids[channel_index] != 0)
60-
irq_handler(channel_ids[channel_index], IRQ_RISE);
61-
}
62-
if (fall2 & pmask) {
63-
mask2 |= pmask;
64-
if (channel_ids[channel_index] != 0)
65-
irq_handler(channel_ids[channel_index], IRQ_FALL);
66-
}
46+
while(fall0 > 0) { //Continue as long as there are interrupts pending
47+
bitloc = 31 - __CLZ(fall0); //CLZ returns number of leading zeros, 31 minus that is location of first pending interrupt
48+
if (channel_ids[bitloc] != 0)
49+
irq_handler(channel_ids[bitloc], IRQ_FALL); //Run that interrupt
50+
51+
//Both clear the interrupt with clear register, and remove it from our local copy of the interrupt pending register
52+
LPC_GPIOINT->IO0IntClr = 1 << bitloc;
53+
fall0 -= 1<<bitloc;
54+
}
55+
56+
//Same for port 2, only we need to watch the channel_index
57+
while(rise2 > 0) { //Continue as long as there are interrupts pending
58+
bitloc = 31 - __CLZ(rise2); //CLZ returns number of leading zeros, 31 minus that is location of first pending interrupt
59+
60+
if (bitloc < 16) //Not sure if this is actually needed
61+
if (channel_ids[bitloc+32] != 0)
62+
irq_handler(channel_ids[bitloc+32], IRQ_RISE); //Run that interrupt
63+
64+
//Both clear the interrupt with clear register, and remove it from our local copy of the interrupt pending register
65+
LPC_GPIOINT->IO2IntClr = 1 << bitloc;
66+
rise2 -= 1<<bitloc;
67+
}
68+
69+
while(fall2 > 0) { //Continue as long as there are interrupts pending
70+
bitloc = 31 - __CLZ(fall2); //CLZ returns number of leading zeros, 31 minus that is location of first pending interrupt
71+
72+
if (bitloc < 16) //Not sure if this is actually needed
73+
if (channel_ids[bitloc+32] != 0)
74+
irq_handler(channel_ids[bitloc+32], IRQ_FALL); //Run that interrupt
75+
76+
//Both clear the interrupt with clear register, and remove it from our local copy of the interrupt pending register
77+
LPC_GPIOINT->IO2IntClr = 1 << bitloc;
78+
fall2 -= 1<<bitloc;
6779
}
68-
69-
// Clear the interrupts we just handled
70-
LPC_GPIOINT->IO0IntClr = mask0;
71-
LPC_GPIOINT->IO2IntClr = mask2;
7280
}
7381

7482
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) {

0 commit comments

Comments
 (0)