2025-03-06 12:21 PM
Hello,
I am implementing I2C slave device with STM32G431. Using DMA with HAL library, it works well as expected in normal situation.
It normally get ready to receive running
HAL_I2C_Slave_Receive_DMA(&hi2c1, (uint8_t *)aRxBuffer, rx_length)
and handles request at
void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *I2cHandle)
If response is requested, response is set ready to send by
HAL_I2C_Slave_Transmit_DMA(&hi2c1, (uint8_t *)aTxBuffer, tx_length)
And in error cases, reset I2C by HAL_I2C_Init(&hi2c1), and ready to receive again by HAL_I2C_Slave_Receive_DMA.
But I can't handle if the master want to read unexpectedly. Without previous command asking to prepare data to respond, the master (another STM32 board) starts read sequence,
> HAL_I2C_Master_Receive(&hi2c1, 0xA1, aRxBuffer, 1, 1000);
Both SDA & SCL go low after I2C address is sent from master and ACK, until the slave powered off.
I guess that the slave is in clock stretching. Reading request is received, but slave has nothing to send (no previous HAL_I2C_Slave_Transmit_DMA call), so both SCL & SDA lines are held low until TxBuffer is filled with something.
However, I found no method to find out whether the data are requested. I have checked hi2c1.State, hi2c1.ErrorCode, hi2c1.hdmatx->State, hi2c1.hdmatx->ErrorCode but I have not found any clue.
My goal is to cancel transfer, or if it is not possible because ACK is already sent, then to send dummy byte until the master gave up receiving. If I can make the slave get out of clock stretching state anyhow, then master will send clock, and get NACK if the slave does not respond, and after several tries the master will give up. That's not bad - anyway I2C port will be back to ready.
So, can anybody help me to escape from the slave holding I2C lines low? Thanks in advance.