I2C Shared Bus Across Different Threads - Hanging on Mutex/EventFlag

I have 2 threads accessing several devices on a shared I2C bus - I am using the I2C framework on SSP 1.3.0

 

I thought that with this framework I could open the different instances in different threads such as below and that each write and read etc is thread aware and will automatically acquire and relinquish mutexes etc:

g_sf_i2c_TOUCH.p_api->open(g_sf_i2c_TOUCH.p_ctrl, g_sf_i2c_TOUCH.p_cfg);

g_sf_i2c_Battery_Charger.p_api->open(g_sf_i2c_Battery_Charger.p_ctrl, g_sf_i2c_Battery_Charger.p_cfg);

 

I am however having an issue where there appears to be a deadlock where one thread will not give up the i2c mutex as it seems to be waiting on a event flag. As far as I can tell the UI_Thread needs the i2c mutex but the pwr_mgmt_thread will not relinquish it as it is suspended until this event flag is set - but this event flag is not something I'm explicitly setting in my code:

 

I have tried changing thread priorities but I don't think that is the issue - could anyone shed any light on this? I have the TraceX file but for some reason can't attach it to this post - though am not sure it tells me anything more than the RTOS resources tab. Am I missing something simple?

Thanks

 

 

 

 

  • Hi James,

    Which value is your application using as a wait option in I2C read() or write() functions? If you provided a large value (or TX_WAIT_FOREVER), it will wait until an event flag is set or timeout expires - e.g. for TX_WAIT_FOREVER it can wait infinitely.

    Moreover, are you closing the I2C instance before you're opening a new one? It is necessary, additonally, right after each open(), call lock() and right before each close(), call unlock().

    Regards,
    adboc
  • In reply to adboc:

    I indeed use TX_WAIT_FOREVER. I can give locking/closing a go - is my understanding of how the i2c framework handles mutexes incorrect? In the following thread it says that I can leave the instances open and I thought lock/unlock was only needed when multiple sequential writes are required to a device:

    renesasrulz.com/.../multiple-devices-and-threads-on-the-same-i2c-bus


    garyj
    You can leave the framework open for each device and just do your read, write, and write-read calls at any time from each thread. The framework will handle the mutual exclusion to the bus. In addition, you can lock the bus so that all bus transfers will be only for the thread that dose the lock until the bus is unlocked.
  • In reply to James:

    Hi James,

    Sorry, you're right, closing and locking/unlocking is not necessary, at least not in all cases.
    I suppose power management thread is trying to read some data, isn't it? Is it possible in your case to use wait option different than TX_WAIT_FOREVER? If it waits for incoming data, it'll prevent from communicating to other devices.

    Regards,
    adboc
  • In reply to adboc:

    adboc,

    I am having trouble understanding what is going on - pwr_mgmt_thread opens instances and also reads/writes, such as below:

    g_sf_i2c_Battery_Charger.p_api->write(g_sf_i2c_Battery_Charger.p_ctrl, &reg_batcharger, 1, true, TX_WAIT_FOREVER );
    g_sf_i2c_Battery_Charger.p_api->read(g_sf_i2c_Battery_Charger.p_ctrl, (uint8_t*)&_charger_characteristics, _length, false, TX_WAIT_FOREVER );

    Is there a way to determine what is pwr_mgmt_thread actually waiting on?

    UI_thread is waiting for the i2c mutex yes? What is actually stopping pwr_mgmt_thread from continuing and relinquishing the mutex? I don't know what 'sf_bus_eventflag_g_sf_i2c_bus0' actually refers to - perhaps naively I'm thinking that pwr_mgmt_thread has the i2c mutex - what is this event it is waiting on? I think I must be missing something fundamental! I thought the timeout referred to how long it would wait for the mutex?

    Thanks,
    James
  • In reply to adboc:

    adboc,

    I believe I have solved the issue - it was me being stupid sadly! I was thinking in terms of SPI where where there are no ACKS or NACKS. One of the I2C devices was not plugged in - I was thinking in terms of SPI where it would just read in a null character if nothing was plugged in but of course with I2C there are acknowledgements. I will need to build up a new unit to test this but am fairly sure that as you rightly say the read function was hanging with no ACK. Thank you for your help and sorry to take up your time with something so trivial! I have at least gained some understanding!

    James