Skip to content

Commit 090d7da

Browse files
committed
blocking/spi: add Read, ReadWrite, rename Transfer to ReadWriteInplace
1 parent a7c1233 commit 090d7da

File tree

2 files changed

+101
-13
lines changed

2 files changed

+101
-13
lines changed

src/blocking/spi.rs

Lines changed: 98 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,30 @@
11
//! Blocking SPI API
22
3-
/// Blocking transfer
4-
pub trait Transfer<W> {
3+
/// Blocking simultaneous read+write with separate buffers
4+
pub trait ReadWrite<W> {
5+
/// Error type
6+
type Error;
7+
8+
/// Writes and reads simultaneously. `write` is written to the slave on MOSI and
9+
/// words received on MISO are stored in `read`.
10+
///
11+
/// It is allowed for `read` and `write` to have different lengths, even zero length.
12+
/// The transfer runs for `max(read.len(), write.len())` words. If `read` is shorter,
13+
/// incoming words after `read` has been filled will be discarded. If `write` is shorter,
14+
/// the value of words sent in MOSI after all `write` has been sent is implementation defined,
15+
/// typically `0x00`, `0xFF`, or configurable.
16+
fn read_write(&mut self, read: &mut [W], write: &[W]) -> Result<(), Self::Error>;
17+
}
18+
19+
/// Blocking simultaneous read+write with a single buffer
20+
pub trait ReadWriteInplace<W> {
521
/// Error type
622
type Error;
723

824
/// Writes and reads simultaneously. The contents of `words` are
925
/// written to the slave, and the received words are stored into the same
1026
/// `words` buffer, overwriting it.
11-
fn transfer(&mut self, words: &mut [W]) -> Result<(), Self::Error>;
27+
fn read_write_inplace(&mut self, words: &mut [W]) -> Result<(), Self::Error>;
1228
}
1329

1430
/// Blocking write
@@ -20,6 +36,16 @@ pub trait Write<W> {
2036
fn write(&mut self, words: &[W]) -> Result<(), Self::Error>;
2137
}
2238

39+
/// Blocking read
40+
pub trait Read<W> {
41+
/// Error type
42+
type Error;
43+
44+
/// Reads `words` to the slave. The word value sent on MOSI during
45+
/// reading is implementation defined, typically `0x00`, `0xFF`, or configurable.
46+
fn read(&mut self, words: &mut [W]) -> Result<(), Self::Error>;
47+
}
48+
2349
/// Blocking write (iterator version)
2450
pub trait WriteIter<W> {
2551
/// Error type
@@ -31,20 +57,56 @@ pub trait WriteIter<W> {
3157
WI: IntoIterator<Item = W>;
3258
}
3359

34-
/// Blocking transfer
35-
pub mod transfer {
60+
/// Blocking simultaneous read+write with separate buffers
61+
pub mod read_write {
62+
/// Default implementation of `blocking::spi::ReadWrite<W>` for implementers of
63+
/// `nonblocking::spi::FullDuplex<W>`
64+
///
65+
/// If `read` is longer than `write`, `W::default()` (which is typically 0) is sent on MOSI
66+
/// to fill the remaining bytes.
67+
pub trait Default<W>: crate::nb::spi::FullDuplex<W> {}
68+
69+
impl<W, S> crate::blocking::spi::ReadWrite<W> for S
70+
where
71+
S: Default<W>,
72+
W: Clone + core::default::Default,
73+
{
74+
type Error = S::Error;
75+
76+
fn read_write(&mut self, read: &mut [W], write: &[W]) -> Result<(), S::Error> {
77+
for i in 0..core::cmp::max(read.len(), write.len()) {
78+
let word_out = if i < write.len() {
79+
write[i].clone()
80+
} else {
81+
W::default()
82+
};
83+
nb::block!(self.write(word_out.clone()))?;
84+
85+
let word_in = nb::block!(self.read())?;
86+
if i < read.len() {
87+
read[i] = word_in;
88+
}
89+
}
90+
91+
Ok(())
92+
}
93+
}
94+
}
95+
96+
/// Blocking simultaneous read+write with separate buffers
97+
pub mod read_write_inplace {
3698
/// Default implementation of `blocking::spi::Transfer<W>` for implementers of
3799
/// `nonblocking::spi::FullDuplex<W>`
38100
pub trait Default<W>: crate::nb::spi::FullDuplex<W> {}
39101

40-
impl<W, S> crate::blocking::spi::Transfer<W> for S
102+
impl<W, S> crate::blocking::spi::ReadWriteInplace<W> for S
41103
where
42104
S: Default<W>,
43105
W: Clone,
44106
{
45107
type Error = S::Error;
46108

47-
fn transfer(&mut self, words: &mut [W]) -> Result<(), S::Error> {
109+
fn read_write_inplace(&mut self, words: &mut [W]) -> Result<(), S::Error> {
48110
for word in words.iter_mut() {
49111
nb::block!(self.write(word.clone()))?;
50112
*word = nb::block!(self.read())?;
@@ -78,6 +140,31 @@ pub mod write {
78140
}
79141
}
80142
}
143+
/// Blocking write
144+
pub mod read {
145+
/// Default implementation of `blocking::spi::Read<W>` for implementers
146+
/// of `nonblocking::spi::FullDuplex<W>`
147+
///
148+
/// During the read, `W::default()` (which is typically 0) is sent on MOSI.
149+
pub trait Default<W>: crate::nb::spi::FullDuplex<W> {}
150+
151+
impl<W, S> crate::blocking::spi::Read<W> for S
152+
where
153+
S: Default<W>,
154+
W: core::default::Default,
155+
{
156+
type Error = S::Error;
157+
158+
fn read(&mut self, words: &mut [W]) -> Result<(), S::Error> {
159+
for word in words.iter_mut() {
160+
nb::block!(self.write(W::default()))?;
161+
*word = nb::block!(self.read())?;
162+
}
163+
164+
Ok(())
165+
}
166+
}
167+
}
81168

82169
/// Blocking write (iterator version)
83170
pub mod write_iter {
@@ -129,15 +216,15 @@ pub trait Transactional<W: 'static> {
129216

130217
/// Blocking transactional impl over spi::Write and spi::Transfer
131218
pub mod transactional {
132-
use super::{Operation, Transfer, Write};
219+
use super::{Operation, ReadWriteInplace, Write};
133220

134221
/// Default implementation of `blocking::spi::Transactional<W>` for implementers of
135222
/// `spi::Write<W>` and `spi::Transfer<W>`
136-
pub trait Default<W>: Write<W> + Transfer<W> {}
223+
pub trait Default<W>: Write<W> + ReadWriteInplace<W> {}
137224

138225
impl<W: 'static, E, S> super::Transactional<W> for S
139226
where
140-
S: self::Default<W> + Write<W, Error = E> + Transfer<W, Error = E>,
227+
S: self::Default<W> + Write<W, Error = E> + ReadWriteInplace<W, Error = E>,
141228
W: Copy + Clone,
142229
{
143230
type Error = E;
@@ -146,7 +233,7 @@ pub mod transactional {
146233
for op in operations {
147234
match op {
148235
Operation::Write(w) => self.write(w)?,
149-
Operation::Transfer(t) => self.transfer(t).map(|_| ())?,
236+
Operation::Transfer(t) => self.read_write_inplace(t).map(|_| ())?,
150237
}
151238
}
152239

src/prelude.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@ pub use crate::blocking::qei::Qei as _embedded_hal_blocking_Qei;
2222
pub use crate::blocking::rng::Read as _embedded_hal_blocking_rng_Read;
2323
pub use crate::blocking::serial::Write as _embedded_hal_blocking_serial_Write;
2424
pub use crate::blocking::spi::{
25-
Transfer as _embedded_hal_blocking_spi_Transfer, Write as _embedded_hal_blocking_spi_Write,
26-
WriteIter as _embedded_hal_blocking_spi_WriteIter,
25+
ReadWrite as _embedded_hal_blocking_spi_ReadWrite,
26+
ReadWriteInplace as _embedded_hal_blocking_spi_ReadWriteInplace,
27+
Write as _embedded_hal_blocking_spi_Write, WriteIter as _embedded_hal_blocking_spi_WriteIter,
2728
};
2829
pub use crate::blocking::watchdog::Disable as _embedded_hal_blocking_watchdog_Disable;
2930
pub use crate::blocking::watchdog::Enable as _embedded_hal_blocking_watchdog_Enable;

0 commit comments

Comments
 (0)