Skip to content

Commit 296618b

Browse files
committed
Support I2C transfers of more than 255 bytes
1 parent 237c7dd commit 296618b

File tree

1 file changed

+140
-90
lines changed

1 file changed

+140
-90
lines changed

src/i2c.rs

Lines changed: 140 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -191,33 +191,45 @@ macro_rules! hal {
191191
impl<PINS> Read for I2c<$I2CX, PINS> {
192192
type Error = Error;
193193
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
194-
// TODO support transfers of more than 255 bytes
195-
assert!(buffer.len() < 256 && buffer.len() > 0);
194+
assert!(buffer.len() > 0);
196195

197196
// Detect Bus busy
198197
if self.i2c.isr.read().busy().is_busy() {
199198
return Err(Error::Busy);
200199
}
201200

202-
// START and prepare to receive `bytes`
203-
self.i2c.cr2.write(|w| {
204-
w.sadd()
205-
.bits(u16::from(addr << 1))
206-
.rd_wrn()
207-
.read()
208-
.nbytes()
209-
.bits(buffer.len() as u8)
210-
.start()
211-
.start()
212-
.autoend()
213-
.automatic()
214-
});
215-
216-
for byte in buffer {
217-
// Wait until we have received something
218-
busy_wait!(self.i2c, rxne, is_not_empty);
219-
220-
*byte = self.i2c.rxdr.read().rxdata().bits();
201+
let end = buffer.len() / 0xFF;
202+
203+
// Process 255 bytes at a time
204+
for (i, buffer) in buffer.chunks_mut(0xFF).enumerate() {
205+
// Prepare to receive `bytes`
206+
self.i2c.cr2.modify(|_, w| {
207+
if i == 0 {
208+
w
209+
.add10().bit7()
210+
.sadd().bits((addr << 1) as u16)
211+
.rd_wrn().read()
212+
.start().start();
213+
}
214+
w.nbytes().bits(buffer.len() as u8);
215+
if i != end {
216+
w.reload().not_completed()
217+
} else {
218+
w.reload().completed().autoend().automatic()
219+
}
220+
});
221+
222+
for byte in buffer {
223+
// Wait until we have received something
224+
busy_wait!(self.i2c, rxne, is_not_empty);
225+
226+
*byte = self.i2c.rxdr.read().rxdata().bits();
227+
}
228+
229+
if i != end {
230+
// Wait until the last transmission is finished
231+
busy_wait!(self.i2c, tcr, is_complete);
232+
}
221233
}
222234

223235
// automatic STOP
@@ -234,36 +246,48 @@ macro_rules! hal {
234246
type Error = Error;
235247

236248
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
237-
// TODO support transfers of more than 255 bytes
238-
assert!(bytes.len() < 256 && bytes.len() > 0);
249+
assert!(bytes.len() > 0);
239250

240251
// Detect Bus busy
241252
if self.i2c.isr.read().busy().is_busy() {
242253
return Err(Error::Busy);
243254
}
244255

245-
// START and prepare to send `bytes`
246-
self.i2c.cr2.modify(|_, w| {
247-
w.sadd()
248-
.bits(u16::from(addr << 1))
249-
.rd_wrn()
250-
.write()
251-
.nbytes()
252-
.bits(bytes.len() as u8)
253-
.start()
254-
.start()
255-
.autoend()
256-
.automatic()
257-
});
258-
259-
for byte in bytes {
260-
// Wait until we are allowed to send data (START has been ACKed or last byte
261-
// when through)
262-
busy_wait!(self.i2c, txis, is_empty);
263-
264-
// put byte on the wire
265-
// NOTE(write): writes all non-reserved bits.
266-
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
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`
261+
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();
268+
}
269+
w.nbytes().bits(bytes.len() as u8);
270+
if i != end {
271+
w.reload().not_completed()
272+
} else {
273+
w.reload().completed().autoend().automatic()
274+
}
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);
290+
}
267291
}
268292

269293
// automatic STOP
@@ -285,61 +309,87 @@ macro_rules! hal {
285309
bytes: &[u8],
286310
buffer: &mut [u8],
287311
) -> Result<(), Error> {
288-
// TODO support transfers of more than 255 bytes
289-
assert!(bytes.len() < 256 && bytes.len() > 0);
290-
assert!(buffer.len() < 256 && buffer.len() > 0);
312+
assert!(bytes.len() > 0 && buffer.len() > 0);
291313

292314
// Detect Bus busy
293315
if self.i2c.isr.read().busy().is_busy() {
294316
return Err(Error::Busy);
295317
}
296318

297-
// START and prepare to send `bytes`
298-
self.i2c.cr2.modify(|_, w| {
299-
w.sadd()
300-
.bits(u16::from(addr << 1))
301-
.rd_wrn()
302-
.write()
303-
.nbytes()
304-
.bits(bytes.len() as u8)
305-
.start()
306-
.start()
307-
.autoend()
308-
.software()
309-
});
310-
311-
for byte in bytes {
312-
// Wait until we are allowed to send data
313-
// (START has been ACKed or last byte went through):
314-
busy_wait!(self.i2c, txis, is_empty);
315-
316-
// put byte into TXDR
317-
// NOTE(write): writes all non-reserved bits.
318-
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
319+
let end = buffer.len() / 0xFF;
320+
321+
// Process 255 bytes at a time
322+
for (i, bytes) in bytes.chunks(0xFF).enumerate() {
323+
// Prepare to send `bytes`
324+
self.i2c.cr2.modify(|_, w| {
325+
if i == 0 {
326+
w
327+
.add10().bit7()
328+
.sadd().bits((addr << 1) as u16)
329+
.rd_wrn().write()
330+
.start().start();
331+
}
332+
w.nbytes().bits(bytes.len() as u8);
333+
if i != end {
334+
w.reload().not_completed()
335+
} else {
336+
w.reload().completed().autoend().software()
337+
}
338+
});
339+
340+
for byte in bytes {
341+
// Wait until we are allowed to send data
342+
// (START has been ACKed or last byte went through)
343+
busy_wait!(self.i2c, txis, is_empty);
344+
345+
// Put byte on the wire
346+
// NOTE(write): Writes all non-reserved bits.
347+
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
348+
}
349+
350+
if i != end {
351+
// Wait until the last transmission is finished
352+
busy_wait!(self.i2c, tcr, is_complete);
353+
}
319354
}
320355

321-
// Wait until the last byte transmission is finished:
356+
// Wait until the last transmission is finished
322357
busy_wait!(self.i2c, tc, is_complete);
323358

324-
// reSTART and prepare to receive bytes into `buffer`
325-
self.i2c.cr2.modify(|_, w| {
326-
w.sadd()
327-
.bits(u16::from(addr << 1))
328-
.rd_wrn()
329-
.read()
330-
.nbytes()
331-
.bits(buffer.len() as u8)
332-
.start()
333-
.start()
334-
.autoend()
335-
.automatic()
336-
});
337-
338-
for byte in buffer {
339-
// Wait until we have received something
340-
busy_wait!(self.i2c, rxne, is_not_empty);
341-
342-
*byte = self.i2c.rxdr.read().rxdata().bits();
359+
// restart
360+
361+
let end = buffer.len() / 0xFF;
362+
363+
// Process 255 bytes at a time
364+
for (i, buffer) in buffer.chunks_mut(0xFF).enumerate() {
365+
// Prepare to receive `bytes`
366+
self.i2c.cr2.modify(|_, w| {
367+
if i == 0 {
368+
w
369+
.add10().bit7()
370+
.sadd().bits((addr << 1) as u16)
371+
.rd_wrn().read()
372+
.start().start();
373+
}
374+
w.nbytes().bits(buffer.len() as u8);
375+
if i != end {
376+
w.reload().not_completed()
377+
} else {
378+
w.reload().completed().autoend().automatic()
379+
}
380+
});
381+
382+
for byte in buffer {
383+
// Wait until we have received something
384+
busy_wait!(self.i2c, rxne, is_not_empty);
385+
386+
*byte = self.i2c.rxdr.read().rxdata().bits();
387+
}
388+
389+
if i != end {
390+
// Wait until the last transmission is finished
391+
busy_wait!(self.i2c, tcr, is_complete);
392+
}
343393
}
344394

345395
// automatic STOP

0 commit comments

Comments
 (0)