Skip to content
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

Use modify instead of write for clearing sr1 #298

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Fix > 2 byte i2c reads
- Send stop after acknowledge errors on i2c
- Fix i2c interactions after errors
- Only clear individual i2c status registers on error

### Changed
- Use `cortex-m-rtic` instead of `cortex-m-rtfm` in the examples
Expand Down
19 changes: 15 additions & 4 deletions src/i2c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,17 +219,25 @@ macro_rules! wait_for_flag {
($i2c:expr, $flag:ident) => {{
let sr1 = $i2c.sr1.read();

// Writing 1s in order to only clear the flag we spotted even
// if the register gets modified externally
// NOTE(unsafe): Writing 1 to registers which are cleared by 0 has no effect.
// Similarly, writing to read-only registers has no effect
if sr1.berr().bit_is_set() {
$i2c.sr1.write(|w| w.berr().clear_bit());
$i2c.sr1
.write(|w| unsafe { w.bits(0xffff) }.berr().clear_bit());
Err(Other(Error::Bus))
} else if sr1.arlo().bit_is_set() {
$i2c.sr1.write(|w| w.arlo().clear_bit());
$i2c.sr1
.write(|w| unsafe { w.bits(0xffff) }.arlo().clear_bit());
Err(Other(Error::Arbitration))
} else if sr1.af().bit_is_set() {
$i2c.sr1.write(|w| w.af().clear_bit());
$i2c.sr1
.write(|w| unsafe { w.bits(0xffff) }.af().clear_bit());
Err(Other(Error::Acknowledge))
} else if sr1.ovr().bit_is_set() {
$i2c.sr1.write(|w| w.ovr().clear_bit());
$i2c.sr1
.write(|w| unsafe { w.bits(0xffff) }.ovr().clear_bit());
Err(Other(Error::Overrun))
} else if sr1.$flag().bit_is_set() {
Ok(())
Expand Down Expand Up @@ -347,6 +355,9 @@ where

/// Generate START condition
fn send_start(&mut self) {
// Clear all pending error bits
// NOTE(unsafe): Writing 0 clears the r/w bits and has no effect on the r bits
self.i2c.sr1.write(|w| unsafe { w.bits(0) });
self.i2c.cr1.modify(|_, w| w.start().set_bit());
}

Expand Down