Unable to get I2C device on RED-V board

Hello,

I am working with a Sparkfun RED-V board and I am unable to get the I2C device struct.

I need it to be able to utilize a series of peripherals connected through the Qwiic port. According to the official Sparkfun website the Qwicc libraries are not available on Zephyr yet but as far as I understand I should still be able to access the sensors through I2C.

I am working in VSCode with platformIO. Here’s a snippet of the device tree:

		gpio0: gpio@10012000 {
			compatible = "sifive,gpio0";
			gpio-controller;
			interrupt-parent = < &plic >;
			interrupts = < 0x8 0x1 >, < 0x9 0x1 >, < 0xa 0x1 >, < 0xb 0x1 >, < 0xc 0x1 >, < 0xd 0x1 >, < 0xe 0x1 >, < 0xf 0x1 >, < 0x10 0x1 >, < 0x11 0x1 >, < 0x12 0x1 >, < 0x13 0x1 >, < 0x14 0x1 >, < 0x15 0x1 >, < 0x16 0x1 >, < 0x17 0x1 >, < 0x18 0x1 >, < 0x19 0x1 >, < 0x1a 0x1 >, < 0x1b 0x1 >, < 0x1c 0x1 >, < 0x1d 0x1 >, < 0x1e 0x1 >, < 0x1f 0x1 >, < 0x20 0x1 >, < 0x21 0x1 >, < 0x22 0x1 >, < 0x23 0x1 >, < 0x24 0x1 >, < 0x25 0x1 >, < 0x26 0x1 >, < 0x27 0x1 >;
			reg = < 0x10012000 0x1000 >;
			reg-names = "control";
			label = "gpio_0";
			status = "okay";
			#gpio-cells = < 0x2 >;
			#address-cells = < 0x1 >;
			#size-cells = < 0x1 >;
			ranges;
			phandle = < 0x9 >;
			pinctrl: pinctrl@10012038 {
				compatible = "sifive,iof";
				reg = < 0x10012038 0x8 >;
			};
		};
		i2c0: arduino_i2c: i2c@10016000 {
			compatible = "sifive,i2c0";
			interrupt-parent = < &plic >;
			interrupts = < 0x34 0x1 >;
			reg = < 0x10016000 0x1000 >;
			reg-names = "control";
			label = "I2C_0";
			status = "okay";
			#address-cells = < 0x1 >;
			#size-cells = < 0x0 >;
			input-frequency = < 0xf42400 >;
			clock-frequency = < 0x186a0 >;
		};

Every GPIO pin can implement up to 2 HW-Driven functions (IOF) and from the FE310 manual looks like GPIO_12 can be configured with I2C0_SDA and as far as my understanding goes (I’m new to the embedded world) getting the i2c0 device should take care of configuring the GPIO pin as well, but please let me know if I’m wrong.

I tried

   const struct device *i2c_dev = device_get_binding("I2C_0");
    
    if (!i2c_dev) {
    printk("Failed to get I2C device\n");
     }

but the pointer is always null.

I tried with the i2c0 as a parameter but no success either.

Tested with macros as well:

#define MY_DEVICE DT_PATH(soc, i2c_10016000)

void main(void)
{
    const struct device *const dev = DEVICE_DT_GET(MY_DEVICE);

    if (!device_is_ready(dev)) {
        printk("Failed to get I2C device\n");
        return;
    }
}

but I get the following error when building:

/home/pc/.platformio/packages/toolchain-riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/bin/ld.bfd: .pio/build/sparkfun_redboard_v/src/main.o: in function `.L0 ':
/home/pc/.platformio/packages/framework-zephyr/include/device.h:573: undefined reference to `__device_dts_ord_19'
/home/pc/.platformio/packages/toolchain-riscv/bin/../lib/gcc/riscv64-unknown-elf/8.3.0/../../../../riscv64-unknown-elf/bin/ld.bfd: /home/pc/.platformio/packages/framework-zephyr/include/device.h:573: undefined reference to `__device_dts_ord_19'
collect2: error: ld returned 1 exit status
*** [.pio/build/sparkfun_redboard_v/zephyr/firmware-pre.elf] Error 1

For instance, I have no issues with getting the gpio device and configure them:

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

#define PIN 5

void main(void) {


    const struct device *gpio_dev = device_get_binding("gpio_0");
    if (!gpio_dev) {
        printk("Cannot find GPIO device!\n");
        return;
    }

    // Configure GPIO pin 5 as an output
    int ret = gpio_pin_configure(gpio_dev, PIN, GPIO_OUTPUT);
    if (ret) {
        printk("Error configuring GPIO pin!\n");
        return;
    }

    while (1) {
        // Set the state of the GPIO pin to high (ON)
        ret = gpio_pin_set(gpio_dev, PIN, 1);
        if (ret) {
            printk("Error setting GPIO pin!\n");
            return;
        }

        k_sleep(K_MSEC(500));

        // Set the state of the GPIO pin to low (OFF)
        ret = gpio_pin_set(gpio_dev, PIN, 0);
        if (ret) {
            printk("Error setting GPIO pin!\n");
            return;
        }

        k_sleep(K_MSEC(500));
    }
}

I just seem to not be able to get the I2C device (and UART).
Any clue on what might be wrong?

1 Like

That doesn’t really look like what I’m seeing on https://blog.golioth.io/how-to-use-zephyr-shell-for-interactive-prototyping-with-i2c-sensors/ and https://docs.zephyrproject.org/latest/build/dts/howtos.html#use-devicetree-overlays, are you sure?

Do you mean the I2C node structure in the device tree doesn’t add up? It’s from the automatically generated zephyr.dts file for that board, I haven’t touched it.

I am a bit lost and overwhelmed to be honest. Thank you so much for the links, I’ll read the article and the documentation and see what I can do!

Hello,

quick update for anyone that might have a similar problem.

I posted the same question on the Zephyr github and it turns out that PlatformIO was the problem: https://github.com/zephyrproject-rtos/zephyr/discussions/61655#discussioncomment-6777569.

Using native Zephyr is not as straightforward as using PlatformIO but I can access my I2C device now.