Hello Devzone Community,
I am facing a run time, peripheral or sensor initialization error in a Zephyr based app, built using sdk-nrf v1.6.1, and its corresponding Zephyr RTOS release 2.6.0. More specifically, I am having trouble porting a firmware project which runs correctly on a Thingy91_nrf9160 dev kit, to a new custom board with a similar layout.
With the Thingy91, I began with the aws_iot client sample app. I then manually incorporated a Nordic I2C sample app with this, to get a feel for and see the I2C subsystem and Zephyr device driver API working. To this I was able to add an external sensor, disable the onboard one by commenting out pertinent lines of DTS code in [west_workspace]/nrf/boards/arm/thingy91_nrf9160/thingy91_nrf9160_common.dts, and enable the external sensor on &i2c2.
For curiosity I also confirmed that my modified aws_iot sample app could talk to both sensors on &i2c2.
The major change I am working through is adapting to a custom board. While I cannot share a schematic of the custom board -- it is work related and not a personal project -- I can say that the board is similar to the Thingy91 in its employment of an nrf9160 SiP, and one or more sensors on an I2C bus. The specific error I'm finding arises when firmware calls a Zephyr API routine:
if (!device_is_ready(sensor))
In this case my sensor data structure / pointer is declared this way:
const struct device *sensor = DEVICE_DT_GET_ANY(st_iis2dh);
In the primary device tree source file, I have configured the code this way to reflect the sensor's hard wiring, and to set I2C clock and data pins as needed:
&i2c2 {
compatible = "nordic,nrf-twim";
status = "okay";
sda-pin = <6>;
scl-pin = <5>;
clock-frequency = <I2C_BITRATE_FAST>;
};
In an overlay file, I append my sensor of interest to the app processor I2C2 peripheral:
&i2c2 {
stmicro_sen18: iis2dh@18 {
status = "okay";
compatible = "st,iis2dh";
reg = <0x18>;
label = "IIS2DH";
};
As I am no longer building firmware for the thing91_nrf9160 board, I have also redirected Zephyr + Nordic toolchain to look for the custom board file in a more local place. Per instructions at docs.zephyrproject.org/.../index.html I have added next stanza to my project CMakeLists.txt file:
set(BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
And this is followed immediately in CMakeLists.txt by the lines:
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(aws-iot-stand-alone)
In all the DTS files of which I'm aware for this project I find no other references to the application processor's (ARM M33) GPIO pins P0.5 and P0.6. From what I can tell these are not being used by nor for any other peripherals. My firmware builds, it executes, but when firmware call's Zephyr's `device_is_ready()` API function, the I2C peripheral is reported as not ready.
Returning to this run time failure, the furthest I can trace things is:
* device_is_ready(device_struct_ptr) returns `device_usable_check(dev) == 0`
* device_usable_check(dev) returns `z_device_ready(dev) ? 0 : -ENODEV;`
* z_device_ready(dev) returns `dev->state->initialized && (dev->state->init_res == 0U);`
When I printk() those two elements of my sensor device's state, initialized shows as 'true' and init_res shows as '5'. Zephyr Project documentation says that Zephyr uses its given minimal C library errno.h as its defining list of named error types. From [west_workspace]/zephyr/lib/libc/minimal/include/errno.h I find this meaning for error 5:
38 #define errno (*z_errno())
39
40 #define EPERM 1 /**< Not owner */
41 #define ENOENT 2 /**< No such file or directory */
42 #define ESRCH 3 /**< No such context */
43 #define EINTR 4 /**< Interrupted system call */
44 #define EIO 5 /**< I/O error */
. . .
Electrically what I can see is that the sensor on the custom board is powered. I2C clock and data lines are pulled high to their 1p8V rail. At firmware boot time SCL and SDA both go to ground for a brief moment, but there's no data packet and they quickly rise again to 1.8V. The I2C bus is just quiet, no activity. Nor is there indication that Zephyr tries to talk on the bus after device_is_ready() returns a failed status.
The sensor module I have is working. It's on a break out board which I have jumper-wired to both Thingy91 and custom board, and back again. I do not see contention on the custom board's I2C lines. In the absence of an obvious hardware problem I am struggling to find the root cause of `init_res == 5`.
If init_res == 5 means there is an general I/O error, I’d expect missing power or bus contention to be a couple likely causes for this, on an I2C bus with one peripheral device connected. If I have correctly ruled these hardware faults out, what else could cause Zephyr to return `init_res` equal to 5?
Has anyone else confronted and solved a problem like this? Is there a DTS or Kconfig mis-configuration which can produce this error at Zephyr run time?
- Ted