I need help getting a GPIO to work from the DTS to the code

Hi all,

this is a bit embarrassing, I updated from nrf SDK 2.5.0 to 3.1.1 and I'm a bit lost with the simplest things.

I need to toggle an LED on a custom board. I'm using an NRF52840 on a UBLOX module. The JLINK debugger recognises the microcontroller, and the power applied is ok.

I have a prj.conf file where the GPIO is enabled:

CONFIG_GPIO=y
I have an overlay file in the "boards" subfolder inside the project with the following statements:
/ { 
    
	leds {
		compatible = "gpio-leds";

		led0: led_0{
			gpios = < &gpio0 24 GPIO_ACTIVE_HIGH>;
			label = "LED0";
		};

		led1: led_1{
			gpios = < &gpio1 16 GPIO_ACTIVE_HIGH>;
			label = "LED1";
		};
	};
};
The init code for the GPIO is following (based on online examples and a previous project with the older SDK 2.5.0):
#define GPIO_LED_0_NODE DT_NODELABEL(led0)
static struct gpio_dt_spec gpio_led_0 = GPIO_DT_SPEC_GET(GPIO_LED_0_NODE, gpios);

void pin_ios_init(void)
{
	
	gpio_pin_configure_dt(&gpio_led_0, GPIO_DISCONNECTED);

	if (!gpio_is_ready_dt(&gpio_led_0))
	{
		LOG_ERR("Error LED 0 init");
	}

	return;
}
When I try to build, I noticed a warning:
CMake Warning at C:/ncs/v3.1.1/zephyr/CMakeLists.txt:1027 (message):
No SOURCES given to Zephyr library: drivers__gpio

Excluding target from build.
After a while everything else fails due to:
C:/ncs/v3.1.1/zephyr/include/zephyr/device.h:96:41: error: '__device_dts_ord_14' undeclared here (not in a function); did you mean '__device_dts_ord_104'?
   96 | #define DEVICE_NAME_GET(dev_id) _CONCAT(__device_, dev_id)
      |                                         ^~~~~~~~~
C:/ncs/v3.1.1/zephyr/include/zephyr/toolchain/common.h:168:26: note: in definition of macro '_DO_CONCAT'
  168 | #define _DO_CONCAT(x, y) x ## y
      |                          ^
C:/ncs/v3.1.1/zephyr/include/zephyr/device.h:96:33: note: in expansion of macro '_CONCAT'
   96 | #define DEVICE_NAME_GET(dev_id) _CONCAT(__device_, dev_id)
      |                                 ^~~~~~~
C:/ncs/v3.1.1/zephyr/include/zephyr/device.h:293:37: note: in expansion of macro 'DEVICE_NAME_GET'
  293 | #define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(Z_DEVICE_DT_DEV_ID(node_id))
      |                                     ^~~~~~~~~~~~~~~
C:/ncs/v3.1.1/zephyr/include/zephyr/device.h:310:34: note: in expansion of macro 'DEVICE_DT_NAME_GET'
  310 | #define DEVICE_DT_GET(node_id) (&DEVICE_DT_NAME_GET(node_id))
      |                                  ^~~~~~~~~~~~~~~~~~
C:/ncs/v3.1.1/zephyr/include/zephyr/drivers/gpio.h:334:25: note: in expansion of macro 'DEVICE_DT_GET'
  334 |                 .port = DEVICE_DT_GET(DT_GPIO_CTLR_BY_IDX(node_id, prop, idx)),\
      |                         ^~~~~~~~~~~~~
C:/ncs/v3.1.1/zephyr/include/zephyr/drivers/gpio.h:370:9: note: in expansion of macro 'GPIO_DT_SPEC_GET_BY_IDX'
  370 |         GPIO_DT_SPEC_GET_BY_IDX(node_id, prop, 0)
      |         ^~~~~~~~~~~~~~~~~~~~~~~
C:/Users/fahre/Projects/_resonAg/Firmware/gamma_comms/src/tasks/pin_ios.c:14:41: note: in expansion of macro 'GPIO_DT_SPEC_GET'
   14 | static struct gpio_dt_spec gpio_led_0 = GPIO_DT_SPEC_GET(GPIO_LED_0_NODE, gpios);
Any help or pointers are greatly appreciated.
Cheers,
Albert
Parents
  • I got it working.

    On the prj.conf file I have the two lines:

    CONFIG_GPIO=y
    CONFIG_PINCTRL=y

    On the .dts file in the "boards" folder I had to add:

    &gpiote {
    	status = "okay";
    };
    
    &gpio0 {
    	status = "okay";
    };
    
    &gpio1 {
    	status = "okay";
    };

    The overlay file has the following:

    	leds {
    		compatible = "gpio-leds";
    
    		led0: led_0{
    			gpios = < &gpio0 24 GPIO_ACTIVE_HIGH>;
    			label = "LED0";
    		};
    
    		led1: led_1{
    			gpios = < &gpio0 16 GPIO_ACTIVE_HIGH>;
    			label = "LED1";
    		};
    	};
    
        aliases{
            led0 = &led0;
        }; 

    And finally on the C code I have:

    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   250
    static void pin_ios_task(void);
    
    K_THREAD_DEFINE(pio_ios_tid, PIN_IOS_STACKSIZE, pin_ios_task, NULL, NULL, NULL, PIN_IOS_PRIORITY, 0, 0);
    
    /* Identifier for GPIOs */
    #define LED0_NODE           DT_ALIAS(led0)
    static struct gpio_dt_spec gpio_led_0 = GPIO_DT_SPEC_GET(LED0_NODE, gpios);
    
    LOG_MODULE_REGISTER(pin_ios);
    
    void pin_ios_init(void)
    {
    	
    	gpio_pin_configure_dt(&gpio_led_0, GPIO_OUTPUT_ACTIVE);
    
    	if (!gpio_is_ready_dt(&gpio_led_0))
    	{
    		LOG_ERR("Error LED 0 init");
    	}
    
    	return;
    }
    
    static void pin_ios_task(void)
    {
        while(1)
        {
            k_sleep(K_MSEC(SLEEP_TIME_MS));
            gpio_pin_toggle_dt(&gpio_led_0);
        }
    }

    I am still not sure what is actually the correct way of doing this of if I added too much information, but it was the only way to get it to compile and run.

    Cheers,

    Alberto

  • This looks about correct.

    I don't think you need to specify CONFIG_PINCTRL=y in prj.conf, as I believe it is set by default.

    Other than that, to set GPIO outputs that you want to control manually from your application, it is normal to define them as leds in your overlay/dts files, and use the API that you are using here. 

    An alternative is to use the buttons and leds module that is used in the nrf samples, such as the peripheral_uart sample. 

    You can add the CONFIG_DK_LIBRARY=y, and include:

    #include <dk_buttons_and_leds.h>

    and use dk_buttons_init() and dk_leds_init(), which will configure all the buttons and leds defined in your board files. Look at the sample for reference. If you dig into the dk_buttons_and_leds.c, you will see that it is set up pretty much like you already did in your application.

    Best regards,

    Edvin

Reply
  • This looks about correct.

    I don't think you need to specify CONFIG_PINCTRL=y in prj.conf, as I believe it is set by default.

    Other than that, to set GPIO outputs that you want to control manually from your application, it is normal to define them as leds in your overlay/dts files, and use the API that you are using here. 

    An alternative is to use the buttons and leds module that is used in the nrf samples, such as the peripheral_uart sample. 

    You can add the CONFIG_DK_LIBRARY=y, and include:

    #include <dk_buttons_and_leds.h>

    and use dk_buttons_init() and dk_leds_init(), which will configure all the buttons and leds defined in your board files. Look at the sample for reference. If you dig into the dk_buttons_and_leds.c, you will see that it is set up pretty much like you already did in your application.

    Best regards,

    Edvin

Children
No Data
Related