Page 1 of 1

Converting old I2C code to the new driver causes device to crash loop

Posted: Wed Jul 09, 2025 3:27 pm
by TeFahr
Hello all,

I'm trying to convert some old I2C code (using i2c.h) to the new driver (using i2c_master.h) and I'm running into some issues I cannot explain. The old code works, but the new code panics and keeps crashing the device. I am sure I've overlooked something, but I've been staring at this for some days now and I just can't figure it out. Hopefully someone here can point out where the error is...

This is a very rudimentary bit of code for reading a touch controller, originally adapted from an Arduino example.

The code that works;

Code: Select all

#define I2C_SDA GPIO_NUM_2
#define I2C_SCL GPIO_NUM_1
const int i2c_touch_addr = 0x38;

bool init_i2c()
{
    i2c_config_t i2c_conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_SDA,
        .scl_io_num = I2C_SCL,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master = {
            .clk_speed = 100000,
        },
        .clk_flags = I2C_SCLK_SRC_FLAG_FOR_NOMAL,
    };

    if (i2c_param_config(I2C_NUM_0, &i2c_conf) != ESP_OK)
    {
        return false;
    }

    if (i2c_driver_install(I2C_NUM_0, I2C_MODE_MASTER, 0, 0, 0) != ESP_OK)
    {
        return false;
    }

    return true;
}

int readTouchReg(uint8_t reg)
{
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, i2c_touch_addr << 1 | I2C_MASTER_WRITE, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, reg, I2C_MASTER_ACK);
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (i2c_touch_addr << 1) | I2C_MASTER_READ, true);
    uint8_t result;
    i2c_master_read_byte(cmd, &result, I2C_MASTER_NACK);
    i2c_master_stop(cmd);
    i2c_master_cmd_begin(I2C_NUM_0, cmd, pdMS_TO_TICKS(1000));
    i2c_cmd_link_delete(cmd);
    return result;
}
And the new code that panics the device and makes it reboot forever;

Code: Select all

#define I2C_SDA GPIO_NUM_2
#define I2C_SCL GPIO_NUM_1
const int i2c_touch_addr = 0x38;
i2c_master_dev_handle_t touch_handle;
i2c_master_bus_handle_t bus_handle;

bool init_i2c()
{
    i2c_master_bus_config_t conf;
    conf.clk_source = I2C_CLK_SRC_DEFAULT;
    conf.i2c_port= I2C_NUM_0;
    conf.sda_io_num = I2C_SDA;
    conf.scl_io_num = I2C_SCL;
    conf.glitch_ignore_cnt = 7;
    conf.flags.enable_internal_pullup = GPIO_PULLUP_ENABLE;
    conf.intr_priority = 0;
    conf.trans_queue_depth = 10;

    if (i2c_new_master_bus(&conf, &bus_handle) != ESP_OK)
    {
        return false;
    }

    i2c_device_config_t touch_config;
    touch_config.dev_addr_length = I2C_ADDR_BIT_LEN_7;
    touch_config.device_address = i2c_touch_addr;
    touch_config.scl_speed_hz = 100000;

    if (i2c_master_bus_add_device(bus_handle, &touch_config, &touch_handle) != ESP_OK)
    {
        return false;
    }

    return true;
}

int readTouchReg(uint8_t reg)
{
    uint8_t result;
    uint8_t data[2] = {i2c_touch_addr, reg};
    //i2c_master_transmit(touch_handle, data, 2, 1000); // crash loops?
    i2c_master_transmit_receive(touch_handle, data, 2, &result, 1, 1000);
    return result;
}
I initially thought it was because of the buffer or something, but just doing a transmit has the same panic behaviour.

Can someone point out what I'm doing wrong here?

Thanks!