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