From 80119920218c06dbaa3da922e438f1e438c2ab48 Mon Sep 17 00:00:00 2001 From: Matthew Else <matthewelse1997@gmail.com> Date: Tue, 23 Jul 2013 14:19:33 +0100 Subject: [PATCH] Fully implemented gpio_irq_set --- .../TARGET_NXP/TARGET_LPC11XX/gpio_irq_api.c | 122 ++++++++++-------- .../hal/TARGET_NXP/TARGET_LPC11XX/objects.h | 2 + 2 files changed, 69 insertions(+), 55 deletions(-) diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/gpio_irq_api.c b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/gpio_irq_api.c index 9782f78793..509606dd0e 100644 --- a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/gpio_irq_api.c +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/gpio_irq_api.c @@ -23,34 +23,16 @@ static uint32_t channel_ids[CHANNEL_NUM] = {0}; static gpio_irq_handler irq_handler; -static int gpioIrqInitialised = 0; +static uint32_t channel = 0; #warning (matthewelse) This code isn't working yet, so don't rely on it, or try to use it. static inline void handle_interrupt_in(uint32_t channel) { #error (matthewelse) There's no way this code will work now... - uint32_t ch_bit = (1 << channel); - - LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) LPC_GPIO0_BASE + (channel * 0x10000)); - - // Return immediately if: - // * The interrupt was already served - // * There is no user handler - // * It is a level interrupt, not an edge interrupt - if ( ((&port_reg->IST & ch_bit) == 0) || - (channel_ids[channel] == 0 ) || - (&port_reg->ISEL & ch_bit ) ) return; - - if ((&port_reg->IENR & ch_bit) && (&port_reg->RISE & ch_bit)) { - irq_handler(channel_ids[channel], IRQ_RISE); - &port_reg->RISE = ch_bit; - } - if ((&port_reg->IENF & ch_bit) && (&port_reg->FALL & ch_bit)) { - irq_handler(channel_ids[channel], IRQ_FALL); - } - &port_reg->IST = ch_bit; + LPC_GPIO_TypeDef *port_reg = ((LPC_GPIO_TypeDef *) (LPC_GPIO0_BASE + (channel * 0x10000))); + } void gpio_irq0(void) {handle_interrupt_in(0);} @@ -60,63 +42,93 @@ void gpio_irq3(void) {handle_interrupt_in(3);} int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id) { if (pin == NC) return -1; - if (gpioInitialised) return; + channel_ids[channel] = id; irq_handler = handler; - /* Enable AHB clock to the GPIO domain. */ - LPC_SYSCON->SYSAHBCLKCTRL |= SCB_SYSAHBCLKCTRL_GPIO; + //obj->pin = pin; + obj->ch = channel; NVIC_EnableIRQ(EINT0_IRQn); NVIC_EnableIRQ(EINT1_IRQn); NVIC_EnableIRQ(EINT2_IRQn); NVIC_EnableIRQ(EINT3_IRQn); - gpioInitialised = 1; + channel++; return 0; } void gpio_irq_free(gpio_irq_t *obj) { channel_ids[obj->ch] = 0; - LPC_SYSCON->STARTERP0 &= ~(1 << obj->ch); } // This is basically complete, but non-functional as it needs to do something with obj at some point. void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable) { - if (!gpioIqrInitialised) gpio_irq_init(); + // TODO: Debug this to find out what data is put in the obj object at runtime... -#warning (matthewelse) TODO: undefined port and value. Also need to do something with the *obj... - int port = 0; - int pin = 0; + LPC_GPIO_TypeDef *gpioReg; - LPC_GPIO_TypeDef *gpioRegisters; - - switch (port) { - case 0: - gpioRegisters = LPC_GPIO0; + // Firstly, clear the interrupts for this pin. + // Then, let the registers know whether we're looking for edge detection... + // And enable the interrupt + // And set it to only respond to interrupts on one edge. + switch (obj->port) { + case LPC_GPIO0_BASE: + // Clear + LPC_GPIO0->IC |= 1 << obj->pin; + + // Edge + LPC_GPIO0->IS &= ~(1 << obj->pin); + + // Enable + if (enable) LPC_GPIO0->IE |= 1 << obj->pin; + else LPC_GPIO0->IE &= ~(1 << obj->pin); + + // One edge + LPC_GPIO0->IBE &= ~(1 << obj->pin); + + // Rising/falling? + if (event == IRQ_RISE) LPC_GPIO0->IEV |= 1 << obj->pin; + else LPC_GPIO0->IEV &= ~(1 << obj->pin); break; - case 1: - gpioRegisters = LPC_GPIO1; - break; - case 2: - gpioRegisters = LPC_GPIO2; - break; - case 3: - gpioRegisters = LPC_GPIO3; - break; - } + case LPC_GPIO1_BASE: + LPC_GPIO1->IC |= 1 << obj->pin; - gpioRegisters->IBE 0; // Assume that we only want to interrupt on high or low edges, not both. - gpioRegisters->IS &= ~(1 << pin); + LPC_GPIO1->IS &= ~(1 << obj->pin); - if (enable) { - gpioRegisters->IE |= (1<<pin); - } + if (enable) LPC_GPIO1->IE |= 1 << obj->pin; + else LPC_GPIO1->IE &= ~(1 << obj->pin); - if (event == IRP_RISE) { - gpioRegisters->IEV |= 1 << pin; - } - else { - gpioRegisters->IEV &= ~(1 << pin); + LPC_GPIO1->IBE &= ~(1 << obj->pin); + + if (event == IRQ_RISE) LPC_GPIO0->IEV |= 1 << obj->pin; + else LPC_GPIO0->IEV &= ~(1 << obj->pin); + break; + case LPC_GPIO2_BASE: + LPC_GPIO2->IC |= 1 << obj->pin; + + LPC_GPIO2->IS &= ~(1 << obj->pin); + + if (enable) LPC_GPIO2->IE |= 1 << obj->pin; + else LPC_GPIO2->IE &= ~(1 << obj->pin); + + LPC_GPIO2->IBE &= ~(1 << obj->pin); + + if (event == IRQ_RISE) LPC_GPIO0->IEV |= 1 << obj->pin; + else LPC_GPIO0->IEV &= ~(1 << obj->pin); + break; + case LPC_GPIO3_BASE: + LPC_GPIO3->IC |= 1 << obj->pin; + + LPC_GPIO3->IC &= ~(1 << obj->pin); + + if (enable) LPC_GPIO3->IE |= 1 << obj->pin; + else LPC_GPIO3->IE &= ~(1 << obj->pin); + + LPC_GPIO3->IBE &= ~(1 << obj->pin); + + if (event == IRQ_RISE) LPC_GPIO0->IEV |= 1 << obj->pin; + else LPC_GPIO0->IEV &= ~(1 << obj->pin); + break; } } diff --git a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/objects.h b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/objects.h index 0718498e8d..9ca1df1f3e 100644 --- a/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/objects.h +++ b/libraries/mbed/targets/hal/TARGET_NXP/TARGET_LPC11XX/objects.h @@ -27,6 +27,8 @@ extern "C" { struct gpio_irq_s { uint32_t ch; + uint32_t port; + uint32_t pin; }; struct port_s {