This example project demonstrates how to use interrupts to detect button presses. The example is written for BGM111 development kit in C language with Bluetooth SDK v2.0.1. The BGScript version of this project can be found at:

http://community.silabs.com/t5/Bluetooth-Wi-Fi-Knowledge-Base/BGScript-BGM111-button-press-detection-with-interrupts/ta-p/169549

 

The example differentiates 3 kind of button presses:

  • short (press and release within a defined short interval)
  • long (press and release over a defined short interval)
  • double click (two presses within a defined short interval)

 

The button presses generate external stack events (gecko_evt_system_external_signal), which can be handled by the user on demand. In the example log messages are sent to UART using UARTDRV.

 

Since UARTDRV uses interrupts as well, an interrupt dispatcher is used instead of writing interrupt handlers. This is implemented in gpiointerrupt.c (${StudioSdkPath}/platform/emdrv/gpiointerrupt/src/gpiointerrupt.c)

 

The interrupts are enabled for both rising and falling edges by:

 

GPIOINT_Init();
GPIO_ExtIntConfig(gpioPortF,6,6,true,true,true);
GPIO_ExtIntConfig(gpioPortF,7,7,true,true,true);

 

And the callback functions are set by 

 

GPIOINT_CallbackRegister(6,handle_button_change);
GPIOINT_CallbackRegister(7,handle_button_change);

Note, that the dispatcher uses pin numbers, no interrupt handler numbers, so in this case the 3rd parameter of GPIO_ExtIntConfig(...) is practically not used.

 

The rising/falling edge can be differentiated by reading the state of the GPIO pins in the interrupt handler.

  • Knowledge Base Articles
  • Bluetooth Low Energy
  • Bluetooth Classic
  • One issue with this approach is that you lose any timestamp of when the interrupt happened inside the handling of the external_signal. If you instead configure the interrupts with gecko_config and use bgapi_hardware_init, you can get the interrupts with timestamp into the hardware_interrupt event.

    0
  • @klangdon79 the event evt_hardware_interrupt is deprecated starting from SDK v2.3.0. Most of the HW related BGAPI calls are marked deprecated (ADC, GPIO, interrupts). It is better to handle the HW peripherals directly using emlib or emdrv. 

    0
  • @JaakkoV for SDK v2.3.1 should GPIO interrupts be configured using functions from em_gpio.c OR should they be configured using the gpios and gpio_exti members of the gecko_configuration_t struct?

    0
  • @Mooneyj it is recommended to NOT use the gecko_configuration_t struct for GPIO interrupts but to use either em_gpio.c or GPIOINT driver from emdrv (like in the code that is published in this article)

    0
  • I set mine up just like the code in this post, but I still haven't been able to get the IRQ handlers to hit.  My code is below.  Am I missing a step?

     

    #include "em_emu.h"
    #include "em_cmu.h"
    #include "em_gpio.h"
    #include "em_rtcc.h"

     

    void GPIO_EVEN_IRQHandler(void)
    {
        uint32_t flags = GPIO_IntGet();
    }

    void GPIO_ODD_IRQHandler(void)
    {
        uint32_t flags = GPIO_IntGet();
    }

     

    void main(void)
    {
    #ifdef FEATURE_SPI_FLASH
    /* Put the SPI flash into Deep Power Down mode for those radio boards where it is available */
    MX25_init();
    MX25_DP();
    /* We must disable SPI communication */
    USART_Reset(USART1);
    #endif /* FEATURE_SPI_FLASH */

    /* Initialize peripherals */
    enter_DefaultMode_from_RESET();

    // Interrupts
    NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
    NVIC_EnableIRQ(GPIO_ODD_IRQn);
    NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
    NVIC_EnableIRQ(GPIO_EVEN_IRQn);
    GPIO_PinModeSet(gpioPortF,6,gpioModeInput,0);
    GPIO_PinModeSet(gpioPortF,7,gpioModeInput,0);
    GPIO_ExtIntConfig(gpioPortF,6,0,true,true,true);
    GPIO_ExtIntConfig(gpioPortF,7,1,true,true,true);

    /* Initialize stack */
    gecko_init(&config);

     

    while(1);

    }

    0
  • @JaakkoV 

     

    I set mine up just like the code in this post, but I still haven't been able to get the IRQ handlers to hit.  My code is below.  Am I missing a step?

     

    #include "em_emu.h"
    #include "em_cmu.h"
    #include "em_gpio.h"
    #include "em_rtcc.h"

     

    void GPIO_EVEN_IRQHandler(void)
    {
        uint32_t flags = GPIO_IntGet();
    }

    void GPIO_ODD_IRQHandler(void)
    {
        uint32_t flags = GPIO_IntGet();
    }

     

    void main(void)
    {
    #ifdef FEATURE_SPI_FLASH
    /* Put the SPI flash into Deep Power Down mode for those radio boards where it is available */
    MX25_init();
    MX25_DP();
    /* We must disable SPI communication */
    USART_Reset(USART1);
    #endif /* FEATURE_SPI_FLASH */

    /* Initialize peripherals */
    enter_DefaultMode_from_RESET();

    // Interrupts
    NVIC_ClearPendingIRQ(GPIO_ODD_IRQn);
    NVIC_EnableIRQ(GPIO_ODD_IRQn);
    NVIC_ClearPendingIRQ(GPIO_EVEN_IRQn);
    NVIC_EnableIRQ(GPIO_EVEN_IRQn);
    GPIO_PinModeSet(gpioPortF,6,gpioModeInput,0);
    GPIO_PinModeSet(gpioPortF,7,gpioModeInput,0);
    GPIO_ExtIntConfig(gpioPortF,6,0,true,true,true);
    GPIO_ExtIntConfig(gpioPortF,7,1,true,true,true);

    /* Initialize stack */
    gecko_init(&config);

     

    while(1);

    }

    0
  • How are you testing this and with which toolchain (IAR or GCC)? I noticed in some of my tests that GCC & breakpoints set inside IRQ handler like in this case do not work (breakpoint is never hit) unless I turn optimization level to "none" in build settings.

    0
  • I'm using IAR 8.10 toolchain.  I know Simplicity Studio recommends using nothing newer than IAR 7.30.  Could this be the issue?

     

    I changed my IRQ handlers to send an external signal to the stacks, and I set a breakpoint on the gecko_external_signal event, but I'm not hitting that breakpoint either.  My optimization is set to "none."

    0
  • Don't know if IAR 8.x is the reason (I know there are some issues with 8.x version but don't know exactly what). Why not test with GCC? That worked fine in my tests. GCC toolchain (4.9.3) should be available in Studio without any extra hassle, just pick that toolchain instead of IAR when creating one of the example projects.

    0
  • I created a new project using IAR 7.30 and got the same results.  Then I created another new project with GCC 4.9.3 and got the same results.  I'm starting to wonder if there's an issue with the hardware.

     

    Do you have any other ideas?

    0