CST816S input driver i2c failed to read

I have problem with i2c that can't read the cst816s, its always return log message `<err> cst816s: failed reading chip id` and `<err> cst816s: Could not read x data` when touched. i'm using the nRF52832. is there any configuration i need to do?

the board device tree: 

/dts-v1/;
#include <nordic/nrf52832_qfaa.dtsi>

...

&flash0 {
	partitions {
		compatible = "fixed-partitions";
		#address-cells = <1>;
		#size-cells = <1>;

		boot_partition: partition@0 {
			label = "mcuboot";
			reg = <0x00000000 DT_SIZE_K(48)>;
		};

		slot0_partition: partition@c000 {
			label = "image-0";
			reg = <0x0000c000 DT_SIZE_K(220)>;
		};

		slot1_partition: partition@43000 {
			label = "image-1";
			reg = <0x00043000 DT_SIZE_K(220)>;
		};

		storage_partition: partition@7a000 {
			label = "storage";
			reg = <0x0007a000 DT_SIZE_K(24)>;
		};
	};
};
&gpio0 {
	status = "okay";
};

&gpiote {
	status = "okay";
};

&rtc2 {
	status = "okay";
};

&uart0 {
	status = "okay";
	pinctrl-0 = <&uart0_default>;
	pinctrl-1 = <&uart0_sleep>;
	pinctrl-names = "default", "sleep";
	current-speed = <115200>;
};

&i2c1 {
	status = "okay";
	pinctrl-0 = <&i2c1_default>;
	pinctrl-1 = <&i2c1_sleep>;
	pinctrl-names = "default", "sleep";
};

the pinctrl file:

&pinctrl {
	uart0_default: uart0_default {
		group1 {
			psels = <NRF_PSEL(UART_TX, 0, 24)>, <NRF_PSEL(UART_RX, 0, 23)>;
		};
	};

	uart0_sleep: uart0_sleep {
		group1 {
			psels = <NRF_PSEL(UART_TX, 0, 24)>, <NRF_PSEL(UART_RX, 0, 23)>;
			low-power-enable;
		};
	};

	spi0_default: spi0_default {
		group1 {
			psels = <NRF_PSEL(SPIM_MOSI, 0, 29)>, <NRF_PSEL(SPIM_SCK, 0, 28)>;
		};
	};

	spi0_sleep: spi0_sleep {
		group1 {
			psels = <NRF_PSEL(SPIM_MOSI, 0, 29)>, <NRF_PSEL(SPIM_SCK, 0, 28)>;
			low-power-enable;
		};
	};

	i2c1_sleep: i2c1_sleep {
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 9)>, <NRF_PSEL(TWIM_SCL, 0, 10)>;
			low-power-enable;
		};
	};

	i2c1_default: i2c1_default {
		group1 {
			psels = <NRF_PSEL(TWIM_SDA, 0, 9)>, <NRF_PSEL(TWIM_SCL, 0, 10)>;
		};
	};
};

the overlay file:

/ {
    chosen {
        zephyr,display = &display;
        zephyr,keyboard-scan = &touch_screen;
    };

    aliases {
        input = &touch_screen;
    };

    leds {
        compatible = "gpio-leds";
        lcd_backlight: lcd_backlight {
            gpios = <&gpio0 11 GPIO_ACTIVE_LOW>;
            label = "LCD Backlight";
        };
    };

    lvgl_pointer_input:lvgl_pointer {
        compatible = "zephyr,lvgl-pointer-input";
        input = <&touch_screen>;
    };
};

&spi0 {
    compatible = "nordic,nrf-spim";
	status = "okay";
	pinctrl-0 = <&spi0_default>;
	pinctrl-1 = <&spi0_sleep>;
	pinctrl-names = "default", "sleep";
	cs-gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;

	display: st7789v@0 {
        label = "ST7789 Display";
		compatible = "sitronix,st7789v";
        spi-max-frequency = <20000000>;
        reg = <0>;
        cmd-data-gpios = < &gpio0 27 GPIO_ACTIVE_LOW>;
        reset-gpios = < &gpio0 31 GPIO_ACTIVE_LOW>;
        width = <240>;
        height = <240>;
        x-offset = <0>;
        y-offset = <0>;
        vcom = <0x19>;
        gctrl = <0x35>;
        vrhs = <0x12>;
        vdvs = <0x20>;
        mdac = <0x00>;
        gamma = <0x01>;
        colmod = <0x05>;
        lcm = <0x2c>;
        porch-param = [0c 0c 00 33 33];
        cmd2en-param = [5a 69 02 01];
        pwctrl1-param = [a4 a1];
        pvgam-param = [D0 04 0D 11 13 2B 3F 54 4C 18 0D 0B 1F 23];
        nvgam-param = [D0 04 0C 11 13 2C 3F 44 51 2F 1F 1F 20 23];
        ram-param = [00 F0];
        rgb-param = [CD 08 14];
	};
};

&i2c1 {
    clock-frequency = <I2C_BITRATE_FAST>;

    touch_screen: cst186s@15 {
        label = "CST816S Touch Screen";
        status = "okay";
        compatible = "hynitron,cst816s";
        reg = <0x15>;
        irq-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
        rst-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
    };
};

  • Hi,

    Are you able to get logic analyzer or oscilloscope readings from the I2C?

    Regards,
    Sigurd Hellesvik

  • Hi, thanks for your response. As you can see, there is nothing on the i2c reading with zephyr. I have tried it with other frameworks and it still works fine. I'm still curious what makes i2c (with gpio sda 9 and gpio scl 10) not output any data, maybe I missed something when setting up the board devicetree or overlay.

    I2c readings with other framework:

    I2c readings with zephyr:

  • Looks like you are using the cst816s drivers directly.
    I found a Zephyr issue where another user has exactly the same issue:
    https://github.com/zephyrproject-rtos/zephyr/discussions/74678. Im not sure if it is related or not, but worth knowing about.

    nanangcreacoll said:
    I2c readings with other framework:

    This is good to know. It shows that the hardware works correctly, and that this is a software issue.

    I suggest that you start by trying to use I2C directly to read the device ID.
    You can do this by following the DevAcademy Fundamentals: I2C lesson

    This way, you get some firmware to compare with. Then we can compare the working I2C with the cst816s driver.

  • Here I try directly using I2C to initialize CST816S. I try to make my own device tree binding for CST816S. I still don't know which part I should fix, I2C still can't read the chip. RST and IRQ gpio work fine.

    overlay file:

    &i2c1 {
    	cst816s: cst816s@15 {
    		compatible = "cst816s";
    		status = "okay";
    		reg = <0x15>;
    		irq-gpios = <&gpio0 26 GPIO_ACTIVE_LOW>;
    		rst-gpios = <&gpio0 21 GPIO_ACTIVE_LOW>;
    	};
    };

    main code:

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/drivers/gpio.h>
    #include <zephyr/drivers/i2c.h>
    
    #define LOG_LEVEL LOG_LEVEL_DBG
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(app, LOG_LEVEL);
    
    #define CST816S_NODE DT_NODELABEL(cst816s)
    
    #define CST816S_I2C_ADDR 0x15
    #define CST816S_I2C_CHIP_ID_REG 0xA7
    
    struct cst816s_data
    {
            const struct i2c_dt_spec *i2c;
            struct k_work work;
            struct gpio_callback irq_gpio_cb;
    };
    
    static int cst816s_reset(const struct gpio_dt_spec *rst_gpio)
    {
            LOG_DBG("CST816S Reset");
    
            int ret;
    
            if (!gpio_is_ready_dt(rst_gpio))
            {
                    LOG_ERR("RST GPIO not ready");
                    return -ENODEV;
            }
    
            ret = gpio_pin_configure_dt(rst_gpio, GPIO_OUTPUT);
            if (ret < 0)
            {
                    LOG_ERR("Failed to configure RST GPIO: %d", ret);
                    return ret;
            }
            
            ret = gpio_pin_set_dt(rst_gpio, 1);
            if (ret < 0)
            {
                    LOG_ERR("Failed to set RST GPIO: %d", ret);
                    return ret;
            }
            k_msleep(5);
            ret = gpio_pin_set_dt(rst_gpio, 0);
            if (ret < 0)
            {
                    LOG_ERR("Failed to set RST GPIO: %d", ret);
                    return ret;
            }
            k_msleep(50);
    
            return 0;
    }
    
    static void cst816s_irq_handler(const struct device *dev, struct gpio_callback *cb, uint32_t pins)
    {
            struct cst816s_data *data = CONTAINER_OF(cb, struct cst816s_data, irq_gpio_cb);
    
            k_work_submit(&data->work);
    }
    
    static int cst816s_irq_init(const struct gpio_dt_spec *irq_gpio, struct gpio_callback *irq_gpio_cb)
    {
            LOG_DBG("CST816S IRQ Initialization");
    
            int ret;
    
            if (!gpio_is_ready_dt(irq_gpio))
            {
                    LOG_ERR("IRQ GPIO not ready");
                    return -ENODEV;
            }
    
            ret = gpio_pin_configure_dt(irq_gpio, GPIO_INPUT);
            if (ret < 0)
            {
                    LOG_ERR("Failed to configure IRQ GPIO: %d", ret);
                    return ret;
            }
    
            ret = gpio_pin_interrupt_configure_dt(irq_gpio, GPIO_INT_EDGE_TO_ACTIVE);
            if (ret < 0)
            {
                    LOG_ERR("Failed to configure IRQ GPIO interrupt: %d", ret);
                    return ret;
            }
    
            gpio_init_callback(irq_gpio_cb, cst816s_irq_handler, BIT(irq_gpio->pin));
            ret = gpio_add_callback(irq_gpio->port, irq_gpio_cb);
            if (ret < 0)
            {
                    LOG_ERR("Failed to add IRQ GPIO callback: %d", ret);
                    return ret;
            }
    
            return 0;
    }
    
    static int cst816s_process(const struct i2c_dt_spec *cst816s)
    {
            LOG_DBG("CST816S Process");
    
            if (!i2c_is_ready_dt(cst816s))
            {
                    LOG_ERR("CST816S I2C device not ready");
                    return -ENODEV;
            }
    
            return 0;
    }
    
    static void cst816s_work_handler(struct k_work *work)
    {
            struct cst816s_data *data = CONTAINER_OF(work, struct cst816s_data, work);
            
            cst816s_process(data->i2c);
    }
    
    static int cst816s_init (const struct i2c_dt_spec *cst816s, const struct gpio_dt_spec *rst_gpio, const struct gpio_dt_spec *irq_gpio, struct cst816s_data *data)
    {
            LOG_DBG("CST816S Initialization");
    
            int ret;
            uint8_t chip_id = 0;
    
            ret = cst816s_reset(rst_gpio);
            if (ret < 0)
            {
                    LOG_ERR("Failed to reset CST816S chip: %d", ret);
                    return ret;
            }
            LOG_DBG("CST816S Chip Reset complete");
    
            ret = cst816s_irq_init(irq_gpio, &data->irq_gpio_cb);
            if (ret < 0)
            {
                    LOG_ERR("Failed to initialize CST816S IRQ: %d", ret);
                    return ret;
            }
            LOG_DBG("CST816S IRQ initialized successfully");
    
            ret = i2c_reg_read_byte_dt(cst816s, CST816S_I2C_CHIP_ID_REG, &chip_id);
            if (ret < 0)
            {
                    LOG_ERR("Failed to read chip ID: %d", ret);
                    return ret;
            }
            LOG_DBG("CST816S Chip ID: 0x%02X", chip_id);
    
            return 0;
    }
    
    int main()
    {
            LOG_DBG("CST816S Touchscreen I2C Test");
    
            const struct i2c_dt_spec cst816s_i2c = I2C_DT_SPEC_GET(CST816S_NODE);
            if (!i2c_is_ready_dt(&cst816s_i2c))
            {
                    LOG_ERR("CST816S I2C device not ready");
                    return -ENODEV;
            }
            LOG_DBG("CST816S I2C device (bus %d, addr 0x%02X)", cst816s_i2c.bus->name, cst816s_i2c.addr);
    
            const struct gpio_dt_spec cst816s_rst_gpio = GPIO_DT_SPEC_GET(CST816S_NODE, rst_gpios);
            if (!gpio_is_ready_dt(&cst816s_rst_gpio))
            {
                    LOG_ERR("RST GPIO not ready");
                    return -ENODEV;
            }
            LOG_DBG("RST GPIO (port %d, pin %d)", cst816s_rst_gpio.port->name, cst816s_rst_gpio.pin);
            const struct gpio_dt_spec cst816s_irq_gpio = GPIO_DT_SPEC_GET(CST816S_NODE, irq_gpios);
            if (!gpio_is_ready_dt(&cst816s_irq_gpio))
            {
                    LOG_ERR("IRQ GPIO not ready");
                    return -ENODEV;
            }
            LOG_DBG("IRQ GPIO (port %d, pin %d)", cst816s_irq_gpio.port->name, cst816s_irq_gpio.pin);
    
            struct cst816s_data data;
            data.i2c = &cst816s_i2c;
    
            k_work_init(&data.work, cst816s_work_handler);
    
            int ret;
    
            ret = cst816s_init(&cst816s_i2c, &cst816s_rst_gpio, &cst816s_irq_gpio, &data);
            if (ret < 0)
            {
                    LOG_ERR("Failed to initialize CST816S: %d", ret);
                    return ret;
            }
            LOG_DBG("CST816S initialized successfully");
    
            while(1)
            {
                    k_msleep(1);
            }
    
            return 0;
    }

    log output:

    *** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
    *** Using Zephyr OS v3.6.99-100befc70c74 ***
    [00:00:00.431,335] <dbg> app: main: CST816S Touchscreen I2C Test
    [00:00:00.431,365] <dbg> app: main: CST816S I2C device (bus i2c@40004000, addr 0x15)
    [00:00:00.431,396] <dbg> app: main: RST GPIO (port gpio@50000000, pin 21)
    [00:00:00.431,427] <dbg> app: main: IRQ GPIO (port gpio@50000000, pin 26)
    [00:00:00.431,457] <dbg> app: cst816s_init: CST816S Initialization
    [00:00:00.431,457] <dbg> app: cst816s_reset: CST816S Reset
    [00:00:00.486,633] <dbg> app: cst816s_init: CST816S Chip Reset complete
    [00:00:00.486,663] <dbg> app: cst816s_irq_init: CST816S IRQ Initialization
    [00:00:00.486,694] <dbg> app: cst816s_init: CST816S IRQ initialized successfully
    [00:00:00.486,785] <err> app: Failed to read chip ID: -5
    [00:00:00.486,816] <err> app: Failed to initialize CST816S: -5
    [00:16:50.213,226] <dbg> app: cst816s_process: CST816S Process

Related