Skip to content

Commit 237c7dd

Browse files
committed
Add Busy and Nack error type for I2C
1 parent 8486da1 commit 237c7dd

File tree

1 file changed

+43
-15
lines changed

1 file changed

+43
-15
lines changed

src/i2c.rs

Lines changed: 43 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,14 @@ use cast::u8;
1313
#[derive(Debug)]
1414
#[non_exhaustive]
1515
pub enum Error {
16-
/// Bus error
17-
Bus,
1816
/// Arbitration loss
1917
Arbitration,
18+
/// Bus error
19+
Bus,
20+
/// Bus busy
21+
Busy,
22+
/// Not Acknowledge received
23+
Nack,
2024
// Overrun, // slave mode only
2125
// Pec, // SMBUS mode only
2226
// Timeout, // SMBUS mode only
@@ -57,15 +61,21 @@ macro_rules! busy_wait {
5761
($i2c:expr, $flag:ident, $variant:ident) => {
5862
loop {
5963
let isr = $i2c.isr.read();
64+
let icr = &$i2c.icr;
6065

61-
if isr.$flag().$variant() {
62-
break;
66+
if isr.arlo().is_lost() {
67+
icr.write(|w| w.arlocf().clear());
68+
return Err(Error::Arbitration);
6369
} else if isr.berr().is_error() {
70+
icr.write(|w| w.berrcf().clear());
6471
return Err(Error::Bus);
65-
} else if isr.arlo().is_lost() {
66-
return Err(Error::Arbitration);
67-
} else {
68-
// try again
72+
} else if isr.nackf().is_nack() {
73+
while $i2c.isr.read().stopf().is_no_stop() {}
74+
icr.write(|w| w.nackcf().clear());
75+
icr.write(|w| w.stopcf().clear());
76+
return Err(Error::Nack);
77+
} else if isr.$flag().$variant() {
78+
break;
6979
}
7080
}
7181
};
@@ -184,8 +194,10 @@ macro_rules! hal {
184194
// TODO support transfers of more than 255 bytes
185195
assert!(buffer.len() < 256 && buffer.len() > 0);
186196

187-
// TODO do we have to explicitly wait here if the bus is busy (e.g. another
188-
// master is communicating)?
197+
// Detect Bus busy
198+
if self.i2c.isr.read().busy().is_busy() {
199+
return Err(Error::Busy);
200+
}
189201

190202
// START and prepare to receive `bytes`
191203
self.i2c.cr2.write(|w| {
@@ -209,6 +221,10 @@ macro_rules! hal {
209221
}
210222

211223
// automatic STOP
224+
// Wait until the last transmission is finished
225+
busy_wait!(self.i2c, stopf, is_stop);
226+
227+
self.i2c.icr.write(|w| w.stopcf().clear());
212228

213229
Ok(())
214230
}
@@ -221,6 +237,11 @@ macro_rules! hal {
221237
// TODO support transfers of more than 255 bytes
222238
assert!(bytes.len() < 256 && bytes.len() > 0);
223239

240+
// Detect Bus busy
241+
if self.i2c.isr.read().busy().is_busy() {
242+
return Err(Error::Busy);
243+
}
244+
224245
// START and prepare to send `bytes`
225246
self.i2c.cr2.modify(|_, w| {
226247
w.sadd()
@@ -245,10 +266,11 @@ macro_rules! hal {
245266
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
246267
}
247268

248-
// Wait until the last transmission is finished ???
249-
// busy_wait!(self.i2c, busy);
250-
251269
// automatic STOP
270+
// Wait until the last transmission is finished
271+
busy_wait!(self.i2c, stopf, is_stop);
272+
273+
self.i2c.icr.write(|w| w.stopcf().clear());
252274

253275
Ok(())
254276
}
@@ -267,8 +289,10 @@ macro_rules! hal {
267289
assert!(bytes.len() < 256 && bytes.len() > 0);
268290
assert!(buffer.len() < 256 && buffer.len() > 0);
269291

270-
// TODO do we have to explicitly wait here if the bus is busy (e.g. another
271-
// master is communicating)?
292+
// Detect Bus busy
293+
if self.i2c.isr.read().busy().is_busy() {
294+
return Err(Error::Busy);
295+
}
272296

273297
// START and prepare to send `bytes`
274298
self.i2c.cr2.modify(|_, w| {
@@ -319,6 +343,10 @@ macro_rules! hal {
319343
}
320344

321345
// automatic STOP
346+
// Wait until the last transmission is finished
347+
busy_wait!(self.i2c, stopf, is_stop);
348+
349+
self.i2c.icr.write(|w| w.stopcf().clear());
322350

323351
Ok(())
324352
}

0 commit comments

Comments
 (0)