This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problem using nRF Connect SDK devicetree GPIO definitions in code

Hi,

I am just starting out creating a project to run on an nRF9160 on custom hardware. I have set up a development environment (v1.9.0) through nRF Connect for Desktop app. I have created a custom board configuration based on the thingy91_nrf9160 board files, and successfully built an example project (cloud_client) for this board configuration.

Now I want to add some GPIO of my own to setup connections to the rest of my system, but since I am new to device trees I am not sure that I am doing things correctly.

Starting out with a testpad on the pcb, I added a GPIO pin to the dts file as follows:

/ {
    /* model and compatible parameter defined here...  */

	tp: testpin {
		gpios = <&gpio0 22 0>;
	};
	
	/* reserved memory defined here... */
};

/* some peripherals defined here... */

&gpio0 {
	status = "okay";
};

/* some more peripherals defined here... */

And I try to use the pin through a sourcefile that I have added to the src folder, using the nrf52840_reset.c code as an example:

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

#define TP_NODE         DT_NODELABEL(tp)
#define TP_GPIO_CTRL    DT_GPIO_CTLR(TP_NODE, gpios)
#define TP_GPIO_PIN     DT_GPIO_PIN(TP_NODE, gpios)
#define TP_GPIO_FLAGS   DT_GPIO_FLAGS(TP_NODE, gpios)

static struct device *port = NULL;

void TestpinInit(void)
{
    port = DEVICE_DT_GET(TP_GPIO_CTRL);
    gpio_pin_configure(port, TP_GPIO_PIN, TP_GPIO_FLAGS | GPIO_OUTPUT_INACTIVE);
}

void TestpinToggle(void)
{
    if (NULL != port)
    {
        gpio_pin_toggle(port, TP_GPIO_PIN);
    }
}

Unfortunately this code creates quite some build errors; all similar. For example:

In file included from C:\_tools\v1.9.0\zephyr\include\toolchain\gcc.h:72,
                 from C:\_tools\v1.9.0\zephyr\include\toolchain.h:50,
                 from C:\_tools\v1.9.0\zephyr\include\sys\printk.h:11,
                 from C:\_tools\v1.9.0\zephyr\include\sys\__assert.h:11,
                 from C:\_tools\v1.9.0\zephyr\include\drivers\gpio.h:18,
                 from c:\_repo\project\nrf9160\cloud_client\src\testpin.c:32:
../src/testpin.c: In function 'TestpinInit':
C:\_tools\v1.9.0\zephyr\include\device.h:96:39: error: '__device_dts_ord_DT_N_S_testpin_P_gpios_IDX_0_PH_ORD' undeclared (first use in this function)
   96 | #define DEVICE_NAME_GET(name) _CONCAT(__device_, name)
      |                                       ^~~~~~~~~
C:\_tools\v1.9.0\zephyr\include\toolchain\common.h:132:26: note: in definition of macro '_DO_CONCAT'
  132 | #define _DO_CONCAT(x, y) x ## y
      |                          ^
C:\_tools\v1.9.0\zephyr\include\device.h:96:31: note: in expansion of macro '_CONCAT'
   96 | #define DEVICE_NAME_GET(name) _CONCAT(__device_, name)
      |                               ^~~~~~~
C:\_tools\v1.9.0\zephyr\include\device.h:291:37: note: in expansion of macro 'DEVICE_NAME_GET'
  291 | #define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(Z_DEVICE_DT_DEV_NAME(node_id))
      |                                     ^~~~~~~~~~~~~~~
C:\_tools\v1.9.0\zephyr\include\device.h:311:34: note: in expansion of macro 'DEVICE_DT_NAME_GET'
  311 | #define DEVICE_DT_GET(node_id) (&DEVICE_DT_NAME_GET(node_id))
      |                                  ^~~~~~~~~~~~~~~~~~
c:\_repo\project\nrf9160\cloud_client\src\testpin.c:72:12: note: in expansion of macro 'DEVICE_DT_GET'
   72 |     port = DEVICE_DT_GET(TP_GPIO_CTRL);
      |            ^~~~~~~~~~~~~
C:\_tools\v1.9.0\zephyr\include\device.h:96:39: note: each undeclared identifier is reported only once for each function it appears in
   96 | #define DEVICE_NAME_GET(name) _CONCAT(__device_, name)
      |                                       ^~~~~~~~~
C:\_tools\v1.9.0\zephyr\include\toolchain\common.h:132:26: note: in definition of macro '_DO_CONCAT'
  132 | #define _DO_CONCAT(x, y) x ## y
      |                          ^
C:\_tools\v1.9.0\zephyr\include\device.h:96:31: note: in expansion of macro '_CONCAT'
   96 | #define DEVICE_NAME_GET(name) _CONCAT(__device_, name)
      |                               ^~~~~~~
C:\_tools\v1.9.0\zephyr\include\device.h:291:37: note: in expansion of macro 'DEVICE_NAME_GET'
  291 | #define DEVICE_DT_NAME_GET(node_id) DEVICE_NAME_GET(Z_DEVICE_DT_DEV_NAME(node_id))
      |                                     ^~~~~~~~~~~~~~~
C:\_tools\v1.9.0\zephyr\include\device.h:311:34: note: in expansion of macro 'DEVICE_DT_NAME_GET'
  311 | #define DEVICE_DT_GET(node_id) (&DEVICE_DT_NAME_GET(node_id))
      |                                  ^~~~~~~~~~~~~~~~~~
c:\_repo\project\nrf9160\cloud_client\src\testpin.c:72:12: note: in expansion of macro 'DEVICE_DT_GET'
   72 |     port = DEVICE_DT_GET(TP_GPIO_CTRL);
      |            ^~~~~~~~~~~~~

I am not sure how to interpret these errors. To me it appears that the compiler creates a node name through the macros used, and it does not match the node name given in the dts file. I am having trouble getting out of this what name the compiler actually expects; where exactly have I made my error and what should I do to fix it.

Can anyone here point me in the right direction?

Parents
  • For future visitors, I have figured out what I was missing.

    I was unaware that the device tree file is only half of the story and that the system also needs a binding to link the dts configuration to a template which specifies the possible fields of a dts node. This binding is what you put in the "compatible" field.

    In my case I defined a file in my board folder under dts/bindings/eac,testpin.yaml, which contains:

    description: GPIO used as testpin
    
    compatible: "eac,testpin"
    
    include: base.yaml
    
    properties:
      status:
        required: true
    
      gpios:
        type: phandle-array
        required: true
        description: |
          GPIO to use as testpin.

    And added to my dts node:

    tp: testpin {
    	compatible = "eac,testpin";
    	gpios = <&gpio0 22 0>;
    	status = "okay";
    };

Reply
  • For future visitors, I have figured out what I was missing.

    I was unaware that the device tree file is only half of the story and that the system also needs a binding to link the dts configuration to a template which specifies the possible fields of a dts node. This binding is what you put in the "compatible" field.

    In my case I defined a file in my board folder under dts/bindings/eac,testpin.yaml, which contains:

    description: GPIO used as testpin
    
    compatible: "eac,testpin"
    
    include: base.yaml
    
    properties:
      status:
        required: true
    
      gpios:
        type: phandle-array
        required: true
        description: |
          GPIO to use as testpin.

    And added to my dts node:

    tp: testpin {
    	compatible = "eac,testpin";
    	gpios = <&gpio0 22 0>;
    	status = "okay";
    };

Children
No Data
Related