TWIM (I2C) on NCS is not working properly.

First of all, the fast mode should be 400kHz, but it seems to be only 200kHz according to the waveform. Also, the duty cycle seems to be wrong.

Secondly, It seems that CONFIG_I2C_CALLBACK is not working at all. I have written the callback function as follows, but it is not called.

/* Callback */
K_SEM_DEFINE(k_sem, 0, 1);
static void twim_callback(const struct device *dev, int result, void *data)
{
    printk("Callback\n");
    k_sem_give(&k_sem);
}
That is obvious since there is no log display and no semaphore to go through.
I am working on a project using TWIM and I hope these bugs will be fixed soon.
Parents Reply Children
  • Hello,

    I am really sorry for the delays, I am struggling a bit to find out about the internal workings of zephyr's I2C driver myself.

    I am trying to consult my colleagues to get more insight into that.

    You may want to look into the nordic's zephyr I2C driver in ncs/zephyr/drivers/i2c, i2c_nrfx_twim.c and i2c_nrfx_twi.c as well.

    There you can find this snippet:

    static const struct i2c_driver_api i2c_nrfx_twim_driver_api = {
        .configure   = i2c_nrfx_twim_configure,
        .transfer    = i2c_nrfx_twim_transfer,
        .recover_bus = i2c_nrfx_twim_recover_bus,
    };

    Which sets the api->transfer to i2c_nrfx_twim_transfer.

    Best regards,

    Michal

  • Hello,

    Sorry, I was handling another job and neglected this matter.

    As you say, i2c_nrfx_twim.c uses the i2c_driver_api structure to set up each callbacks. That of course includes i2c_nrfx_twim_transfer.
    But when I actually debug the program and look into the contents of the device structure, only the address of i2c_nrfx_twim_transfer is 0(null).
    What does this mean? I can think it is a bug.

  • Hello,

    Finally I understood. The snippet in i2c_nrfx_twim.c is wrong. Because the transfer callback element is transfer_cb, not transfer.

    Here is the snippet in i2c.h.

    __subsystem struct i2c_driver_api {
    	i2c_api_configure_t configure;
    	i2c_api_get_config_t get_config;
    	i2c_api_full_io_t transfer;
    	i2c_api_target_register_t target_register;
    	i2c_api_target_unregister_t target_unregister;
    #ifdef CONFIG_I2C_CALLBACK
    	i2c_api_transfer_cb_t transfer_cb;
    #endif
    	i2c_api_recover_bus_t recover_bus;
    };
    

  • Hello,

    Thank you for the information. I am not exactly sure if the transfer_cb should be defined in the driver directly, but I will discuss it with the developers.

    I have talked with a colleague and he has pointed me to this pull request where the I2C callbacks got implemented and there is a test example.

    You may also want to just use the nrfx_twim driver directly for callbacks, since the Zephyr driver may be missing some functionality as well.

    Best regards,

    Michal

  • A small update: looks like callbacks are not implemented in the Nordic Zephyr I2C driver yet.

    Please use nrfx_twim driver directly.

    Best regards,

    Michal

Related