This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Symbol not found with device_get_binding

Hello!

I'm currently working with Zephyr on a custom board based on the RAK5010 board. This board (RAK5010) is currently supported by the Zephyr project,uses the NRF52840 chipset and has an BG96 modem.

The problem that I'm facing is that I'm not being able to "get" the device reference with the device_get_binding() macro for the modem node (BG9X), the method keeps returning NULL for me.

I've run through the Troubleshoot device tree section and could see that there are no typos in the code. So I tried to debug it and I'll put what I could observe next.

Regarding the application code, I'm currently with this:

/* The devicetree node identifier for the "quectel_bg9x". */
#define BG96_NODE DT_NODELABEL(quectel_bg9x)

#if !DT_NODE_HAS_STATUS(BG96_NODE, okay)
#error "Unsupported board: bg96 devicetree node is not defined"
#endif

[...]

static const struct device *init_bg96() {
        const struct device *bg96_dev = device_get_binding(DT_LABEL(BG96_NODE));

        if (bg96_dev == NULL) {
                printk("BG96 not found\n");
                return NULL;
        }

        return bg96_dev;
}

void main() {
[...]
        const struct device *bg96_dev = init_bg96();
[...]        
        if (bg96_dev == NULL) {
                while (true) {
                        printk("BG96 modem not found, stopping...\n");
                        printk("prop: %s\n", DT_PROP(DT_NODELABEL(quectel_bg9x), label));
                        k_msleep(2000);
                }
                return;
        }
[...]
}

I've also placed some logs on the zephyr/kernel/device.c file, on the z_impl_device_get_binding() method, as can be seen in the following snippet:

106 const struct device *z_impl_device_get_binding(const char *name)
107 {
108         const struct device *dev;
109 
110         printk("name (target): %s\n", name);
111         /* A null string identifies no device.  So does an empty
112          * string.
113          */
114         if ((name == NULL) || (name[0] == '\0')) {
115                 return NULL;
116         }
117 
118         /* Split the search into two loops: in the common scenario, where
119          * device names are stored in ROM (and are referenced by the user
120          * with CONFIG_* macros), only cheap pointer comparisons will be
121          * performed. Reserve string comparisons for a fallback.
122          */
123         for (dev = __device_start; dev != __device_end; dev++) {
124                 printk("dev->name: %s\n", dev->name);
125                 if (z_device_ready(dev) && (dev->name == name)) {
126                         return dev;
127                 }
128         }
129 
130         for (dev = __device_start; dev != __device_end; dev++) {
131                 if (z_device_ready(dev) && (strcmp(name, dev->name) == 0)) {
132                         return dev;
133                 }
134         }
135 
136         return NULL;
137 }

After flashing the board, I could see these messages on the J-Link RTT viewer:

00> *** Booting Zephyr OS build zephyr-v2.6.0-2010-gdca54e69f2d9  ***
00> name (target): GPIO_0
00> dev->name: CLOCK
00> dev->name: UART_0
00> dev->name: sys_clock
00> dev->name: GPIO_0
00> name (target): UART_0
00> dev->name: CLOCK
00> dev->name: UART_0
00> name (target): SHTC3
00> dev->name: CLOCK
00> dev->name: UART_0
00> dev->name: sys_clock
00> dev->name: GPIO_0
00> dev->name: GPIO_1
00> dev->name: I2C_1
00> dev->name: SHTC3
00> name (target): quectel,bg9x
00> dev->name: CLOCK
00> dev->name: UART_0
00> dev->name: sys_clock
00> dev->name: GPIO_0
00> dev->name: GPIO_1
00> dev->name: I2C_1
00> dev->name: SHTC3
00> BG96 not found
00> BG96 modem not found, stopping...
00> prop: quectel,bg9x
00> BG96 modem not found, stopping...
00> prop: quectel,bg9x
00> BG96 modem not found, stopping...
00> prop: quectel,bg9x

With that log, I could conclude that the binding is probably OK, as I am capable of reading the properties of the bg9x node, and the issue is that the device is not in the device list for some reason.

I could not understand why It's not in that list, however. I tried to see where the list is populated but for what I understood, that structure is either populated at compile time or by a python script (not sure however, I'm not really knowledgeable on compilers/linkers).

Regarding configs, this is how my prj.conf looks like (I've added the CONFIG_MODEM_QUECTEL but it should not be needed as it's automatically selected because of the board config):

CONFIG_GPIO=y
CONFIG_UART_CONSOLE=n
CONFIG_PRINTK=y
CONFIG_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_STDOUT_CONSOLE=y
CONFIG_RTT_CONSOLE=y
CONFIG_USE_SEGGER_RTT=y
CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_SHTCX=y
CONFIG_MODEM_QUECTEL_BG9X=y

And my CMakeLists.txt looks like this:

# Find Zephyr. This also loads Zephyr's build system.
cmake_minimum_required(VERSION 3.13.1)
find_package(Zephyr)
project(poc_geocan_nrf52840)

# Add your source file to the "app" target. This must come after
# find_package(Zephyr) which defines the target.
target_sources(app PRIVATE src/main.c)
target_include_directories(app PRIVATE $ENV{ZEPHYR_BASE}/include/drivers/)

By the way, as can be seen in the logs, I am capable of getting the reference to the UART_0 (which the modem is connected to), but not the modem itself. I need to get the reference to it in order to be able to set the pins and initialize it.

Do you have any idea on what I'm missing here or what I could do in order to debug this issue?

Thanks a lot in advance!

Renato

Parents Reply Children
No Data
Related