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:
#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: