-
Notifications
You must be signed in to change notification settings - Fork 182
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
various i2c fixes #282
various i2c fixes #282
Changes from all commits
c80c7da
a1d8b24
765ac49
ea24f01
db95d14
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -220,12 +220,16 @@ macro_rules! wait_for_flag { | |
let sr1 = $i2c.sr1.read(); | ||
|
||
if sr1.berr().bit_is_set() { | ||
$i2c.sr1.write(|w| w.berr().clear_bit()); | ||
Err(Other(Error::Bus)) | ||
} else if sr1.arlo().bit_is_set() { | ||
$i2c.sr1.write(|w| w.arlo().clear_bit()); | ||
Err(Other(Error::Arbitration)) | ||
} else if sr1.af().bit_is_set() { | ||
$i2c.sr1.write(|w| w.af().clear_bit()); | ||
Err(Other(Error::Acknowledge)) | ||
} else if sr1.ovr().bit_is_set() { | ||
$i2c.sr1.write(|w| w.ovr().clear_bit()); | ||
Err(Other(Error::Overrun)) | ||
} else if sr1.$flag().bit_is_set() { | ||
Ok(()) | ||
|
@@ -432,12 +436,17 @@ where | |
last_ret | ||
} | ||
|
||
fn write_without_stop(&mut self, addr: u8, bytes: &[u8]) -> NbResult<(), Error> { | ||
self.send_start_and_wait()?; | ||
fn send_addr_and_wait(&mut self, addr: u8, read: bool) -> NbResult<(), Error> { | ||
self.nb.i2c.sr1.read(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not directly related to the PR, but I'm now becomming unsure about what this is doing here. My best guess is that it tries to clear the status registers, but clearly that's not done since the first commit in the PR is needed... There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. hmm; looking at the datasheet i'm not entirely sure if it's needed here either; Fwiw the relevant parts are:
with EV5 being But ofcourse the Overall it seems some bits of sr1 are persistents (the error bits in particular) while others gets cleared on read There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right. I think the best course of action here is to break this into its own issue and maybe fix it later since doing the wrong thing could break things subtly. |
||
self.nb.send_addr(addr, false); | ||
self.nb.send_addr(addr, read); | ||
let ret = busy_wait_cycles!(wait_for_flag!(self.nb.i2c, addr), self.addr_timeout); | ||
if ret == Err(Other(Error::Acknowledge)) { | ||
self.nb.send_stop(); | ||
} | ||
ret | ||
} | ||
|
||
busy_wait_cycles!(wait_for_flag!(self.nb.i2c, addr), self.addr_timeout)?; | ||
fn write_bytes_and_wait(&mut self, bytes: &[u8]) -> NbResult<(), Error> { | ||
self.nb.i2c.sr1.read(); | ||
self.nb.i2c.sr2.read(); | ||
|
||
|
@@ -451,6 +460,17 @@ where | |
|
||
Ok(()) | ||
} | ||
|
||
fn write_without_stop(&mut self, addr: u8, bytes: &[u8]) -> NbResult<(), Error> { | ||
self.send_start_and_wait()?; | ||
self.send_addr_and_wait(addr, false)?; | ||
|
||
let ret = self.write_bytes_and_wait(bytes); | ||
if ret == Err(Other(Error::Acknowledge)) { | ||
self.nb.send_stop(); | ||
} | ||
ret | ||
} | ||
} | ||
|
||
impl<I2C, PINS> Write for BlockingI2c<I2C, PINS> | ||
|
@@ -476,9 +496,7 @@ where | |
|
||
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> { | ||
self.send_start_and_wait()?; | ||
self.nb.i2c.sr1.read(); | ||
self.nb.send_addr(addr, true); | ||
busy_wait_cycles!(wait_for_flag!(self.nb.i2c, addr), self.addr_timeout)?; | ||
self.send_addr_and_wait(addr, true)?; | ||
|
||
match buffer.len() { | ||
1 => { | ||
|
@@ -515,6 +533,7 @@ where | |
self.nb.i2c.cr1.modify(|_, w| w.ack().set_bit()); | ||
} | ||
buffer_len => { | ||
self.nb.i2c.cr1.modify(|_, w| w.ack().set_bit()); | ||
self.nb.i2c.sr1.read(); | ||
self.nb.i2c.sr2.read(); | ||
|
||
|
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.
Hmm, is
write
correct here? These look like no-op to me.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 could be wrong, but I believe these are there to reset the flags.
Edit: Reference manual says
And I don't believe we have PE set
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.
Yes, but
sr1.write(|w| w.any_field().clear_bit());
basically writes 0 to the whole register, regardless of the field name. That's why this looks like a mistake.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.
Oh right, I guess that should be
modify
instead. Good catch, I'll go ahead and fix that