Skip to main content
Graduate
May 24, 2023
Solved

I2C errors with two slave devices

  • May 24, 2023
  • 2 replies
  • 1438 views

Hi,

I have ST25DV64KC and another ADC chip connected to STM32L071RZT6 on I2C1.

I noticed that reading GPO1 or other registers or MB by HAL_I2C_Mem_Read_IT() fails from time to time. Completions of operations are often timeout (somehow read timeouts more often, i.e. I don't get INT in expected time).

I only read static & dyn registers as well as accessing MB for r/w and tend to think that I don't handle i2c concurrent access properly.

  • Should only function call of HAL_I2C_Mem_Read_IT() or WriteIT() be protected by mutex or I should keep it until I get INT back signalling the end of the requested operation?
  • What should timeout be for reading of static/dyn registers or reading 256 bytes from MB? (configured i2c Fast-mode)
  • Does competing for i2c resources task's priority matters much or elevated priority will sort it out?
  • Could someone suggest a working approach to solve concurrent access on the i2c bus?

Cheers

    This topic has been closed for replies.
    Best answer by Bob S

    If you are using and RTOS and more than one thread/task can access that I2C bus then, yes, you need a mutex to control access. And if you are using the _IT() versions of the HAL functions, you need a semaphore or task notification for the callback to notify the task that the I2C transfer is complete. Something like this pseudo code:

    // TASK #1
    acquire_i2c1_mutex();
    sts = HAL_I2C_MasterTransmit_IT( .... ); // To device #1
    acquire_i2c1_semaphore(); // semaphore set in I2C transmit complete callback
    release_i2c1_mutex();
     
    // TASK #3
    acquire_i2c1_mutex();
    sts = HAL_I2C_MasterTransmit_IT( .... ); // To device #2a
    acquire_i2c1_semaphore(); // semaphore set in I2C transmit complete callback
    release_i2c1_mutex();
     
    void HAL_I2C_TxCpltCallback( .. )
    {
     if ( hi2c == &hi2c1 ) {
     release_i2c1_semaphore()
     }
    }
     

    If you are using the _IT() functions there are no (inherent) timeouts. And with I2C devices the only way ANY timeout makes sense is if there are multiple masters that might keep the bus busy and prevent your CPU from getting its turn.

    2 replies

    Visitor II
    May 26, 2023

    Well since the computer era started last millenia, network printers implementer a queue, aka spooler which funnel all print request in a tidy manner. Mutex may then becomes needless. Apply and adapt to I2C master

    Bob SAnswer
    Super User
    May 26, 2023

    If you are using and RTOS and more than one thread/task can access that I2C bus then, yes, you need a mutex to control access. And if you are using the _IT() versions of the HAL functions, you need a semaphore or task notification for the callback to notify the task that the I2C transfer is complete. Something like this pseudo code:

    // TASK #1
    acquire_i2c1_mutex();
    sts = HAL_I2C_MasterTransmit_IT( .... ); // To device #1
    acquire_i2c1_semaphore(); // semaphore set in I2C transmit complete callback
    release_i2c1_mutex();
     
    // TASK #3
    acquire_i2c1_mutex();
    sts = HAL_I2C_MasterTransmit_IT( .... ); // To device #2a
    acquire_i2c1_semaphore(); // semaphore set in I2C transmit complete callback
    release_i2c1_mutex();
     
    void HAL_I2C_TxCpltCallback( .. )
    {
     if ( hi2c == &hi2c1 ) {
     release_i2c1_semaphore()
     }
    }
     

    If you are using the _IT() functions there are no (inherent) timeouts. And with I2C devices the only way ANY timeout makes sense is if there are multiple masters that might keep the bus busy and prevent your CPU from getting its turn.