Skip to content

Commit 752b65f

Browse files
authored
Merge pull request #98 from adamgreig/fix-97
Fix #97: split unbalanced SPI transfers into rw+r or rw+w
2 parents 86ab035 + 848b59f commit 752b65f

File tree

2 files changed

+46
-14
lines changed

2 files changed

+46
-14
lines changed

CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
1212
- Updated to `embedded-hal` `1.0.0-alpha.11` release ([API changes](https://github.com/rust-embedded/embedded-hal/blob/master/embedded-hal/CHANGELOG.md#v100-alpha11---2023-07-04))
1313
- Updated to `spidev` `0.5.2` release([API changes](https://github.com/rust-embedded/rust-spidev/blob/master/CHANGELOG.md#052--2023-08-02))
1414

15+
### Fixed
16+
- Fix using SPI transfer with unequal buffer sizes (#97, #98).
17+
1518
## [v0.4.0-alpha.3] - 2022-08-04
1619

1720
### Added

src/spi.rs

Lines changed: 43 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
//! [`embedded-hal`]: https://docs.rs/embedded-hal
44
//!
55
6+
use std::cmp::Ordering;
67
use std::fmt;
78
use std::io;
89
use std::ops;
@@ -64,9 +65,24 @@ mod embedded_hal_impl {
6465
}
6566

6667
fn transfer(&mut self, read: &mut [u8], write: &[u8]) -> Result<(), Self::Error> {
67-
self.0
68-
.transfer(&mut SpidevTransfer::read_write(write, read))
69-
.map_err(|err| SPIError { err })
68+
let read_len = read.len();
69+
match read_len.cmp(&write.len()) {
70+
Ordering::Less => self.0.transfer_multiple(&mut [
71+
SpidevTransfer::read_write(&write[..read_len], read),
72+
SpidevTransfer::write(&write[read_len..]),
73+
]),
74+
Ordering::Equal => self
75+
.0
76+
.transfer(&mut SpidevTransfer::read_write(write, read)),
77+
Ordering::Greater => {
78+
let (read1, read2) = read.split_at_mut(write.len());
79+
self.0.transfer_multiple(&mut [
80+
SpidevTransfer::read_write(write, read1),
81+
SpidevTransfer::read(read2),
82+
])
83+
}
84+
}
85+
.map_err(|err| SPIError { err })
7086
}
7187

7288
fn transfer_in_place(&mut self, words: &mut [u8]) -> Result<(), Self::Error> {
@@ -82,7 +98,7 @@ mod embedded_hal_impl {
8298
}
8399

84100
impl SpiDevice for Spidev {
85-
///Perform a transaction against the device. [Read more][transaction]
101+
/// Perform a transaction against the device. [Read more][transaction]
86102
///
87103
/// [Delay operations][delay] are capped to 65535 microseconds.
88104
///
@@ -92,24 +108,37 @@ mod embedded_hal_impl {
92108
&mut self,
93109
operations: &mut [SpiOperation<'_, u8>],
94110
) -> Result<(), Self::Error> {
95-
let mut transfers: Vec<_> = operations
96-
.iter_mut()
97-
.map(|op| match op {
98-
SpiOperation::Read(buf) => SpidevTransfer::read(buf),
99-
SpiOperation::Write(buf) => SpidevTransfer::write(buf),
100-
SpiOperation::Transfer(read, write) => SpidevTransfer::read_write(write, read),
111+
let mut transfers = Vec::with_capacity(operations.len());
112+
for op in operations {
113+
match op {
114+
SpiOperation::Read(buf) => transfers.push(SpidevTransfer::read(buf)),
115+
SpiOperation::Write(buf) => transfers.push(SpidevTransfer::write(buf)),
116+
SpiOperation::Transfer(read, write) => match read.len().cmp(&write.len()) {
117+
Ordering::Less => {
118+
let n = read.len();
119+
transfers.push(SpidevTransfer::read_write(&write[..n], read));
120+
transfers.push(SpidevTransfer::write(&write[n..]));
121+
}
122+
Ordering::Equal => transfers.push(SpidevTransfer::read_write(write, read)),
123+
Ordering::Greater => {
124+
let (read1, read2) = read.split_at_mut(write.len());
125+
transfers.push(SpidevTransfer::read_write(write, read1));
126+
transfers.push(SpidevTransfer::read(read2));
127+
}
128+
},
101129
SpiOperation::TransferInPlace(buf) => {
102130
let tx = unsafe {
103131
let p = buf.as_ptr();
104132
std::slice::from_raw_parts(p, buf.len())
105133
};
106-
SpidevTransfer::read_write(tx, buf)
134+
transfers.push(SpidevTransfer::read_write(tx, buf));
107135
}
108136
SpiOperation::DelayUs(us) => {
109-
SpidevTransfer::delay((*us).try_into().unwrap_or(u16::MAX))
137+
let us = (*us).try_into().unwrap_or(u16::MAX);
138+
transfers.push(SpidevTransfer::delay(us));
110139
}
111-
})
112-
.collect();
140+
}
141+
}
113142
self.0
114143
.transfer_multiple(&mut transfers)
115144
.map_err(|err| SPIError { err })?;

0 commit comments

Comments
 (0)