-
Notifications
You must be signed in to change notification settings - Fork 2
i2c: Add target implementation #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
The example is currently only tested on NUCLEO-STM32H503, and uses pins that are not available on other H5 processors. This can be enabled on other processors by choosing different pins for the various evaluation boards.
src/i2c.rs
Outdated
/// This encapsulates a transaction event that occurs when listening in Target | ||
/// operation. A TargetWrite event indicates that the Controller wants to read | ||
/// data from the Target (I2C read operation). A TargetRead event indicates | ||
/// that the Controller wants to write data to the Target (I2C write | ||
/// operation). A Stop event indicates that a Stop condition was received and | ||
/// the transaction has been completed. | ||
#[derive(Copy, Clone, Debug, PartialEq, Eq)] | ||
pub enum TargetEvent { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These definitions are pretty confusing. Wouldn't a TargetRead
indicates that the controller wants to read data from the target?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ha. I actually had these the other way round, simply called TargetEvent::Read
(controller wants to read, target must execute a write) and TargetEvent::Write
(controller wants to write, target must execute a read), but I thought that was confusing, so I tried to disambiguate it by indicating that a TargetRead event is in response to controller write. Guess they're both a bit confusing, so I'll go back to the old iteration.
- Deduplicate functions shared between AutoAck and ManualAck implementations for I2cTarget - Rename TargetEvent variants - Fix writing buffer larger than 255 bytes in ManualAck operation - Improved documentation
length <= u8::MAX as usize, | ||
"I2C max transfer size per reload = {}", | ||
u8::MAX | ||
); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added these bounds checks in the controller start logic because I realized that the controller implementation does not use NBYTES reloads to write buffers longer than 255 bytes, but also doesn't bounds check on repeat starts or reloads, leading to wrap around bugs on the value written to the NBYTES field and transactions that were unexpectedly short.
Created this issue to track: #46
@ryan-summers mind taking another look at this? I believe I've addressed everything |
This extends the I2C driver to support target operation. It adds an I2cTarget type to represent the I2C operation as the target.
Target operation can be operated in automatic ACKing mode, letting the hardware manage clock stretching and ACKing automatically, or it can be operated in manual ACK control mode, which lets the user of the driver determine when to ACK the end of a transaction. Manual ACK control allows for clock stretching while data is being processed or retrieved before ACK'ing the final byte of a transfer and initiating either the end of a transfer or a repeat start to read the processed/retrieved data. This implementation does not currently allow for ACKing individual or a subset of bytes manually, but extending the interface to do so can build upon what is implemented so far.
This also adds role switching to the driver, enabling both controller and target implementation through choosing the appropriate initialization functions.