Skip to content

Commit 26c1c1f

Browse files
committed
spi::FrameSize and e-hal 1.0
1 parent 1f19959 commit 26c1c1f

File tree

4 files changed

+121
-39
lines changed

4 files changed

+121
-39
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1919
- Update to `stm32f1` v0.16.0 [#503] [#534]
2020
- `Spi` now takes `Option<PIN>` for `SCK`, `MISO`, `MOSI` [#514],
2121
add `SPIx::NoSck`, etc. [#537]
22+
- `spi::FrameSize` and `embedded-hal` 1.0 implementations
2223
- move `Qei` mod inside `pwm_input` mod [#516]
2324

2425
### Changed

src/spi.rs

Lines changed: 108 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,6 @@ mod hal_02;
6666
mod hal_1;
6767

6868
use core::ops::{Deref, DerefMut};
69-
use core::ptr;
7069

7170
use crate::pac::{self, RCC};
7271

@@ -109,6 +108,36 @@ pub struct Mode {
109108
pub phase: Phase,
110109
}
111110

111+
type SpiRB = pac::spi1::RegisterBlock;
112+
113+
pub trait FrameSize: Copy + Default {
114+
const DFF: bool;
115+
#[doc(hidden)]
116+
fn read_data(spi: &SpiRB) -> Self;
117+
#[doc(hidden)]
118+
fn write_data(self, spi: &SpiRB);
119+
}
120+
121+
impl FrameSize for u8 {
122+
const DFF: bool = false;
123+
fn read_data(spi: &SpiRB) -> Self {
124+
spi.dr8().read().dr().bits()
125+
}
126+
fn write_data(self, spi: &SpiRB) {
127+
spi.dr8().write(|w| w.dr().set(self));
128+
}
129+
}
130+
131+
impl FrameSize for u16 {
132+
const DFF: bool = true;
133+
fn read_data(spi: &SpiRB) -> Self {
134+
spi.dr().read().dr().bits()
135+
}
136+
fn write_data(self, spi: &SpiRB) {
137+
spi.dr().write(|w| w.dr().set(self));
138+
}
139+
}
140+
112141
/// Interrupt event
113142
pub enum Event {
114143
/// New data has been received
@@ -519,24 +548,7 @@ impl<SPI: Instance, Otype, PULL> SpiSlave<SPI, u8, Otype, PULL> {
519548
}
520549
}
521550

522-
pub trait SpiReadWrite<T> {
523-
fn read_data_reg(&mut self) -> T;
524-
fn write_data_reg(&mut self, data: T);
525-
fn spi_write(&mut self, words: &[T]) -> Result<(), Error>;
526-
}
527-
528-
impl<SPI: Instance, W: Copy> SpiReadWrite<W> for SpiInner<SPI, W> {
529-
fn read_data_reg(&mut self) -> W {
530-
// NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
531-
// reading a half-word)
532-
unsafe { ptr::read_volatile(self.spi.dr().as_ptr() as *const W) }
533-
}
534-
535-
fn write_data_reg(&mut self, data: W) {
536-
// NOTE(write_volatile) see note above
537-
unsafe { ptr::write_volatile(self.spi.dr().as_ptr() as *mut W, data) }
538-
}
539-
551+
impl<SPI: Instance, W: FrameSize> SpiInner<SPI, W> {
540552
// Implement write as per the "Transmit only procedure" page 712
541553
// of RM0008 Rev 20. This is more than twice as fast as the
542554
// default Write<> implementation (which reads and drops each
@@ -547,7 +559,7 @@ impl<SPI: Instance, W: Copy> SpiReadWrite<W> for SpiInner<SPI, W> {
547559
loop {
548560
let sr = self.spi.sr().read();
549561
if sr.txe().bit_is_set() {
550-
self.write_data_reg(*word);
562+
(*word).write_data(&self.spi);
551563
if sr.modf().bit_is_set() {
552564
return Err(Error::ModeFault);
553565
}
@@ -560,13 +572,13 @@ impl<SPI: Instance, W: Copy> SpiReadWrite<W> for SpiInner<SPI, W> {
560572
// Wait for final !BSY
561573
while self.is_busy() {}
562574
// Clear OVR set due to dropped received values
563-
let _ = self.read_data_reg();
575+
let _ = W::read_data(&self.spi);
564576
let _ = self.spi.sr().read();
565577
Ok(())
566578
}
567579
}
568580

569-
impl<SPI: Instance, W: Copy> SpiInner<SPI, W> {
581+
impl<SPI: Instance, W> SpiInner<SPI, W> {
570582
/// Select which frame format is used for data transfers
571583
pub fn bit_format(&mut self, format: SpiBitFormat) {
572584
self.spi
@@ -676,9 +688,9 @@ impl<SPI: Instance, Otype, PULL> SpiSlave<SPI, u16, Otype, PULL> {
676688
impl<SPI, W> SpiInner<SPI, W>
677689
where
678690
SPI: Instance,
679-
W: Copy,
691+
W: FrameSize,
680692
{
681-
pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
693+
pub(crate) fn check_read(&mut self) -> nb::Result<W, Error> {
682694
let sr = self.spi.sr().read();
683695

684696
Err(if sr.ovr().bit_is_set() {
@@ -690,12 +702,13 @@ where
690702
} else if sr.rxne().bit_is_set() {
691703
// NOTE(read_volatile) read only 1 byte (the svd2rust API only allows
692704
// reading a half-word)
693-
return Ok(self.read_data_reg());
705+
return Ok(W::read_data(&self.spi));
694706
} else {
695707
nb::Error::WouldBlock
696708
})
697709
}
698-
pub fn write_nonblocking(&mut self, data: W) -> nb::Result<(), Error> {
710+
711+
pub(crate) fn check_send(&mut self, data: W) -> nb::Result<(), Error> {
699712
let sr = self.spi.sr().read();
700713

701714
// NOTE: Error::Overrun was deleted in #408. Need check
@@ -705,15 +718,83 @@ where
705718
Error::Crc.into()
706719
} else if sr.txe().bit_is_set() {
707720
// NOTE(write_volatile) see note above
708-
self.write_data_reg(data);
721+
data.write_data(&self.spi);
709722
return Ok(());
710723
} else {
711724
nb::Error::WouldBlock
712725
})
713726
}
727+
728+
#[inline(always)]
729+
pub fn read_nonblocking(&mut self) -> nb::Result<W, Error> {
730+
// TODO: bidimode
731+
self.check_read()
732+
}
733+
734+
#[inline(always)]
735+
pub fn write_nonblocking(&mut self, data: W) -> nb::Result<(), Error> {
736+
// TODO: bidimode
737+
self.check_send(data)
738+
}
739+
740+
#[inline(always)]
714741
pub fn write(&mut self, words: &[W]) -> Result<(), Error> {
715742
self.spi_write(words)
716743
}
744+
745+
pub fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Error> {
746+
for word in words {
747+
nb::block!(self.write_nonblocking(*word))?;
748+
*word = nb::block!(self.read_nonblocking())?;
749+
}
750+
751+
Ok(())
752+
}
753+
754+
pub fn transfer(&mut self, buff: &mut [W], data: &[W]) -> Result<(), Error> {
755+
if data.len() == buff.len() {
756+
for (d, b) in data.iter().cloned().zip(buff.iter_mut()) {
757+
nb::block!(self.write_nonblocking(d))?;
758+
*b = nb::block!(self.read_nonblocking())?;
759+
}
760+
} else {
761+
let mut iter_r = buff.iter_mut();
762+
let mut iter_w = data.iter().cloned();
763+
loop {
764+
match (iter_r.next(), iter_w.next()) {
765+
(Some(r), Some(w)) => {
766+
nb::block!(self.write_nonblocking(w))?;
767+
*r = nb::block!(self.read_nonblocking())?;
768+
}
769+
(Some(r), None) => {
770+
nb::block!(self.write_nonblocking(W::default()))?;
771+
*r = nb::block!(self.read_nonblocking())?;
772+
}
773+
(None, Some(w)) => {
774+
nb::block!(self.write_nonblocking(w))?;
775+
let _ = nb::block!(self.read_nonblocking())?;
776+
}
777+
(None, None) => break,
778+
}
779+
}
780+
}
781+
782+
Ok(())
783+
}
784+
785+
pub fn flush(&mut self) -> Result<(), Error> {
786+
Ok(())
787+
}
788+
789+
pub fn read(&mut self, words: &mut [W]) -> Result<(), Error> {
790+
// TODO: bidimode
791+
for word in words {
792+
nb::block!(self.check_send(W::default()))?;
793+
*word = nb::block!(self.check_read())?;
794+
}
795+
796+
Ok(())
797+
}
717798
}
718799

719800
// DMA

src/spi/hal_02.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ impl From<Mode> for super::Mode {
3333
impl<SPI, W, PULL> spi::FullDuplex<W> for Spi<SPI, W, PULL>
3434
where
3535
SPI: Instance,
36-
W: Copy,
36+
W: FrameSize,
3737
{
3838
type Error = Error;
3939

@@ -49,7 +49,7 @@ where
4949
impl<SPI, W, PULL> blocking::transfer::Default<W> for Spi<SPI, W, PULL>
5050
where
5151
SPI: Instance,
52-
W: Copy,
52+
W: FrameSize,
5353
{
5454
}
5555

src/spi/hal_1.rs

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,13 @@ impl<SPI: Instance, W, PULL> ErrorType for Spi<SPI, W, PULL> {
4343
}
4444

4545
mod nb {
46-
use super::{Error, Instance, Spi};
46+
use super::{Error, FrameSize, Instance, Spi};
4747
use embedded_hal_nb::spi::FullDuplex;
4848

4949
impl<SPI, W, PULL> FullDuplex<W> for Spi<SPI, W, PULL>
5050
where
5151
SPI: Instance,
52-
W: Copy,
52+
W: FrameSize,
5353
{
5454
fn read(&mut self) -> nb::Result<W, Error> {
5555
self.read_nonblocking()
@@ -62,25 +62,25 @@ mod nb {
6262
}
6363

6464
mod blocking {
65-
use super::super::{Instance, Spi};
65+
use super::super::{FrameSize, Instance, Spi};
6666
use core::ops::DerefMut;
6767
use embedded_hal::spi::SpiBus;
6868

6969
impl<SPI: Instance, W, PULL> SpiBus<W> for Spi<SPI, W, PULL>
7070
where
7171
SPI: Instance,
72-
W: Copy + 'static,
72+
W: FrameSize + 'static,
7373
{
74-
fn transfer_in_place(&mut self, _words: &mut [W]) -> Result<(), Self::Error> {
75-
todo!()
74+
fn transfer_in_place(&mut self, words: &mut [W]) -> Result<(), Self::Error> {
75+
self.deref_mut().transfer_in_place(words)
7676
}
7777

78-
fn transfer(&mut self, _buff: &mut [W], _data: &[W]) -> Result<(), Self::Error> {
79-
todo!()
78+
fn transfer(&mut self, buff: &mut [W], data: &[W]) -> Result<(), Self::Error> {
79+
self.deref_mut().transfer(buff, data)
8080
}
8181

82-
fn read(&mut self, _words: &mut [W]) -> Result<(), Self::Error> {
83-
todo!()
82+
fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error> {
83+
self.deref_mut().read(words)
8484
}
8585

8686
fn write(&mut self, words: &[W]) -> Result<(), Self::Error> {

0 commit comments

Comments
 (0)