Skip to content

Commit 58a69ef

Browse files
committed
spi: flush bus before read
1 parent 98c4685 commit 58a69ef

File tree

1 file changed

+19
-26
lines changed

1 file changed

+19
-26
lines changed

src/spi.rs

Lines changed: 19 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -296,8 +296,11 @@ macro_rules! spi {
296296
let len = words.len();
297297
if len == 0 { return Ok(()) }
298298

299+
// flush data from previous operations, otherwise we'd get unwanted data
300+
self.flush()?;
299301
// FIFO threshold to 16 bits
300302
self.spi.cr2.modify(|_, w| w.frxth().clear_bit());
303+
self.set_bidi();
301304

302305
let half_len = len / 2;
303306
let pair_left = len % 2;
@@ -309,36 +312,32 @@ macro_rules! spi {
309312
}
310313

311314
for r in words.chunks_exact_mut(2).take(half_len - prefill) {
312-
nb::block!(self.nb_write(0u16))?;
313315
let r_two: u16 = unsafe {
314316
nb::block!(self.nb_read_no_err()).unwrap_unchecked()
315317
};
318+
nb::block!(self.nb_write(0u16))?;
316319
// safety: chunks have exact length of 2
317320
unsafe { *r.as_mut_ptr().cast() = r_two.to_le_bytes(); }
318321
}
319322

320-
let odd_idx = len.saturating_sub(prefill + pair_left);
323+
let odd_idx = len.saturating_sub(2*prefill + pair_left);
321324
// FIFO threshold to 8 bits
322325
self.spi.cr2.modify(|_, w| w.frxth().set_bit());
323326
if pair_left == 1 {
324327
nb::block!(self.nb_write(0u8))?;
325328
words[odd_idx] = nb::block!(self.nb_read_no_err()).unwrap();
326329
}
327330

328-
Ok(for r in words[odd_idx+1..].iter_mut() {
331+
Ok(for r in words[odd_idx+pair_left..].iter_mut() {
329332
*r = nb::block!(self.nb_read())?;
330333
})
331334
}
332335

333336
fn write(&mut self, words: &[u8]) -> Result<(), Self::Error> {
334-
let catch = |spi: &mut Self| Ok(for w in words {
335-
nb::block!(spi.nb_write(*w))?
336-
});
337-
338337
self.set_tx_only();
339-
let res = catch(self);
340-
self.set_bidi();
341-
res
338+
Ok(for w in words {
339+
nb::block!(self.nb_write(*w))?
340+
})
342341
}
343342

344343
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
@@ -348,6 +347,7 @@ macro_rules! spi {
348347
return self.read(read)
349348
}
350349

350+
self.set_bidi();
351351
let common_len = core::cmp::min(read.len(), write.len());
352352
let half_len = common_len / 2;
353353
let pair_left = common_len % 2;
@@ -372,7 +372,6 @@ macro_rules! spi {
372372
// write ahead of reading
373373
let zipped = read.chunks_exact_mut(2).zip(write_iter).take(half_len - prefill);
374374
for (r, w) in zipped {
375-
376375
let r_two: u16 = unsafe {
377376
nb::block!(self.nb_read_no_err()).unwrap_unchecked()
378377
};
@@ -410,6 +409,7 @@ macro_rules! spi {
410409
let len = words.len();
411410
if len == 0 { return Ok(()) }
412411

412+
self.set_bidi();
413413
self.spi.cr2.modify(|_, w| w.frxth().clear_bit());
414414
let half_len = len / 2;
415415
let pair_left = len % 2;
@@ -450,23 +450,16 @@ macro_rules! spi {
450450
})
451451
}
452452
fn flush(&mut self) -> Result<(), Self::Error> {
453-
let catch = |spi: &mut Self| {
454-
// drain rx fifo
455-
while match spi.nb_read::<u8>() {
456-
Ok(_) => true,
457-
Err(nb::Error::WouldBlock) => false,
458-
Err(nb::Error::Other(e)) => { return Err(e) }
459-
} { core::hint::spin_loop() };
460-
// wait for tx fifo to be drained by the peripheral
461-
while spi.spi.sr.read().ftlvl() != 0 { core::hint::spin_loop() };
462-
Ok(())
463-
};
464-
465453
// stop receiving data
466454
self.set_tx_only();
467-
let res = catch(self);
468-
self.set_bidi();
469-
res
455+
// drain rx fifo
456+
while match self.nb_read::<u8>() {
457+
Ok(_) => true,
458+
Err(nb::Error::WouldBlock) => false,
459+
Err(nb::Error::Other(e)) => { return Err(e) }
460+
} { core::hint::spin_loop() };
461+
// wait for idle
462+
Ok(while self.spi.sr.read().bsy().bit() { core::hint::spin_loop() })
470463
}
471464
}
472465

0 commit comments

Comments
 (0)