Merge pull request #396 from Sissors/master

[KLxxZ] Increased KLxxZs interrupt handling speed
pull/397/head
Martin Kojtal 2014-07-10 08:51:45 +01:00
commit ffef32f2bc
3 changed files with 124 additions and 108 deletions

View File

@ -30,40 +30,45 @@ static gpio_irq_handler irq_handler;
#define IRQ_FALLING_EDGE PORT_PCR_IRQC(10)
#define IRQ_EITHER_EDGE PORT_PCR_IRQC(11)
const uint32_t search_bits[] = {0x0000FFFF, 0x000000FF, 0x0000000F, 0x00000003, 0x00000001};
static void handle_interrupt_in(PORT_Type *port, int ch_base) {
uint32_t mask = 0, i;
uint32_t isfr;
uint8_t location;
for (i = 0; i < 32; i++) {
uint32_t pmask = (1 << i);
if (port->ISFR & pmask) {
mask |= pmask;
uint32_t id = channel_ids[ch_base + i];
if (id == 0) {
continue;
}
FGPIO_Type *gpio;
gpio_irq_event event = IRQ_NONE;
switch (port->PCR[i] & PORT_PCR_IRQC_MASK) {
case IRQ_RAISING_EDGE:
event = IRQ_RISE;
break;
case IRQ_FALLING_EDGE:
event = IRQ_FALL;
break;
case IRQ_EITHER_EDGE:
gpio = (port == PORTA) ? (FPTA) : (FPTB);
event = (gpio->PDIR & pmask) ? (IRQ_RISE) : (IRQ_FALL);
break;
}
if (event != IRQ_NONE) {
irq_handler(id, event);
}
while((isfr = port->ISFR) != 0) {
location = 0;
for (int i = 0; i < 5; i++) {
if (!(isfr & (search_bits[i] << location)))
location += 1 << (4 - i);
}
uint32_t id = channel_ids[ch_base + location];
if (id == 0) {
continue;
}
FGPIO_Type *gpio;
gpio_irq_event event = IRQ_NONE;
switch (port->PCR[location] & PORT_PCR_IRQC_MASK) {
case IRQ_RAISING_EDGE:
event = IRQ_RISE;
break;
case IRQ_FALLING_EDGE:
event = IRQ_FALL;
break;
case IRQ_EITHER_EDGE:
gpio = (port == PORTA) ? (FPTA) : (FPTB);
event = (gpio->PDIR & (1 << location)) ? (IRQ_RISE) : (IRQ_FALL);
break;
}
if (event != IRQ_NONE) {
irq_handler(id, event);
}
port->ISFR = 1 << location;
}
port->ISFR = mask;
}
/* IRQ only on PORTA and PORTB */
@ -86,21 +91,21 @@ int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32
uint32_t ch_base, vector;
IRQn_Type irq_n;
switch (obj->port) {
case PortA:
ch_base = 0;
irq_n = PORTA_IRQn;
vector = (uint32_t)gpio_irqA;
break;
case PortA:
ch_base = 0;
irq_n = PORTA_IRQn;
vector = (uint32_t)gpio_irqA;
break;
case PortB:
ch_base = 32;
irq_n = PORTB_IRQn;
vector = (uint32_t)gpio_irqB;
break;
case PortB:
ch_base = 32;
irq_n = PORTB_IRQn;
vector = (uint32_t)gpio_irqB;
break;
default:
error("gpio_irq only supported on Port A and B");
break;
default:
error("gpio_irq only supported on Port A and B");
break;
}
NVIC_SetVector(irq_n, vector);
NVIC_EnableIRQ(irq_n);

View File

@ -30,40 +30,45 @@ static gpio_irq_handler irq_handler;
#define IRQ_FALLING_EDGE PORT_PCR_IRQC(10)
#define IRQ_EITHER_EDGE PORT_PCR_IRQC(11)
const uint32_t search_bits[] = {0x0000FFFF, 0x000000FF, 0x0000000F, 0x00000003, 0x00000001};
static void handle_interrupt_in(PORT_Type *port, int ch_base) {
uint32_t mask = 0, i;
uint32_t isfr;
uint8_t location;
for (i = 0; i < 32; i++) {
uint32_t pmask = (1 << i);
if (port->ISFR & pmask) {
mask |= pmask;
uint32_t id = channel_ids[ch_base + i];
if (id == 0) {
continue;
}
FGPIO_Type *gpio;
gpio_irq_event event = IRQ_NONE;
switch (port->PCR[i] & PORT_PCR_IRQC_MASK) {
case IRQ_RAISING_EDGE:
event = IRQ_RISE;
break;
case IRQ_FALLING_EDGE:
event = IRQ_FALL;
break;
case IRQ_EITHER_EDGE:
gpio = (port == PORTA) ? (FPTA) : (FPTD);
event = (gpio->PDIR & pmask) ? (IRQ_RISE) : (IRQ_FALL);
break;
}
if (event != IRQ_NONE) {
irq_handler(id, event);
}
while((isfr = port->ISFR) != 0) {
location = 0;
for (int i = 0; i < 5; i++) {
if (!(isfr & (search_bits[i] << location)))
location += 1 << (4 - i);
}
uint32_t id = channel_ids[ch_base + location];
if (id == 0) {
continue;
}
FGPIO_Type *gpio;
gpio_irq_event event = IRQ_NONE;
switch (port->PCR[location] & PORT_PCR_IRQC_MASK) {
case IRQ_RAISING_EDGE:
event = IRQ_RISE;
break;
case IRQ_FALLING_EDGE:
event = IRQ_FALL;
break;
case IRQ_EITHER_EDGE:
gpio = (port == PORTA) ? (FPTA) : (FPTD);
event = (gpio->PDIR & (1 << location)) ? (IRQ_RISE) : (IRQ_FALL);
break;
}
if (event != IRQ_NONE) {
irq_handler(id, event);
}
port->ISFR = 1 << location;
}
port->ISFR = mask;
}
void gpio_irqA(void) {handle_interrupt_in(PORTA, 0);}

View File

@ -30,45 +30,51 @@ static gpio_irq_handler irq_handler;
#define IRQ_FALLING_EDGE PORT_PCR_IRQC(10)
#define IRQ_EITHER_EDGE PORT_PCR_IRQC(11)
const uint32_t search_bits[] = {0x0000FFFF, 0x000000FF, 0x0000000F, 0x00000003, 0x00000001};
static void handle_interrupt_in(PORT_Type *port, int ch_base) {
uint32_t mask = 0, i;
uint32_t isfr;
uint8_t location;
for (i = 0; i < 32; i++) {
uint32_t pmask = (1 << i);
if (port->ISFR & pmask) {
mask |= pmask;
uint32_t id = channel_ids[ch_base + i];
if (id == 0) {
continue;
}
FGPIO_Type *gpio;
gpio_irq_event event = IRQ_NONE;
switch (port->PCR[i] & PORT_PCR_IRQC_MASK) {
case IRQ_RAISING_EDGE:
event = IRQ_RISE;
break;
case IRQ_FALLING_EDGE:
event = IRQ_FALL;
break;
case IRQ_EITHER_EDGE:
if (port == PORTA) {
gpio = FPTA;
} else if (port == PORTC) {
gpio = FPTC;
} else {
gpio = FPTD;
}
event = (gpio->PDIR & pmask) ? (IRQ_RISE) : (IRQ_FALL);
break;
}
if (event != IRQ_NONE)
irq_handler(id, event);
while((isfr = port->ISFR) != 0) {
location = 0;
for (int i = 0; i < 5; i++) {
if (!(isfr & (search_bits[i] << location)))
location += 1 << (4 - i);
}
uint32_t id = channel_ids[ch_base + location];
if (id == 0) {
continue;
}
FGPIO_Type *gpio;
gpio_irq_event event = IRQ_NONE;
switch (port->PCR[location] & PORT_PCR_IRQC_MASK) {
case IRQ_RAISING_EDGE:
event = IRQ_RISE;
break;
case IRQ_FALLING_EDGE:
event = IRQ_FALL;
break;
case IRQ_EITHER_EDGE:
if (port == PORTA) {
gpio = FPTA;
} else if (port == PORTC) {
gpio = FPTC;
} else {
gpio = FPTD;
}
event = (gpio->PDIR & (1<<location)) ? (IRQ_RISE) : (IRQ_FALL);
break;
}
if (event != IRQ_NONE) {
irq_handler(id, event);
}
port->ISFR = 1 << location;
}
port->ISFR = mask;
}
void gpio_irqA(void) {