nRF5x GPIO tutorial


In this lab, we will take a close look on the General Purpose Input/Output (GPIO) hardware peripheral (aka: GPIO Port) available inside an nRF5x SoC, its registers layout and software available abstraction layers. The GPIO will be used in this lab to communicate with the  push buttons and LEDs on the nRF52840-DK . Even though there is an easier approach to interact with the LEDs and push buttons which is through the Board Support Package (BSP)  library seen in LabA-5 , however, understanding the GPIO port is critical and will enable us to interface with a broader range of external circuitry and not just the board’s LEDs and push buttons. The GPIOTE is covered in the next lab.

General purpose input/output (GPIO) hardware peripheral (GPIO Port)

The GPIO hardware peripheral inside an nRF5x SoC  provides a general purpose input/output interface to any external hardware that you want to include in your design. In this lab, GPIO is used to interface with push buttons and LEDs available on the hosting development board of the SoC (nRF52840-DK). The  GPIO is organized as one port with up to 32 I/Os (dependent on package QFN= 31, WLCSP =32) enabling access and control of up to 32 pins through one port. Each GPIO pin can be accessed and configured  individually. All digital I/O are fully configurable, only the analog inputs have fixed pins.

nRF5x GPIO Port and the GPIO pin details ( Click to Enlarge)

The figure above illustrates the GPIO port, which contains 32 individual pins, where PIN0 is illustrated in more detail as a reference. All the signals on the left side of the illustration are used by other peripherals in the system and can be used to override the output path and/or read the input signal.

The available registers in the GPIO hardware peripheral (GPIO port) are summarized below. Keep in mind that all of these registers are 32-bits :

OUT                  Register to write to the whole port.

OUTSET             Register to set pins in the GPIO port high (‘1’) ( Simplified Set).

OUTCLR            Register to set pins in the GPIO port low (‘0’)  ( Simplified Clear).

IN                      Register to read the whole port.

DIR                    Register to set direction of pins in the GPIO.(1=output, 0=input).

DIRSET               Register to set direction of pins in the GPIO. Writing 1 to individual pin sets pins as output.

DIRCLR              Same as DIRSET, but 1 sets pin as input.

LATCH               Latch register indicating what GPIO pins that have met the criteria set in the PIN_CNF[n].SENSE registers.

DETECTMODE   Select between default DETECT signal behavior and LDETECT mode.

PIN_OUT[n]       (n=0..31)  Register to write value to PIN number n.

PIN_CNF[n]       (n=0..31)Configuration register (sense, pull, drive strength, direction).

Each pin individually configurable (PINn_CFG register):
  • Direction
  • Drive strength
  • Enable pull up/down
  • Pin sensing
  • Input buffer disconnect

Programing the GPIO Port

It is possible to program the GPIO  by directly writing and reading to its memory mapped registers at the right offset values .

Base Address of the GPIO for the nRF52840. The nRF52840 chip is the only chip in the nRFx family that has two GPIO ports P0 and P1.

GPIO Registers Offsets

However, this would be a tedious task  as it requires thorough reading the Product Specification  technical documentation of the chip and understanding the functionality of each bit in these 32-bits registers. The nRF5 SDK provides a much simpler and effective method to program the GPIO port which is through the GPIO Hardware access layer (HAL) .


The Hardware access layer (HAL) provides high-level abstraction to interact with the GPIO by implementing macros and inline functions that take care of writing to the low-level registers. It is implemented in the SDK file nrf_gpio.h residing in <SDK Installation Path>\modules\nrfx\hal . The steps involved to use the GPIO HAL are outlined below:

1.Pin Configuration: The first step to work with a GPIO pin is to configure it. The core configuration function in the HAL is the nrf_gpio_cfg() . The function allows to set all parameters of a pin in the GPIO Port in one call.

nrf_gpio_cfg() core function parameters

The pin_number should be an integer value between 0-31 (0-47 for the nRF52840 chip ) .

the dir is of type nrf_gpio_pin_dir_t which is an enumeration of 2 values. This value specifies weather to program a specific pin as an input or an output.

nrf_gpio_pin_dir_t enumeration

The input parameter is only useful if the pin is configured as  an input and it controls the connection of the input buffer. Its of type nrf_gpio_pin_input_t enumeration.

nrf_gpio_pin_input_t enumeration

The pull parameter is also only useful if the pin is configured as  an input and it allows us to enable/disable a pull-up or pull-down resister on the pin to prevent floating . Its of type nrf_gpio_pin_input_t enumeration.

nrf_gpio_pin_pull_t enumeration

The drive parameter is used for pins configured as output. It determinants the gate driving behavior of the pin when 0 or 1 is written to the corresponding output bit of the pin in register OUT (Standard 0.5 mA, High Drive 5mA , or disconnect “High impedance”. Current rating may vary with product variant and package ).

nrf_gpio_pin_drive_t enumeration

Lastly, the sense parameter which is only valid if the pin is configured as input. Pins can be configured to detect either a high level NRF_GPIO_PIN_SENSE_HIGH or a low level NRF_GPIO_PIN_SENSE_LOW on their input. When the correct level is detected on any such configured pin, the sense mechanism will set the DETECT signal high, which can be utilized by other peripherals for many purposes such as wake up.

nrf_gpio_pin_sense_t enumeration

For Instance, Let’s assume we want to configure pin number 13 as output pin with gate driving GPIO_PIN_CNF_DRIVE_S0S1  , the right parameters to pass to the nrf_gpio_cfg() are shown below:


It’s worth noting that the GPIO HAL offers alternative simplified “shorthand” methods to configure the pins , which hide the inner details of setting these parameters individually . For instance, the function call shown below is identical to the nrf_gpio_cfg() code above


nrf_gpio_cfg_output() is implemented on top of the nrf_gpio_cfg() 

nrf_gpio_cfg_output implementation in nrf_gpio.h

Available shorthand configuration functions by the GPIO HAL are :


Check the GPIO HAL documentation on Nordic InfoCenter for the API reference of these functions.

2.Pin Reading/Writing : After configuring a pin to be either digital output or digital input, you could use the following GPIO HAL functions for writing to an output pin or reading from an input pin.

For writing to a GPIO pin use the function nrf_gpio_pin_write() , which only takes two parameters the pin two write to , and the value to write (0 or 1).

nrf_gpio_pin_write() function usage

See the example below (Complete source code and project files are available on GitHub), which is a simple program that keeps toggling GPIO number 13 ( P0.13) which is on the nRF52840-DK connected to LED.

nrf_gpio_pin_write() example

For instructions on running the example on the development board,  read the instructions in LabA-5 (Running Embedded Centric labs and tutorials).

GPIO pin mapping of the nRF52840-DK for reference

For reading from a GPIO pin use the function nrf_gpio_pin_read() , it takes one parameter which is the pin number to be read and it returned 0 or 1.

nrf_gpio_pin_read() function


See the example below (Complete source code and project files are available on GitHub), which is a simple  demo program that controls  LED1 through push button 1 ( Turn LED1 on) and push button 2( Turn LED1 off) on the nRF52840-DK. The pooling method to read the buttons here is not recommended for real application as it consumes CPU power, You may want to consider using GPIOTE or interrupts.

nrf_gpio_pin_read() example

For instructions on running the example on the development board,  read the instructions in LabA-5 (Running Embedded Centric labs and tutorials).

References and pictures:
Nordic Semiconductor