Skip to content

Commit 92d9357

Browse files
authored
Merge pull request #154 from Piroro-hs/i2c
Support I2C transfers of more than 255 bytes
2 parents c44988a + fe25fbb commit 92d9357

File tree

2 files changed

+196
-105
lines changed

2 files changed

+196
-105
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
2020
([#99](https://github.com/stm32-rs/stm32f3xx-hal/pull/99))
2121
- SPI4 peripheral for supported
2222
devices. ([#99](https://github.com/stm32-rs/stm32f3xx-hal/pull/99))
23+
- Support for I2C transfer of more than 255 bytes, and 0 byte write ([#154](https://github.com/stm32-rs/stm32f3xx-hal/pull/154))
2324

2425
### Changed
2526

src/i2c.rs

Lines changed: 195 additions & 105 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
};
@@ -181,34 +191,52 @@ macro_rules! hal {
181191
impl<PINS> Read for I2c<$I2CX, PINS> {
182192
type Error = Error;
183193
fn read(&mut self, addr: u8, buffer: &mut [u8]) -> Result<(), Self::Error> {
184-
// TODO support transfers of more than 255 bytes
185-
assert!(buffer.len() < 256 && buffer.len() > 0);
186-
187-
// TODO do we have to explicitly wait here if the bus is busy (e.g. another
188-
// master is communicating)?
189-
190-
// START and prepare to receive `bytes`
191-
self.i2c.cr2.write(|w| {
192-
w.sadd()
193-
.bits(u16::from(addr << 1))
194-
.rd_wrn()
195-
.read()
196-
.nbytes()
197-
.bits(buffer.len() as u8)
198-
.start()
199-
.start()
200-
.autoend()
201-
.automatic()
202-
});
194+
assert!(buffer.len() > 0);
203195

204-
for byte in buffer {
205-
// Wait until we have received something
206-
busy_wait!(self.i2c, rxne, is_not_empty);
196+
// Detect Bus busy
197+
if self.i2c.isr.read().busy().is_busy() {
198+
return Err(Error::Busy);
199+
}
207200

208-
*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+
}
209233
}
210234

211235
// automatic STOP
236+
// Wait until the last transmission is finished
237+
busy_wait!(self.i2c, stopf, is_stop);
238+
239+
self.i2c.icr.write(|w| w.stopcf().clear());
212240

213241
Ok(())
214242
}
@@ -218,37 +246,67 @@ macro_rules! hal {
218246
type Error = Error;
219247

220248
fn write(&mut self, addr: u8, bytes: &[u8]) -> Result<(), Error> {
221-
// TODO support transfers of more than 255 bytes
222-
assert!(bytes.len() < 256 && bytes.len() > 0);
223-
224-
// START and prepare to send `bytes`
225-
self.i2c.cr2.modify(|_, w| {
226-
w.sadd()
227-
.bits(u16::from(addr << 1))
228-
.rd_wrn()
229-
.write()
230-
.nbytes()
231-
.bits(bytes.len() as u8)
232-
.start()
233-
.start()
234-
.autoend()
235-
.automatic()
236-
});
237-
238-
for byte in bytes {
239-
// Wait until we are allowed to send data (START has been ACKed or last byte
240-
// when through)
241-
busy_wait!(self.i2c, txis, is_empty);
242-
243-
// put byte on the wire
244-
// NOTE(write): writes all non-reserved bits.
245-
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
249+
// Detect Bus busy
250+
if self.i2c.isr.read().busy().is_busy() {
251+
return Err(Error::Busy);
246252
}
247253

248-
// Wait until the last transmission is finished ???
249-
// busy_wait!(self.i2c, busy);
254+
if bytes.len() == 0 {
255+
// 0 byte write
256+
self.i2c.cr2.modify(|_, w| {
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));
296+
}
297+
298+
if i != end {
299+
// Wait until the last transmission is finished
300+
busy_wait!(self.i2c, tcr, is_complete);
301+
}
302+
}
303+
}
250304

251305
// automatic STOP
306+
// Wait until the last transmission is finished
307+
busy_wait!(self.i2c, stopf, is_stop);
308+
309+
self.i2c.icr.write(|w| w.stopcf().clear());
252310

253311
Ok(())
254312
}
@@ -263,62 +321,94 @@ macro_rules! hal {
263321
bytes: &[u8],
264322
buffer: &mut [u8],
265323
) -> Result<(), Error> {
266-
// TODO support transfers of more than 255 bytes
267-
assert!(bytes.len() < 256 && bytes.len() > 0);
268-
assert!(buffer.len() < 256 && buffer.len() > 0);
269-
270-
// TODO do we have to explicitly wait here if the bus is busy (e.g. another
271-
// master is communicating)?
272-
273-
// START and prepare to send `bytes`
274-
self.i2c.cr2.modify(|_, w| {
275-
w.sadd()
276-
.bits(u16::from(addr << 1))
277-
.rd_wrn()
278-
.write()
279-
.nbytes()
280-
.bits(bytes.len() as u8)
281-
.start()
282-
.start()
283-
.autoend()
284-
.software()
285-
});
324+
assert!(bytes.len() > 0 && buffer.len() > 0);
286325

287-
for byte in bytes {
288-
// Wait until we are allowed to send data
289-
// (START has been ACKed or last byte went through):
290-
busy_wait!(self.i2c, txis, is_empty);
326+
// Detect Bus busy
327+
if self.i2c.isr.read().busy().is_busy() {
328+
return Err(Error::Busy);
329+
}
291330

292-
// put byte into TXDR
293-
// NOTE(write): writes all non-reserved bits.
294-
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
331+
let end = buffer.len() / 0xFF;
332+
333+
// Process 255 bytes at a time
334+
for (i, bytes) in bytes.chunks(0xFF).enumerate() {
335+
// Prepare to send `bytes`
336+
self.i2c.cr2.modify(|_, w| {
337+
if i == 0 {
338+
w
339+
.add10().bit7()
340+
.sadd().bits((addr << 1) as u16)
341+
.rd_wrn().write()
342+
.start().start();
343+
}
344+
w.nbytes().bits(bytes.len() as u8);
345+
if i != end {
346+
w.reload().not_completed()
347+
} else {
348+
w.reload().completed().autoend().software()
349+
}
350+
});
351+
352+
for byte in bytes {
353+
// Wait until we are allowed to send data
354+
// (START has been ACKed or last byte went through)
355+
busy_wait!(self.i2c, txis, is_empty);
356+
357+
// Put byte on the wire
358+
// NOTE(write): Writes all non-reserved bits.
359+
self.i2c.txdr.write(|w| w.txdata().bits(*byte));
360+
}
361+
362+
if i != end {
363+
// Wait until the last transmission is finished
364+
busy_wait!(self.i2c, tcr, is_complete);
365+
}
295366
}
296367

297-
// Wait until the last byte transmission is finished:
368+
// Wait until the last transmission is finished
298369
busy_wait!(self.i2c, tc, is_complete);
299370

300-
// reSTART and prepare to receive bytes into `buffer`
301-
self.i2c.cr2.modify(|_, w| {
302-
w.sadd()
303-
.bits(u16::from(addr << 1))
304-
.rd_wrn()
305-
.read()
306-
.nbytes()
307-
.bits(buffer.len() as u8)
308-
.start()
309-
.start()
310-
.autoend()
311-
.automatic()
312-
});
313-
314-
for byte in buffer {
315-
// Wait until we have received something
316-
busy_wait!(self.i2c, rxne, is_not_empty);
317-
318-
*byte = self.i2c.rxdr.read().rxdata().bits();
371+
// restart
372+
373+
let end = buffer.len() / 0xFF;
374+
375+
// Process 255 bytes at a time
376+
for (i, buffer) in buffer.chunks_mut(0xFF).enumerate() {
377+
// Prepare to receive `bytes`
378+
self.i2c.cr2.modify(|_, w| {
379+
if i == 0 {
380+
w
381+
.add10().bit7()
382+
.sadd().bits((addr << 1) as u16)
383+
.rd_wrn().read()
384+
.start().start();
385+
}
386+
w.nbytes().bits(buffer.len() as u8);
387+
if i != end {
388+
w.reload().not_completed()
389+
} else {
390+
w.reload().completed().autoend().automatic()
391+
}
392+
});
393+
394+
for byte in buffer {
395+
// Wait until we have received something
396+
busy_wait!(self.i2c, rxne, is_not_empty);
397+
398+
*byte = self.i2c.rxdr.read().rxdata().bits();
399+
}
400+
401+
if i != end {
402+
// Wait until the last transmission is finished
403+
busy_wait!(self.i2c, tcr, is_complete);
404+
}
319405
}
320406

321407
// automatic STOP
408+
// Wait until the last transmission is finished
409+
busy_wait!(self.i2c, stopf, is_stop);
410+
411+
self.i2c.icr.write(|w| w.stopcf().clear());
322412

323413
Ok(())
324414
}

0 commit comments

Comments
 (0)