From 33015d601879ab6484b6121a53f5264e4ed679fb Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 21 Oct 2014 13:51:30 -0600 Subject: [PATCH] EFM32: Add buton interrupt handling for the Olimex board --- configs/Kconfig | 1 + configs/olimex-efm32g880f128-stk/README.txt | 16 ++ .../olimex-efm32g880f128-stk/include/board.h | 26 ++ configs/olimex-efm32g880f128-stk/src/Makefile | 4 + .../src/efm32_buttons.c | 227 ++++++++++++++++++ .../src/efm32g880f128-stk.h | 58 +++-- 6 files changed, 307 insertions(+), 25 deletions(-) create mode 100644 configs/olimex-efm32g880f128-stk/src/efm32_buttons.c diff --git a/configs/Kconfig b/configs/Kconfig index f176d1b484..319fec3073 100755 --- a/configs/Kconfig +++ b/configs/Kconfig @@ -367,6 +367,7 @@ config ARCH_BOARD_OLIMEX_EFM32G880F128_STK bool "Olimex EFM32G880F128 STK" depends on ARCH_CHIP_EFM32G880F128 select ARCH_HAVE_BUTTONS + select ARCH_HAVE_IRQBUTTONS ---help--- This options selects the Olimex EFM32G880F128 STK diff --git a/configs/olimex-efm32g880f128-stk/README.txt b/configs/olimex-efm32g880f128-stk/README.txt index f21bdb5dbe..9611a9ab16 100644 --- a/configs/olimex-efm32g880f128-stk/README.txt +++ b/configs/olimex-efm32g880f128-stk/README.txt @@ -46,6 +46,22 @@ LEDs The EFM32G880F128-STK has no user controllable LEDs. +Buttons +======= + + The Olimex board has four buttons, BUT1-4. Each is grounded and so should + have a weak pull-up so that it will be sensed as "1" when open and "0" + when closed. + + --------------------- --------------------- + PIN CONNECTIONS + --------------------- --------------------- + PE0/PCNT0_S0IN/U0_TX BUT1, EXT-18 + PE1/PCNT0_S1IN/U0_RX BUT2, EXT-19 + PE2/ACMP0_O BUT3, EXT-20 + E3/ACMP1_O BUT4, EXT-21 + --------------------- --------------------- + Serial Console ============== diff --git a/configs/olimex-efm32g880f128-stk/include/board.h b/configs/olimex-efm32g880f128-stk/include/board.h index d8c70fe98a..45fd4fa15c 100644 --- a/configs/olimex-efm32g880f128-stk/include/board.h +++ b/configs/olimex-efm32g880f128-stk/include/board.h @@ -204,6 +204,32 @@ #define LED_ASSERTION 6 /* LED1 + LED2 + LED3 */ #define LED_PANIC 7 /* N/C + N/C + N/C + LED4 */ +/* Buttons ******************************************************************/ +/* The Olimex board has four buttons, BUT1-4. Each is grounded and so should + * have a weak pull-up so that it will be sensed as "1" when open and "0" + * when closed. + * + * --------------------- --------------------- + * PIN CONNECTIONS + * --------------------- --------------------- + * PE0/PCNT0_S0IN/U0_TX BUT1, EXT-18 + * PE1/PCNT0_S1IN/U0_RX BUT2, EXT-19 + * PE2/ACMP0_O BUT3, EXT-20 + * PE3/ACMP1_O BUT4, EXT-21 + * --------------------- --------------------- + */ + +#define BUTTON_1 0 +#define BUTTON_2 1 +#define BUTTON_3 2 +#define BUTTON_4 3 +#define NUM_BUTTONS 4 + +#define BUTTON_1_BIT (1 << BUTTON_1) +#define BUTTON_2_BIT (1 << BUTTON_2) +#define BUTTON_3_BIT (1 << BUTTON_3) +#define BUTTON_4_BIT (1 << BUTTON_4) + /* Pin routing **************************************************************/ /* UART0: * diff --git a/configs/olimex-efm32g880f128-stk/src/Makefile b/configs/olimex-efm32g880f128-stk/src/Makefile index bd927233d0..6428fdddff 100644 --- a/configs/olimex-efm32g880f128-stk/src/Makefile +++ b/configs/olimex-efm32g880f128-stk/src/Makefile @@ -37,6 +37,10 @@ CSRCS = efm32_boot.c +ifeq ($(CONFIG_ARCH_BUTTONS),y) +CSRCS += efm32_buttons.c +endif + COBJS = $(CSRCS:.c=$(OBJEXT)) SRCS = $(ASRCS) $(CSRCS) OBJS = $(AOBJS) $(COBJS) diff --git a/configs/olimex-efm32g880f128-stk/src/efm32_buttons.c b/configs/olimex-efm32g880f128-stk/src/efm32_buttons.c new file mode 100644 index 0000000000..178bc2b9ff --- /dev/null +++ b/configs/olimex-efm32g880f128-stk/src/efm32_buttons.c @@ -0,0 +1,227 @@ +/**************************************************************************** + * configs/olimex-efm32g880f128-stk/src/efm32_buttons.c + * + * Copyright (C) 2014 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + ****************************************************************************/ +/* The Olimex board has four buttons, BUT1-4. Each is grounded and so should + * have a weak pull-up so that it will be sensed as "1" when open and "0" + * when closed. + * + * --------------------- --------------------- + * PIN CONNECTIONS + * --------------------- --------------------- + * PE0/PCNT0_S0IN/U0_TX BUT1, EXT-18 + * PE1/PCNT0_S1IN/U0_RX BUT2, EXT-19 + * PE2/ACMP0_O BUT3, EXT-20 + * E3/ACMP1_O BUT4, EXT-21 + * --------------------- --------------------- + */ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include + +#include +#include + +#include +#include + +#include "efm32_gpio.h" +#include "efm32g880f128-stk.h" + +#if CONFIG_ARCH_BUTTONS + +/**************************************************************************** + * Definitions + ****************************************************************************/ + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +#if defined(CONFIG_EFM32_GPIO_IRQ) && defined(CONFIG_ARCH_IRQBUTTONS) +#if 0 /* REVISIT -- See comments in board_button_irq() */ +static xcpt_t g_button_handlers[NUM_BUTTONS]; +#endif +static const uint8_t g_button_irqs[NUM_BUTTONS]; +#endif + +static const gpio_pinset_t g_button_configs[NUM_BUTTONS] = +{ + GPIO_BUTTON_1, GPIO_BUTTON_2, GPIO_BUTTON_3, GPIO_BUTTON_4 +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: board_button_initialize + * + * Description: + * board_button_initialize() must be called to initialize button resources. + * After that, board_buttons() may be called to collect the current state + * of all buttons or board_button_irq() may be called to register button + * interrupt handlers. + * + ****************************************************************************/ + +void board_button_initialize(void) +{ + int i; + + /* Configure each button */ + + for (i = 0; i < NUM_BUTTONS; i++) + { + (void)efm32_configgpio(g_button_configs[i]); + } +} + +/**************************************************************************** + * Name: board_buttons + * + * Description: + * After board_button_initialize() has been called, board_buttons() may be + * called to collect the state of all buttons. board_buttons() returns an + * 8-bit bit set with each bit associated with a button. See the BUTTON* + * definitions above for the meaning of each bit in the returned value. + * + ****************************************************************************/ + +uint8_t board_buttons(void) +{ + uint8_t ret; + int i; + + /* Check each button */ + + for (i = 0, ret = 0; i < NUM_BUTTONS; i++) + { + /* The button is closed if a low value is sensed */ + + if (!efm32_gpioread(g_button_configs[i])) + { + ret |= (1 << i); + } + } + + return ret; +} + +/**************************************************************************** + * Name: board_button_irq + * + * Description: + * This function may be called to register an interrupt handler that will + * be called when a button is depressed or released. The ID value is one + * of the BUTTON* definitions provided above. The previous interrupt + * handler address is returned (so that it may restored, if so desired). + * + * Configuration Notes: + * Configuration CONFIG_EFM32_GPIO_IRQ must be selected to enable the + * overall GPIO IRQ feature. + * + * Returned Value: + * This function should return the old interrupt handler value, but + * currently always returns NULL. + * + ****************************************************************************/ + +#if defined(CONFIG_EFM32_GPIO_IRQ) && defined(CONFIG_ARCH_IRQBUTTONS) +xcpt_t board_button_irq(int id, xcpt_t irqhandler) +{ + xcpt_t oldhandler = NULL; + + if (id >=0 && id < NUM_BUTTONS) + { + irqstate_t flags; + + /* Disable interrupts until we are done. This guarantees that the + * following operations are atomic. + */ + + flags = irqsave(); + + /* Get/set the old button handler + * + * REVISIT: Keeping copies of the hander in RAM seems wasteful + * since the OS already has this information internally. + */ + +#if 0 /* REVISIT */ + oldhandler = g_button_handlers[id]; + g_button_handlers[id] = irqhandler; +#else + oldhandler = NULL; +#endif + + /* Are we attaching or detaching? */ + + if (irqhandler != NULL) + { + /* Configure the interrupt */ + + efm32_gpioirq(g_button_configs[id]); + + /* Attach and enable the interrupt */ + + (void)irq_attach(g_button_irqs[id], irqhandler); + efm32_gpioirqenable(g_button_irqs[id]); + } + else + { + /* Disable and detach the interrupt */ + + efm32_gpioirqdisable(g_button_irqs[id]); + (void)irq_detach(g_button_irqs[id]); + } + + irqrestore(flags); + } + + /* Return the old button handler (so that it can be restored) */ + + return oldhandler; +} +#endif + +#endif /* CONFIG_ARCH_BUTTONS */ diff --git a/configs/olimex-efm32g880f128-stk/src/efm32g880f128-stk.h b/configs/olimex-efm32g880f128-stk/src/efm32g880f128-stk.h index f70344acc0..ebd0bab9dd 100644 --- a/configs/olimex-efm32g880f128-stk/src/efm32g880f128-stk.h +++ b/configs/olimex-efm32g880f128-stk/src/efm32g880f128-stk.h @@ -40,36 +40,44 @@ * Included Files ****************************************************************************/ +#include + /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ - /* LEDs - * - * The EFM32 Gecko Start Kit has four yellow LEDs. These LEDs are connected - * as follows: - * - * ------------------------------------- -------------------- - * EFM32 PIN BOARD SIGNALS - * ------------------------------------- -------------------- - * C0/USART1_TX#0/PCNT0_S0IN#2/ACMP0_CH0 MCU_PC0 UIF_LED0 - * C1/USART1_RX#0/PCNT0_S1IN#2/ACMP0_CH1 MCU_PC1 UIF_LED1 - * C2/USART2_TX#0/ACMP0_CH2 MCU_PC2 UIF_LED2 - * C3/USART2_RX#0/ACMP0_CH3 MCU_PC3 UIF_LED3 - * ------------------------------------- -------------------- - * - * All LEDs are grounded and so are illuminated by outputting a high - * value to the LED. - */ +/* Buttons: + * + * The Olimex board has four buttons, BUT1-4. Each is grounded and so should + * have a weak pull-up so that it will be sensed as "1" when open and "0" + * when closed. + * + * --------------------- --------------------- + * PIN CONNECTIONS + * --------------------- --------------------- + * PE0/PCNT0_S0IN/U0_TX BUT1, EXT-18 + * PE1/PCNT0_S1IN/U0_RX BUT2, EXT-19 + * PE2/ACMP0_O BUT3, EXT-20 + * PE3/ACMP1_O BUT4, EXT-21 + * --------------------- --------------------- + */ -#define GPIO_LED1 (GPIO_OUTPUT_WIREDOR_PULLDOWN|\ - GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN0) -#define GPIO_LED2 (GPIO_OUTPUT_WIREDOR_PULLDOWN|\ - GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN1) -#define GPIO_LED3 (GPIO_OUTPUT_WIREDOR_PULLDOWN|\ - GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN2) -#define GPIO_LED4 (GPIO_OUTPUT_WIREDOR_PULLDOWN|\ - GPIO_OUTPUT_CLEAR|GPIO_PORTC|GPIO_PIN3) +#ifdef CONFIG_EFM32_GPIO_IRQ +# define GPIO_BUTTON_1 (GPIO_INPUT_PULLUP|GPIO_INT_BOTH|GPIO_PORTE|GPIO_PIN0) +# define GPIO_BUTTON_2 (GPIO_INPUT_PULLUP|GPIO_INT_BOTH|GPIO_PORTE|GPIO_PIN1) +# define GPIO_BUTTON_3 (GPIO_INPUT_PULLUP|GPIO_INT_BOTH|GPIO_PORTE|GPIO_PIN2) +# define GPIO_BUTTON_4 (GPIO_INPUT_PULLUP|GPIO_INT_BOTH|GPIO_PORTE|GPIO_PIN3) + +# define GPIO_IRQ_BUTTON_1 EFM32_IRQ_EXTI0 +# define GPIO_IRQ_BUTTON_2 EFM32_IRQ_EXTI1 +# define GPIO_IRQ_BUTTON_3 EFM32_IRQ_EXTI2 +# define GPIO_IRQ_BUTTON_4 EFM32_IRQ_EXTI3 +#else +# define GPIO_BUTTON_1 (GPIO_INPUT_PULLUP|GPIO_PORTE|GPIO_PIN0) +# define GPIO_BUTTON_2 (GPIO_INPUT_PULLUP|GPIO_PORTE|GPIO_PIN1) +# define GPIO_BUTTON_3 (GPIO_INPUT_PULLUP|GPIO_PORTE|GPIO_PIN2) +# define GPIO_BUTTON_4 (GPIO_INPUT_PULLUP|GPIO_PORTE|GPIO_PIN3) +#endif /**************************************************************************** * Public Function Prototypes