Problem with using gpio pins after upgrading to connect sdk 2.2.0

I am in the process of migrating a project using the nrf5340 from nRF Connect SDK v1.6.0 to v2.2.0.

I have run into an issue where gpio pins I could use before are no longer usable and pins that I am allowed to use crash the app as well. My current guess is that there have been introduced a requirement to initialise the gpio0 and gpio1 devices before they can be used. Is this the case and if so how would they need to be initialised.

The error I am seeing is that an assert fails that checks if a given pin number is associated with the gpio device

ASSERTION FAIL [(cfg->port_pin_mask & (gpio_port_pins_t)(1UL << (pin))) != 0U] @ WEST_TOPDIR/zephyr/include/zephyr/drivers/gpio.h:732
        Unsupported pin

Here is the content of the local variables before the assertion fails, it can be seen that gpio0->state->initialized == false



My issue can be reproduced using nRF Connect SDK v2.2.0 and running the peripheral_uart sample on a nRF5340-DK (I am not sure of the revision as we have several) with slight modifications:

  • Adding src/p_gpio.c to target_sources in the CMakeLists:

target_sources(app PRIVATE
  src/main.c
  src/p_gpio.c
)

  • Including p_gpio.h in main.c and adding a call to p_gpio_init in the main function:

#include "p_gpio.h"
//...
void main(void)
{
	int blink_status = 0;
	int err = 0;

	err = p_gpio_init();
	if (err) {
		printk("Failed to init p_gpio.\n");
	}

	configure_gpio();

	err = uart_init();
	if (err) {
		error();
	}
//...
}

  • Add the two following files to src:

p_gpio.h

#include "p_gpio.h"

#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>

#include <zephyr/kernel.h>

#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(p_gpio);

static const struct device* gpio_0;
static const struct device* gpio_1;

int p_gpio_set_pin_internal(const struct device* gpio, uint8_t pin, bool value);
static int p_gpio_pin_callback_init_internal(const struct device* gpio, uint8_t pin, uint32_t pin_flags, gpio_callback_handler_t callback, struct gpio_callback* callback_data, uint32_t callback_flags);

int p_gpio_init() {
	gpio_0 = device_get_binding("GPIO_0");
	gpio_1 = device_get_binding("GPIO_1");
	
	int res = p_gpio_init_pins();
	
	if(!gpio_0 || !gpio_1 || res) {
		LOG_ERR("Error: Failed to init GPIO pins");
	}

	return res;
}

int p_gpio_init_pins() {
	int res;
	//Test Setup Pins
	res = p_gpio_pin_init(gpio_0, 31, GPIO_OUTPUT | GPIO_PULL_UP);
	gpio_port_clear_bits(gpio_0, BIT(31));

	res |= p_gpio_pin_init(gpio_0, 30, GPIO_OUTPUT | GPIO_PULL_UP);
	gpio_port_clear_bits(gpio_0, BIT(30));

	res |= p_gpio_pin_init(gpio_0, 29, GPIO_OUTPUT | GPIO_PULL_UP);
	gpio_port_clear_bits(gpio_0, BIT(29));

	return res;
}

int p_gpio_get_pin(uint8_t gpio, uint8_t pin) {
	if(!gpio) {
		return gpio_pin_get(gpio_0, pin);
	} else {
		return gpio_pin_get(gpio_1, pin);
	}
	
}

int p_gpio_set_pin(uint8_t gpio, uint8_t pin, bool value) {
	if(!gpio) {
		return p_gpio_set_pin_internal(gpio_0, pin, value);
	} else {
		return p_gpio_set_pin_internal(gpio_1, pin, value);
	}
}

int p_gpio_set_pin_internal(const struct device* gpio, uint8_t pin, bool value) {
	if(value) {
		return gpio_port_set_bits(gpio, BIT(pin));
	} else {
		return gpio_port_clear_bits(gpio, BIT(pin));
	}
	
}

int p_gpio_pin_init(const struct device* gpio, uint8_t pin, uint32_t flags) {
	int err = gpio_pin_configure(gpio, pin, flags);
	if(err) {
		LOG_ERR("Failed to init pin %d", pin);
	} else {
		LOG_INF("Pin %d inited", pin);
	}
	return err;
}

int p_gpio_pin_callback_init(uint8_t gpio, uint8_t pin, uint32_t pin_flags, gpio_callback_handler_t callback, struct gpio_callback* callback_data, uint32_t callback_flags) {	
	if(!gpio) {
		return p_gpio_pin_callback_init_internal(gpio_0, pin, pin_flags, callback, callback_data, callback_flags);
	} else {
		return p_gpio_pin_callback_init_internal(gpio_1, pin, pin_flags, callback, callback_data, callback_flags);
	}
}

int p_gpio_pin_callback_init_internal(const struct device* gpio, uint8_t pin, uint32_t pin_flags, gpio_callback_handler_t callback, struct gpio_callback* callback_data, uint32_t callback_flags) {
	int ret;
	ret = p_gpio_pin_init(gpio, pin, pin_flags);
	if(ret != 0) {
		LOG_ERR("Error %d: failed to configure pin %d\n", ret, pin);
		return ret;
	}

	ret = gpio_pin_interrupt_configure(gpio, pin, callback_flags);
	if(ret != 0) {
		LOG_ERR("Error %d: failed to configure interrupt on pin %d\n", ret, pin);
		return ret;
	}

	gpio_init_callback(callback_data, callback, BIT(pin));
	gpio_add_callback(gpio, callback_data);
	LOG_INF("Set up interrupt on pin %d\n", pin);
	return ret;
}

  • and lastly the build configuration used the board nrf5340dk_nrf5340_cpuapp and the prj.conf.

Here is a zip of the modified project:

3603.peripheral_uart.zip

Related