0
\$\begingroup\$

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

\$\endgroup\$
  • \$\begingroup\$ I afraid there is no other way. And I do not understand why it is not efficient. It is efficient as safe. \$\endgroup\$ – P__J__ Jul 28 '18 at 12:46
1
\$\begingroup\$

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.

\$\endgroup\$
  • \$\begingroup\$ Hi Maple. Thank you, my protocol includes the message length at the first byte. But when using the STM32 LL (or HAL) libraries I have to specify the length of the read when starting it, so I had to split the read into two reads, first one to get the response length and the second to read the whole message back. I thought perhaps there is a better way but this seems to be the only way if wanting to use DMA. If I had it interrupt driven I could have done as you said in the second paragraph. Thanks for answering! \$\endgroup\$ – AJBotha Jul 30 '18 at 9:37
  • \$\begingroup\$ The I2C libraries that I've seen usually have separate start/stop functions. What's left is read function. If you have sources of those libraries you can make your own version of read that does not send NACK and another one that does not send address. \$\endgroup\$ – Maple Jul 30 '18 at 9:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.