2023-05-24 06:32 AM
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.
Cheers
Solved! Go to Solution.
2023-05-26 07:52 AM
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.
2023-05-25 06:21 PM
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
2023-05-26 07:52 AM
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.