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>;
    };
};

Parents
  • 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

  • nanangcreacoll said:
    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.

    Alright, then we have tried two different ways to read the CST816S over I2C.

    At this point, I think it would be a good idea to look at the hardware.

    How do you connect the CST to the nRF?
    Do you have another I2C device that you can try to read with the nRF, to verify that the I2C code work?

  • I use this board, connect the touch screen with the socket on the board.

    I have a PCF8574 GPIO Expander that I am using to try out I2C, it can read and write to the PCF8574.

    Main code with PCF8574:

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/drivers/i2c.h>
    
    #define LOG_LEVEL LOG_LEVEL_DBG
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(app, LOG_LEVEL);
    
    #define PCF8574_NODE DT_NODELABEL(pcf8574)
    
    int main(void)
    {
            const struct i2c_dt_spec pcf8574 = I2C_DT_SPEC_GET(PCF8574_NODE);
            if (!i2c_is_ready_dt(&pcf8574))
            {
                    LOG_ERR("I2C device not ready");
                    return -ENODEV;
            }
    
            int ret;
            uint8_t data = 0;
            
            ret = i2c_read_dt(&pcf8574, &data, sizeof(data));
            if (ret < 0)
            {
                    LOG_ERR("Failed to read data: %d", ret);
                    return ret;
            }
            LOG_DBG("Initial data read: 0x%02X", data);
    
            while(1)
            {
                    uint8_t read_data;
                    
                    ret = i2c_write_read_dt(&pcf8574, &data, sizeof(data), &read_data, sizeof(read_data));
                    if (ret < 0)
                    {
                            LOG_ERR("Failed to write/read data: %d", ret);
                    }
                    LOG_DBG("Wrote data: 0x%02X, Read data: 0x%02X", data, read_data);
    
                    if (data == 0)
                    {
                            data = 1;
                    }
                    else if (data & 0x80)
                    {
                            data = 0;
                    }
                    else
                    {
                            data <<= 1;
                    }
                    
                    k_msleep(1000);
            }
            return 0;
    }

    Output log:

    ** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
    *** Using Zephyr OS v3.6.99-100befc70c74 ***
    [00:00:00.391,174] <dbg> app: main: Initial data read: 0xFF
    [00:00:00.391,387] <dbg> app: main: Wrote data: 0xFF, Read data: 0xFF
    [00:00:01.391,632] <dbg> app: main: Wrote data: 0x00, Read data: 0x00
    [00:00:02.391,967] <dbg> app: main: Wrote data: 0x01, Read data: 0x01
    [00:00:03.392,303] <dbg> app: main: Wrote data: 0x02, Read data: 0x02
    [00:00:04.392,639] <dbg> app: main: Wrote data: 0x04, Read data: 0x04
    [00:00:05.392,974] <dbg> app: main: Wrote data: 0x08, Read data: 0x08
    [00:00:06.393,310] <dbg> app: main: Wrote data: 0x10, Read data: 0x10
    [00:00:07.393,646] <dbg> app: main: Wrote data: 0x20, Read data: 0x20
    [00:00:08.393,981] <dbg> app: main: Wrote data: 0x40, Read data: 0x40
    [00:00:09.394,317] <dbg> app: main: Wrote data: 0x80, Read data: 0x80

    Is there a possible problem with the board? I've used it with other platforms and it works fine.

Reply
  • I use this board, connect the touch screen with the socket on the board.

    I have a PCF8574 GPIO Expander that I am using to try out I2C, it can read and write to the PCF8574.

    Main code with PCF8574:

    #include <zephyr/kernel.h>
    #include <zephyr/device.h>
    #include <zephyr/devicetree.h>
    #include <zephyr/drivers/i2c.h>
    
    #define LOG_LEVEL LOG_LEVEL_DBG
    #include <zephyr/logging/log.h>
    LOG_MODULE_REGISTER(app, LOG_LEVEL);
    
    #define PCF8574_NODE DT_NODELABEL(pcf8574)
    
    int main(void)
    {
            const struct i2c_dt_spec pcf8574 = I2C_DT_SPEC_GET(PCF8574_NODE);
            if (!i2c_is_ready_dt(&pcf8574))
            {
                    LOG_ERR("I2C device not ready");
                    return -ENODEV;
            }
    
            int ret;
            uint8_t data = 0;
            
            ret = i2c_read_dt(&pcf8574, &data, sizeof(data));
            if (ret < 0)
            {
                    LOG_ERR("Failed to read data: %d", ret);
                    return ret;
            }
            LOG_DBG("Initial data read: 0x%02X", data);
    
            while(1)
            {
                    uint8_t read_data;
                    
                    ret = i2c_write_read_dt(&pcf8574, &data, sizeof(data), &read_data, sizeof(read_data));
                    if (ret < 0)
                    {
                            LOG_ERR("Failed to write/read data: %d", ret);
                    }
                    LOG_DBG("Wrote data: 0x%02X, Read data: 0x%02X", data, read_data);
    
                    if (data == 0)
                    {
                            data = 1;
                    }
                    else if (data & 0x80)
                    {
                            data = 0;
                    }
                    else
                    {
                            data <<= 1;
                    }
                    
                    k_msleep(1000);
            }
            return 0;
    }

    Output log:

    ** Booting nRF Connect SDK v2.7.0-5cb85570ca43 ***
    *** Using Zephyr OS v3.6.99-100befc70c74 ***
    [00:00:00.391,174] <dbg> app: main: Initial data read: 0xFF
    [00:00:00.391,387] <dbg> app: main: Wrote data: 0xFF, Read data: 0xFF
    [00:00:01.391,632] <dbg> app: main: Wrote data: 0x00, Read data: 0x00
    [00:00:02.391,967] <dbg> app: main: Wrote data: 0x01, Read data: 0x01
    [00:00:03.392,303] <dbg> app: main: Wrote data: 0x02, Read data: 0x02
    [00:00:04.392,639] <dbg> app: main: Wrote data: 0x04, Read data: 0x04
    [00:00:05.392,974] <dbg> app: main: Wrote data: 0x08, Read data: 0x08
    [00:00:06.393,310] <dbg> app: main: Wrote data: 0x10, Read data: 0x10
    [00:00:07.393,646] <dbg> app: main: Wrote data: 0x20, Read data: 0x20
    [00:00:08.393,981] <dbg> app: main: Wrote data: 0x40, Read data: 0x40
    [00:00:09.394,317] <dbg> app: main: Wrote data: 0x80, Read data: 0x80

    Is there a possible problem with the board? I've used it with other platforms and it works fine.

Children
Related