Skip to content

Commit 4acac31

Browse files
committed
Add transactional spi implementation.
Requires embedded-hal patch with feature/spi-transactions branch and transactional-spi feature
1 parent 0df951c commit 4acac31

File tree

2 files changed

+43
-2
lines changed

2 files changed

+43
-2
lines changed

Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,12 @@ license = "MIT OR Apache-2.0"
77
name = "linux-embedded-hal"
88
repository = "https://github.com/japaric/linux-embedded-hal"
99
version = "0.3.0"
10+
edition = "2018"
1011

1112
[features]
1213
gpio_sysfs = ["sysfs_gpio"]
1314
gpio_cdev = ["gpio-cdev"]
15+
transactional-spi = [] # Guard for transactional SPI feature (https://github.com/rust-embedded/embedded-hal/pull/191)
1416

1517
default = [ "gpio_cdev", "gpio_sysfs" ]
1618

@@ -32,3 +34,6 @@ openpty = "0.1.0"
3234
# we don't need the `Error` implementation
3335
default-features = false
3436
version = "0.2.2"
37+
38+
[patch.crates-io]
39+
#embedded-hal = { git = "https://github.com/ryankurte/embedded-hal", branch = "feature/spi-transactions" }

src/lib.rs

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
#![deny(missing_docs)]
1414

1515
extern crate cast;
16-
extern crate core;
1716
extern crate embedded_hal as hal;
1817
pub extern crate i2cdev;
1918
pub extern crate nb;
@@ -202,7 +201,10 @@ impl hal::blocking::i2c::WriteRead for I2cdev {
202201
buffer: &mut [u8],
203202
) -> Result<(), Self::Error> {
204203
self.set_address(address)?;
205-
let mut messages = [LinuxI2CMessage::write(bytes), LinuxI2CMessage::read(buffer)];
204+
let mut messages = [
205+
LinuxI2CMessage::write(bytes),
206+
LinuxI2CMessage::read(buffer),
207+
];
206208
self.inner.transfer(&mut messages).map(drop)
207209
}
208210
}
@@ -257,6 +259,40 @@ impl hal::blocking::spi::Write<u8> for Spidev {
257259
}
258260
}
259261

262+
#[cfg(feature = "transactional-spi")]
263+
pub use hal::blocking::spi::{Operation as SpiOperation};
264+
265+
#[cfg(feature = "transactional-spi")]
266+
impl hal::blocking::spi::Transactional<u8> for Spidev {
267+
type Error = io::Error;
268+
269+
fn try_exec<'a>(&mut self, operations: &mut [SpiOperation<'a, u8>]) -> Result<(), Self::Error> {
270+
271+
// Map types from generic to linux objects
272+
let mut messages: Vec<_> = operations.iter_mut().map(|a| {
273+
match a {
274+
SpiOperation::Write(w) => SpidevTransfer::write(w),
275+
SpiOperation::Transfer(r) => {
276+
// TODO: is spidev okay with the same array pointer
277+
// being used twice? If not, need some kind of vector
278+
// pool that will outlive the transfer
279+
let w = unsafe {
280+
let p = r.as_ptr();
281+
std::slice::from_raw_parts(p, r.len())
282+
};
283+
284+
SpidevTransfer::read_write(w, r)
285+
},
286+
}
287+
}).collect();
288+
289+
// Execute transfer
290+
self.0.transfer_multiple(&mut messages)?;
291+
292+
Ok(())
293+
}
294+
}
295+
260296
impl ops::Deref for Spidev {
261297
type Target = spidev::Spidev;
262298

0 commit comments

Comments
 (0)