Controlling nRF52 GPIO by tasks and events

Introduction

In previous article, I have introduced APIs to control GPIO ports of nRF52 using nrf_gpio.h driver in nRF5 SDK. There’s another way to interact with digital I/O ports of nRF52 which involves tasks and events. In this article, I will discuss the GPIOTE (General Purpose Input Output Tasks and Events) peripheral in nRF52. I will talk about:

  • Why you might want to use GPIOTE in your project
  • GPIOTE registers
  • The nrfx_gpiote driver in nRF52 SDK to interact with GPIOTE
  • How to include nrfx_gpiote in your project
  • Some commonly used APIs in nrfx_gpiote library
  • Build a project using GPIOTE to control digital input and output ports

To compile and run your code on real nRF52 hardware, it is recommended that you have a nRF52 development kit such as

Affiliate Disclosure: When you click on links in this section and make a purchase, this may result in this site earning a commission at no extra cost to you.

GPIOTE peripheral

The GPIOTE peripheral in nRF52 provides a way for accessing GPIO pins using tasks and events. Here are some reasons why would you might want to use GPIOTE in your project:

  • Using tasks and events allow a peripheral to trigger another peripheral without CPU intervention, hence you can use GPIOTE (in combination with PPI) to implement interesting low power applications.
  • GPIOTE can generate interrupt when an event happens. You can connect a GPIO pin to a GPIOTE channel and configure it to generate an interrupt on the GPIO pin state change.

GPIOTE is a peripheral which has 8 channels. Each channel can be configured to connect to a GPIO pin.

  • If a GPIOTE channel is connected to a GPIO Input Pin, it can generate events on the input state change (rising edge, falling edge or any change).
GPIO Input Pin ---> GPIOTE Channel ---> Events

  • If a GPIOTE channel is connected to a GPIO output pin, it can control its digital output (e.g. drive it low or high). This is done by writing to a GPIOTE task register.
GPIOTE Output Pin <--- GPIOTE Channel <--- Tasks

Configuration registers

  • CONFIG[0], ..., CONFIG[7]: These registers configures GPIOTE channel 0 to 7, respectively, including:
    • Mode: To configure GPIOTE channel in event mode or task mode. Use event mode when GPIOTE channel is connected to an input pin, and use task mode when GPIOTE Channel is connected to an output pin.
    • GPIO pin: to select which GPIO pin is connected to the GPIOTE Channel.
    • Initial value of GPIO pin when in task mode
    • Configure operation in task mode when OUT task is triggered. The OUT task can set, clear or toggle an output pin. When writing to OUT task register, the operation that will be performed depending on CONFIG register.
    • Configure operation in input that will trigger IN event in event mode

Event registers

  • EVENTS_IN[0], ..., EVENTS_IN[7]: these 32-bit event registers are updated when an event happens in a GPIOTE channel 0, …, 7, respectively. These registers are used when a GPIOTE channel is connected to an input GPIO pin. An event may be generated when the input pin goes from low to high, high to low, or both. The CONFIG register determines when an event is generated.

Task registers

  • TASKS_SET[0], ..., TASK_SET[7]: These SET task registers are used to set a GPIO output pin that is connected to a GPIOTE channel. Writing to these registers to set the output port high.
  • TASKS_CLR[0], ..., TASKS_CLR[7]: CLR task registers will clear the GPIO output pin that is connected to the GPIOTE channel when written to.
  • TASKS_OUT[0], ..., TASKS_OUT[7]: These OUT task registers will trigger an operation (e.g. Set, Clear or Toggle an output pin). The specific operation that happens depends on the settings in CONFIG register.

Interrupt registers

  • INTENSET: enable interrupt when an event happens
  • INTENCLR: disable interrupt when an event occurs

The nrfx_gpiote driver

In the previous section, we described the GPIOTE hardware and its internal registers. To control the GPIOTE peripheral, you use the nrfx_gpiote driver from nRF5 SDK. In this section, we discuss how to include the driver in your project and some common APIs from the library.

Include nrfx_gpiote driver in your project

To include nrfx_gpiote driver in your project, you need to add nrfx_gpiote.c in your source file list

nrfx_gpiote in source file list

and include nrfx_gpiote.h header file defined in $(SDK_ROOT)/modules/nrfx/drivers/include.

Enabling GPIOTE peripheral in sdk_config.h

To use GPIOTE peripheral, you need to enable it in sdk_config.h by setting NRFX_GPIOTE_ENABLED to 1

Enable nrfx_gpiote in project configuration

Initialise GPIOTE driver

Before using the driver, you need to initialise it. To initialise the driver, you call nrfx_gpiote_init() function:

Configure GPIOTE for an input pin

Use the function nrfx_gpiote_in_init() to configure a GPIOTE channel to connect to an input I/O pin and to generate an interrupt on pin state change.

This function takes 3 arguments:

  • pin: The GPIO pin that should be connected to a GPIOTE channel
  • p_config: a pointer that points to a configuration structure which specifies the conditions to trigger interrupt and whether to use internal pull up or pull down resistors on the GPIO pin.
  • evt_handler: a callback function that executes when interrupt occurs.

Enabling GPIOTE input pin

After configuring the GPIOTE input pin, you need to call nrfx_gpiote_in_event_enable() to enable it

Configure GPIOTE for an output pin

To configure a GPIOTE channel to connect to an output pin, use the function nrfx_gpiote_out_init():

This function takes 2 parameters:

  • pin: the GPIO pin that should be connected to a GPIOTE channel
  • p_config: a pointer that points to a configuration structure nrfx_gpiote_out_config_t. You can use the following macros for the configuration:
    • NRFX_GPIOTE_CONFIG_OUT_TASK_LOW
    • NRFX_GPIOTE_CONFIG_OUT_TASK_HIGH
    • NRFX_GPIOTE_CONFIG_OUT_TASK_TOGGLE

Enabling GPIOTE output pin

After configuring the GPIOTE output pin, you need to enable it by calling nrfx_gpiote_out_task_enable()

Manually triggering GPIOTE OUT task

To trigger GPIOTE OUT task manually, call API nrfx_gpiote_out_task_trigger()

This function will trigger OUT task, and will set, clear or toggle the output pin connected to the GPIOTE channel based on GPIOTE channel configuration.

NRF52 GPIOTE Project Example

In this section, you will implement a project using GPIOTE to control digital input and output ports. The objective of the project is to toggle a LED whenever you press a button:

  • Initially, the button is not pressed, and LED is off
  • When you press the button the first time, the LED is turned on.
  • If you press the button second time, the LED is shutdown, and so on.

By going through this simple project, you will learn how to use nrfx_gpiote APIs to configure a GPIOTE channel to control an output port (control LED), and uses a GPIOTE channel to trigger an interrupt on an input pin state change (detect button pressed).

Code

The above task can be implemented with the following code

The full project files can be seen here.

Wrapping Up

In this article, you have learnt about the GPIOTE peripheral of nRF52 and the APIs in nrfx_gpiote driver to interact with it. You aslo learnt how to implement a practical project that uses GPIOTE to control digital input and output ports. Thanks for reading.

Leave a Comment