nRF5 SDK v13.0.0
GPIOTE

The GPIOTE driver controls the GPIO and GPIOTE peripherals and configures and controls output and input pins. Output pins can be configured to be controlled manually or by a GPIOTE task. Input pins can be configured to be controlled in different modes:

TASK/EVENT channels allocation

The number of TASK/EVENT channels that can be used to drive an output pin using a GPIOTE task or to generate an event on input pin change is limited. The driver manages those channels. The user cannot control which channels are used.

When nrf_drv_gpiote_in_init or nrf_drv_gpiote_out_init is called, the driver allocates a channel from the pool. If all channels are already allocated, the functions return an error code. Note that nrf_drv_gpiote_out_init allocates a channel only if nrf_drv_gpiote_out_config_t indicates that the pin will be controlled by a task.

When nrf_drv_gpiote_in_uninit or nrf_drv_gpiote_out_uninit is called, the driver frees the allocated channel.

Driver configuration

To ensure that the driver configuration is known to all modules, only static configuration is supported. Therefore, nrf_drv_gpiote_init has no input parameters. The static configuration parameters are located in the sdk_config.h file.

The configuration parameters include:

Driver initialization

The GPIOTE driver is a shared resource that can be used by multiple modules in an application. Therefore, it can be initialized only once. If a module is using the driver, it must check if it has already been initialized by calling the function nrf_drv_gpiote_is_init. If this function returns false, the module must initialize the driver by calling the function nrf_drv_gpiote_init.

The following code example shows how to initialize the driver:

uint32_t err_code;
{
err_code = nrf_drv_gpiote_init();
}

Controlling output pins

After initialization, output pins can be configured to be controlled manually or by a GPIOTE task.

Initialization

Output pins are initialized by calling the function nrf_drv_gpiote_out_init. The argument of type nrf_drv_gpiote_out_config_t specifies the configuration of the output pin. You can use the following macros to set the configuration:

The configuration can be modified before calling nrf_drv_gpiote_out_init.

The following code example configures the 10th pin to be used by the task that sets the pin. The pin is initially set.

config.init_set = true;
err_code = nrf_drv_gpiote_out_init(10, &config);

Manually controlled output pins

When a pin is configured as non-task pin, it can be controlled by calling the following functions:

The driver asserts if the functions are called on a pin that is configured as task pin.

Task-controlled output pins

When a pin is configured as task pin, it can be controlled using the CPU by writing 1 to the relevant TASK register, or using PPI. Before a pin can be controlled, it must be enabled by calling the function nrf_drv_gpiote_out_task_enable.

When a pin is initialized as task pin, it allocates one of the available TASK/EVENT channels. Therefore, you must call nrf_drv_gpiote_out_uninit when the pin is no longer used.

The following code example shows how to use a task pin to be toggled using a task:

err_code = nrf_drv_gpiote_out_init(10, &config);
if (err_code != NRF_SUCCESS)
{
// handle error condition
}
// Configure PPI using ppi_task_address or use the address to manually control the task.
// Task is enabled and can be used by PPI.
// Task is disabled and cannot be controlled.
// Task is enabled again and can be controlled using ppi_task_addr.
// Pin is uninitialized. Task is disabled and TASK/EVENT channel is freed.

Controlling input pins

The GPIOTE peripheral can generate events on pin level change using the following methods:

Initialization

Input pins are initialized by calling the function nrf_drv_gpiote_in_init. The argument of type nrf_drv_gpiote_in_config_t specifies the configuration of the input pin. You can use the following macros to set the configuration:

The configuration can be modified before calling nrf_drv_gpiote_in_init. Note that macros are not setting any pull.

During the initialization of an input pin, the user must provide an event handler. The event handler will be called by the driver when the configured transition occurs and the interrupt is enabled.

The following code example configures the 10th pin to have pull-up and generate an event on pin toggling:

err_code = nrf_drv_gpiote_in_init(10, &config, pin_event_handler);

Usage

From a software point of view, the input sensing functionality is independent of the pin mode. If a high-accuracy pin is used, it can detect signals that are changed faster. Turning off high accuracy, on the other hand, enables the low-power feature.

Events that are generated by an input pin level change can be used to trigger events to be utilized by PPI, and optionally they can trigger a user event handler.

To start sensing an input pin, it must be enabled.

Pin input values can always be checked by calling the function nrf_drv_gpiote_in_is_set.

The following code example shows how to use a pin to detect toggling using high accuracy:

err_code = nrf_drv_gpiote_in_init(10, &config, pin_event_handler);
if (err_code != NRF_SUCCESS)
{
// handle error condition
}
ppi_event_addr = nrf_drv_gpiote_in_event_addr_get(10);
// Configure PPI using ppi_event_address.
// Enable event, interrupt is not enabled.
// Event is enabled and can be used by PPI.
// Task is disabled and cannot be controlled.
// Event and corresponding interrupt are enabled.
// Event is enabled again and can be used by PPI.
// Additionally, any toggling sensed will trigger interrupt
// Pin is uninitialized. Event is disabled and TASK/EVENT channel is freed.

Working with a SoftDevice

When a SoftDevice is enabled, it can interrupt the application at any time for a certain amount of time. This can lead to the situation where some pin level changes are missed. If the application must track an input pin that can change its level frequently, PPI should be used with a high-accuracy event together with a TIMER in counter mode to count the detected transitions.


Documentation feedback | Developer Zone | Subscribe | Updated