Electrical – STM32 I2C Read Variable Length message from Slave

hal-libraryi2cmicrocontrollerstm32

I have two devices that must communicate over I2C. The master writes some data to the slave, and then it must read back a response from the slave.

Neither the slave nor the master knows the length of the message that should be received. On the Slave this is not a problem, I set the DMA to receive 255 bytes (more than the master will ever write in one message), and then wait for the STOP condition to be raised to signal the end of the transfer.

On the Master I can't figure out how to read a message from the slave without knowing how many bytes should be read. Is there a way to do this? My understanding is that the Master generates the STOP condition, so I can't use that.

I currently just read back one byte from the slave that contains the number of bytes that are to be transferred, and then do another read for that amount of data, but I am looking for a more efficient and faster way.

I am using STM32L433 MCU's and have used the LL-Libraries for the I2C code with DMA to transfer the messages to the peripheral.
Best Regards

Best Answer

Every byte transmitted over I2C requires acknowledgement. When slave is transmitting data back to master it is the master's responsibility to either allow slave to continue (by replying ACK) or telling it to stop (by replying NACK).

So, if you send the number of bytes N available for reading first then your master can simply continue reading and replying with N-1 ACKs and finish it all up by replying NACK before issuing STOP condition.

Alternatively, if your data format allows it, you can mark the last byte as "end of data". For example 7-bit data can be marked by 1 bit high. The data that is a subset of 8-bit values can be marked by any value outside of that subset. Or you can reserve two values as ESC and EOD signals etc.

Note that all these methods are generally less efficient than sending one message length byte first. After all, even if there was some "magic" 1-bit way to end transmission from slave side in I2C protocol, you would be saving only 7 bit time on one transmission.