Implement transaction for async I²C. #1319
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Here is the implementation of transaction for async I²C.
It makes use of the end command to be able to perform several reads or writes consecutively without a stop condition, therefore following the transaction contract of embedded-hal, while allowing reading and writing of buffers that exceed the fifo size, by splitting the operation in multiple segments, as explained in the esp32 technical reference manual.
It gets rid of the read, write and write_read implementations as they are automatically provided by embedded-hal once transaction is implemented.
This has been tested successfully on esp32s2, esp32c3 and esp32c6 boards with several I²C devices. However, I was not able to test read and write operations exceeding the fifo size. The maximum I am able to do with the devices I have is a read of 25 bytes. But I made tests with transactions with several consecutive read or write operations which result in the same segmented transfers as when the fifo size is exceeded.
This has also been tested on esp32 boards, but I encounter some issues there. What is happening is that the end command pulls the SCL pin low before the reception of the ACK/NACK from the slave. It leads to timeouts since the ACK/NACK is only received once the SCL pin is pulled high again. I initially thought of a hardware bug of the esp32, but the technical reference manual explains clearly the use of the end command for segmented transfer and there is nothing about that in the errata for ESP32 Series SOC. Also the end command seems to used successfully in esp-idf. So I guess this is rather more due to a misconfiguration on our side, probably in the timing configuration. There is already an issue on the I²C frequency that I reported here, but I made sure to be in the conditions where the frequency is correct to perform my tests, so this is not the cause of this issue.
I will continue to investigate that to be able to amend this pull request to provide a solution for all esp32 chips, but wanted to share a first draft here. If anyone has an idea on how to solve the esp32 issue, I'm all ears.