mirror of
https://github.com/rtic-rs/rtic.git
synced 2024-12-24 19:09:33 +01:00
rtic-sync: Add SPI bus sharing with arbiter
This commit is contained in:
parent
96e7704487
commit
ff5cad9cd2
4 changed files with 90 additions and 0 deletions
|
@ -9,6 +9,8 @@ For each category, _Added_, _Changed_, _Fixed_ add new entries at the top!
|
|||
|
||||
### Added
|
||||
|
||||
- `arbiter::spi::ArbiterDevice` for sharing SPI buses using `embedded-hal-async`
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
|
|
@ -21,6 +21,9 @@ heapless = "0.7"
|
|||
critical-section = "1"
|
||||
rtic-common = { version = "1.0.0", path = "../rtic-common" }
|
||||
portable-atomic = { version = "1", default-features = false }
|
||||
embedded-hal = { version = "1.0.0-rc.1", optional = true }
|
||||
embedded-hal-async = { version = "1.0.0-rc.1", optional = true }
|
||||
embedded-hal-bus = { version = "0.1.0-rc.1", optional = true, features = ["async"] }
|
||||
|
||||
[dev-dependencies]
|
||||
tokio = { version = "1", features = ["rt", "macros", "time"] }
|
||||
|
@ -29,3 +32,4 @@ tokio = { version = "1", features = ["rt", "macros", "time"] }
|
|||
[features]
|
||||
default = []
|
||||
testing = ["critical-section/std", "rtic-common/testing"]
|
||||
unstable = ["embedded-hal", "embedded-hal-async", "embedded-hal-bus"]
|
||||
|
|
|
@ -191,6 +191,89 @@ impl<'a, T> DerefMut for ExclusiveAccess<'a, T> {
|
|||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "unstable")]
|
||||
/// SPI bus sharing using [`Arbiter`]
|
||||
pub mod spi {
|
||||
use super::Arbiter;
|
||||
use embedded_hal::digital::OutputPin;
|
||||
use embedded_hal_async::{
|
||||
delay::DelayUs,
|
||||
spi::{ErrorType, Operation, SpiBus, SpiDevice},
|
||||
};
|
||||
use embedded_hal_bus::spi::DeviceError;
|
||||
|
||||
/// [`Arbiter`]-based shared bus implementation.
|
||||
pub struct ArbiterDevice<'a, BUS, CS, D> {
|
||||
bus: &'a Arbiter<BUS>,
|
||||
cs: CS,
|
||||
delay: D,
|
||||
}
|
||||
|
||||
impl<'a, BUS, CS, D> ArbiterDevice<'a, BUS, CS, D> {
|
||||
/// Create a new [`ArbiterDevice`].
|
||||
pub fn new(bus: &'a Arbiter<BUS>, cs: CS, delay: D) -> Self {
|
||||
Self { bus, cs, delay }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, BUS, CS, D> ErrorType for ArbiterDevice<'a, BUS, CS, D>
|
||||
where
|
||||
BUS: ErrorType,
|
||||
CS: OutputPin,
|
||||
{
|
||||
type Error = DeviceError<BUS::Error, CS::Error>;
|
||||
}
|
||||
|
||||
impl<'a, Word, BUS, CS, D> SpiDevice<Word> for ArbiterDevice<'a, BUS, CS, D>
|
||||
where
|
||||
Word: Copy + 'static,
|
||||
BUS: SpiBus<Word>,
|
||||
CS: OutputPin,
|
||||
D: DelayUs,
|
||||
{
|
||||
async fn transaction(
|
||||
&mut self,
|
||||
operations: &mut [Operation<'_, Word>],
|
||||
) -> Result<(), DeviceError<BUS::Error, CS::Error>> {
|
||||
let mut bus = self.bus.access().await;
|
||||
|
||||
self.cs.set_low().map_err(DeviceError::Cs)?;
|
||||
|
||||
let op_res = 'ops: {
|
||||
for op in operations {
|
||||
let res = match op {
|
||||
Operation::Read(buf) => bus.read(buf).await,
|
||||
Operation::Write(buf) => bus.write(buf).await,
|
||||
Operation::Transfer(read, write) => bus.transfer(read, write).await,
|
||||
Operation::TransferInPlace(buf) => bus.transfer_in_place(buf).await,
|
||||
Operation::DelayUs(us) => match bus.flush().await {
|
||||
Err(e) => Err(e),
|
||||
Ok(()) => {
|
||||
self.delay.delay_us(*us).await;
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
};
|
||||
if let Err(e) = res {
|
||||
break 'ops Err(e);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
};
|
||||
|
||||
// On failure, it's important to still flush and deassert CS.
|
||||
let flush_res = bus.flush().await;
|
||||
let cs_res = self.cs.set_high();
|
||||
|
||||
op_res.map_err(DeviceError::Spi)?;
|
||||
flush_res.map_err(DeviceError::Spi)?;
|
||||
cs_res.map_err(DeviceError::Cs)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -89,6 +89,7 @@ impl Package {
|
|||
.chain(std::iter::once(None))
|
||||
.collect()
|
||||
}
|
||||
Package::RticSync => vec![Some("unstable".to_string()), None],
|
||||
_ => vec![None],
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue