Skip to content

Commit c251ebf

Browse files
committed
Support 0 byte I2C write
1 parent 296618b commit c251ebf

File tree

1 file changed

+46
-34
lines changed

1 file changed

+46
-34
lines changed

src/i2c.rs

Lines changed: 46 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ macro_rules! hal {
222222
for byte in buffer {
223223
// Wait until we have received something
224224
busy_wait!(self.i2c, rxne, is_not_empty);
225-
225+
226226
*byte = self.i2c.rxdr.read().rxdata().bits();
227227
}
228228

@@ -246,47 +246,59 @@ macro_rules! hal {
246246
type Error = Error;
247247

248248
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
249-
assert!(bytes.len() > 0);
250-
251249
// Detect Bus busy
252250
if self.i2c.isr.read().busy().is_busy() {
253251
return Err(Error::Busy);
254252
}
255253

256-
let end = bytes.len() / 0xFF;
257-
258-
// Process 255 bytes at a time
259-
for (i, bytes) in bytes.chunks(0xFF).enumerate() {
260-
// Prepare to send `bytes`
254+
if bytes.len() == 0 {
255+
// 0 byte write
261256
self.i2c.cr2.modify(|_, w| {
262-
if i == 0 {
263-
w
264-
.add10().bit7()
265-
.sadd().bits((addr << 1) as u16)
266-
.rd_wrn().write()
267-
.start().start();
257+
w
258+
.add10().bit7()
259+
.sadd().bits((addr << 1) as u16)
260+
.rd_wrn().write()
261+
.nbytes().bits(0)
262+
.reload().completed()
263+
.autoend().automatic()
264+
.start().start()
265+
});
266+
} else {
267+
let end = bytes.len() / 0xFF;
268+
269+
// Process 255 bytes at a time
270+
for (i, bytes) in bytes.chunks(0xFF).enumerate() {
271+
// Prepare to send `bytes`
272+
self.i2c.cr2.modify(|_, w| {
273+
if i == 0 {
274+
w
275+
.add10().bit7()
276+
.sadd().bits((addr << 1) as u16)
277+
.rd_wrn().write()
278+
.start().start();
279+
}
280+
w.nbytes().bits(bytes.len() as u8);
281+
if i != end {
282+
w.reload().not_completed()
283+
} else {
284+
w.reload().completed().autoend().automatic()
285+
}
286+
});
287+
288+
for byte in bytes {
289+
// Wait until we are allowed to send data
290+
// (START has been ACKed or last byte went through)
291+
busy_wait!(self.i2c, txis, is_empty);
292+
293+
// Put byte on the wire
294+
// NOTE(write): Writes all non-reserved bits.
295+
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
268296
}
269-
w.nbytes().bits(bytes.len() as u8);
297+
270298
if i != end {
271-
w.reload().not_completed()
272-
} else {
273-
w.reload().completed().autoend().automatic()
299+
// Wait until the last transmission is finished
300+
busy_wait!(self.i2c, tcr, is_complete);
274301
}
275-
});
276-
277-
for byte in bytes {
278-
// Wait until we are allowed to send data
279-
// (START has been ACKed or last byte went through)
280-
busy_wait!(self.i2c, txis, is_empty);
281-
282-
// Put byte on the wire
283-
// NOTE(write): Writes all non-reserved bits.
284-
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
285-
}
286-
287-
if i != end {
288-
// Wait until the last transmission is finished
289-
busy_wait!(self.i2c, tcr, is_complete);
290302
}
291303
}
292304

@@ -382,7 +394,7 @@ macro_rules! hal {
382394
for byte in buffer {
383395
// Wait until we have received something
384396
busy_wait!(self.i2c, rxne, is_not_empty);
385-
397+
386398
*byte = self.i2c.rxdr.read().rxdata().bits();
387399
}
388400

0 commit comments

Comments
 (0)