mirror of
https://github.com/italicsjenga/rp-hal-boards.git
synced 2025-02-23 23:57:43 +11:00
Fix i2c peripheral mode state machine
The start_det flag is set as soon as a start condition occurs whereas rd_req flag is only set once the address byte is received.
This commit is contained in:
parent
d6bb177fd7
commit
d08bfac989
1 changed files with 16 additions and 14 deletions
|
@ -24,9 +24,10 @@ pub enum I2CEvent {
|
||||||
Stop,
|
Stop,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
enum State {
|
enum State {
|
||||||
Idle,
|
Idle,
|
||||||
|
Active,
|
||||||
Read,
|
Read,
|
||||||
Write,
|
Write,
|
||||||
}
|
}
|
||||||
|
@ -98,7 +99,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Deref<Target = I2CBlock>, PINS> I2CPeripheralEventIterator<T, PINS> {
|
impl<T: Deref<Target = I2CBlock>, PINS> I2CPeripheralEventIterator<T, PINS> {
|
||||||
/// Pushs up to `usize::min(TX_FIFO_SIZE, buf.len())` bytes to the TX FIFO.
|
/// Push up to `usize::min(TX_FIFO_SIZE, buf.len())` bytes to the TX FIFO.
|
||||||
/// Returns the number of bytes pushed to the FIFO. Note this does *not* reflect how many bytes
|
/// Returns the number of bytes pushed to the FIFO. Note this does *not* reflect how many bytes
|
||||||
/// are effectively received by the controller.
|
/// are effectively received by the controller.
|
||||||
pub fn write(&mut self, buf: &[u8]) -> usize {
|
pub fn write(&mut self, buf: &[u8]) -> usize {
|
||||||
|
@ -122,7 +123,7 @@ impl<T: Deref<Target = I2CBlock>, PINS> I2CPeripheralEventIterator<T, PINS> {
|
||||||
sent
|
sent
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pulls up to `usize::min(RX_FIFO_SIZE, buf.len())` bytes from the RX FIFO.
|
/// Pull up to `usize::min(RX_FIFO_SIZE, buf.len())` bytes from the RX FIFO.
|
||||||
pub fn read(&mut self, buf: &mut [u8]) -> usize {
|
pub fn read(&mut self, buf: &mut [u8]) -> usize {
|
||||||
let mut read = 0;
|
let mut read = 0;
|
||||||
|
|
||||||
|
@ -147,29 +148,30 @@ impl<T: Deref<Target = I2CBlock>, PINS> Iterator for I2CPeripheralEventIterator<
|
||||||
match self.state {
|
match self.state {
|
||||||
State::Idle if stat.start_det().bit_is_set() => {
|
State::Idle if stat.start_det().bit_is_set() => {
|
||||||
self.i2c.i2c.ic_clr_start_det.read();
|
self.i2c.i2c.ic_clr_start_det.read();
|
||||||
self.state = if stat.rd_req().bit_is_set() {
|
self.state = State::Active;
|
||||||
State::Read
|
|
||||||
} else {
|
|
||||||
State::Write
|
|
||||||
};
|
|
||||||
Some(I2CEvent::Start)
|
Some(I2CEvent::Start)
|
||||||
}
|
}
|
||||||
State::Read if stat.rd_req().bit_is_set() => {
|
State::Active if !self.i2c.rx_fifo_empty() => {
|
||||||
// `rd_req` is used by the hardware to detect when the I2C block can stop stretching
|
self.state = State::Write;
|
||||||
// the clock and start process the data pushed to the FIFO (if any).
|
Some(I2CEvent::TransferWrite)
|
||||||
|
}
|
||||||
|
State::Active if stat.rd_req().bit_is_set() => {
|
||||||
|
// Clearing `rd_req` is used by the hardware to detect when the I2C block can stop
|
||||||
|
// stretching the clock and start process the data pushed to the FIFO (if any).
|
||||||
// This is done in `Self::write`.
|
// This is done in `Self::write`.
|
||||||
|
self.state = State::Read;
|
||||||
Some(I2CEvent::TransferRead)
|
Some(I2CEvent::TransferRead)
|
||||||
}
|
}
|
||||||
|
State::Read if stat.rd_req().bit_is_set() => Some(I2CEvent::TransferRead),
|
||||||
State::Read if stat.restart_det().bit_is_set() => {
|
State::Read if stat.restart_det().bit_is_set() => {
|
||||||
self.i2c.i2c.ic_clr_restart_det.read();
|
self.i2c.i2c.ic_clr_restart_det.read();
|
||||||
self.state = State::Write;
|
self.state = State::Active;
|
||||||
Some(I2CEvent::Restart)
|
Some(I2CEvent::Restart)
|
||||||
}
|
}
|
||||||
State::Write if !self.i2c.rx_fifo_empty() => Some(I2CEvent::TransferWrite),
|
State::Write if !self.i2c.rx_fifo_empty() => Some(I2CEvent::TransferWrite),
|
||||||
State::Write if stat.restart_det().bit_is_set() => {
|
State::Write if stat.restart_det().bit_is_set() => {
|
||||||
self.i2c.i2c.ic_clr_restart_det.read();
|
self.i2c.i2c.ic_clr_restart_det.read();
|
||||||
self.state = State::Read;
|
self.state = State::Active;
|
||||||
Some(I2CEvent::Restart)
|
Some(I2CEvent::Restart)
|
||||||
}
|
}
|
||||||
_ if stat.stop_det().bit_is_set() => {
|
_ if stat.stop_det().bit_is_set() => {
|
||||||
|
|
Loading…
Add table
Reference in a new issue