Skip to content

Commit

Permalink
feat(embedded-hal-bus): Spi - Add support for cs to clock delay
Browse files Browse the repository at this point in the history
  • Loading branch information
vchapuis committed May 31, 2024
1 parent a0ccb65 commit ab42bc6
Show file tree
Hide file tree
Showing 6 changed files with 159 additions and 11 deletions.
32 changes: 30 additions & 2 deletions embedded-hal-bus/src/spi/atomic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ pub struct AtomicDevice<'a, BUS, CS, D> {
bus: &'a AtomicCell<BUS>,
cs: CS,
delay: D,
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
cs_to_clock_delay_ns: u32,
clock_to_cs_delay_ns: u32,
}

#[derive(Debug, Copy, Clone)]
Expand All @@ -55,7 +58,23 @@ impl<'a, BUS, CS, D> AtomicDevice<'a, BUS, CS, D> {
CS: OutputPin,
{
cs.set_high()?;
Ok(Self { bus, cs, delay })
Ok(Self {
bus,
cs,
delay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}

/// Set the delay between the CS pin toggle and the first clock
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
self.cs_to_clock_delay_ns = delay_ns;
}

/// Set the delay between the last clock and the CS pin reset
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
self.clock_to_cs_delay_ns = delay_ns;
}
}

Expand Down Expand Up @@ -93,6 +112,8 @@ where
bus,
cs,
delay: super::NoDelay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}
}
Expand Down Expand Up @@ -134,7 +155,14 @@ where

let bus = unsafe { &mut *self.bus.bus.get() };

let result = transaction(operations, bus, &mut self.delay, &mut self.cs);
let result = transaction(
operations,
bus,
&mut self.delay,
&mut self.cs,
self.cs_to_clock_delay_ns,
self.clock_to_cs_delay_ns,
);

self.bus
.busy
Expand Down
32 changes: 30 additions & 2 deletions embedded-hal-bus/src/spi/critical_section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ pub struct CriticalSectionDevice<'a, BUS, CS, D> {
bus: &'a Mutex<RefCell<BUS>>,
cs: CS,
delay: D,
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
cs_to_clock_delay_ns: u32,
clock_to_cs_delay_ns: u32,
}

impl<'a, BUS, CS, D> CriticalSectionDevice<'a, BUS, CS, D> {
Expand All @@ -34,7 +37,23 @@ impl<'a, BUS, CS, D> CriticalSectionDevice<'a, BUS, CS, D> {
CS: OutputPin,
{
cs.set_high()?;
Ok(Self { bus, cs, delay })
Ok(Self {
bus,
cs,
delay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}

/// Set the delay between the CS pin toggle and the first clock
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
self.cs_to_clock_delay_ns = delay_ns;
}

/// Set the delay between the last clock and the CS pin reset
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
self.clock_to_cs_delay_ns = delay_ns;
}
}

Expand Down Expand Up @@ -68,6 +87,8 @@ impl<'a, BUS, CS> CriticalSectionDevice<'a, BUS, CS, super::NoDelay> {
bus,
cs,
delay: super::NoDelay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}
}
Expand All @@ -91,7 +112,14 @@ where
critical_section::with(|cs| {
let bus = &mut *self.bus.borrow_ref_mut(cs);

transaction(operations, bus, &mut self.delay, &mut self.cs)
transaction(
operations,
bus,
&mut self.delay,
&mut self.cs,
self.cs_to_clock_delay_ns,
self.clock_to_cs_delay_ns,
)
})
}
}
34 changes: 31 additions & 3 deletions embedded-hal-bus/src/spi/exclusive.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,9 @@ pub struct ExclusiveDevice<BUS, CS, D> {
bus: BUS,
cs: CS,
delay: D,
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
cs_to_clock_delay_ns: u32,
clock_to_cs_delay_ns: u32,
}

impl<BUS, CS, D> ExclusiveDevice<BUS, CS, D> {
Expand All @@ -28,12 +31,28 @@ impl<BUS, CS, D> ExclusiveDevice<BUS, CS, D> {
/// This sets the `cs` pin high, and returns an error if that fails. It is recommended
/// to set the pin high the moment it's configured as an output, to avoid glitches.
#[inline]
pub fn new(bus: BUS, mut cs: CS, delay: D) -> Result<Self, CS::Error>
pub fn new(bus: BUS, mut cs: CS, delay: D, cs_to_clock_delay_ns: u32) -> Result<Self, CS::Error>
where
CS: OutputPin,
{
cs.set_high()?;
Ok(Self { bus, cs, delay })
Ok(Self {
bus,
cs,
delay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}

/// Set the delay between the CS pin toggle and the first clock
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
self.cs_to_clock_delay_ns = delay_ns;
}

/// Set the delay between the last clock and the CS pin reset
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
self.clock_to_cs_delay_ns = delay_ns;
}

/// Returns a reference to the underlying bus object.
Expand Down Expand Up @@ -79,6 +98,8 @@ impl<BUS, CS> ExclusiveDevice<BUS, CS, super::NoDelay> {
bus,
cs,
delay: super::NoDelay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}
}
Expand All @@ -99,7 +120,14 @@ where
{
#[inline]
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
transaction(operations, &mut self.bus, &mut self.delay, &mut self.cs)
transaction(
operations,
&mut self.bus,
&mut self.delay,
&mut self.cs,
self.cs_to_clock_delay_ns,
self.clock_to_cs_delay_ns,
)
}
}

Expand Down
32 changes: 30 additions & 2 deletions embedded-hal-bus/src/spi/mutex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ pub struct MutexDevice<'a, BUS, CS, D> {
bus: &'a Mutex<BUS>,
cs: CS,
delay: D,
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
cs_to_clock_delay_ns: u32,
clock_to_cs_delay_ns: u32,
}

impl<'a, BUS, CS, D> MutexDevice<'a, BUS, CS, D> {
Expand All @@ -32,7 +35,23 @@ impl<'a, BUS, CS, D> MutexDevice<'a, BUS, CS, D> {
CS: OutputPin,
{
cs.set_high()?;
Ok(Self { bus, cs, delay })
Ok(Self {
bus,
cs,
delay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}

/// Set the delay between the CS pin toggle and the first clock
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
self.cs_to_clock_delay_ns = delay_ns;
}

/// Set the delay between the last clock and the CS pin reset
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
self.clock_to_cs_delay_ns = delay_ns;
}
}

Expand Down Expand Up @@ -66,6 +85,8 @@ impl<'a, BUS, CS> MutexDevice<'a, BUS, CS, super::NoDelay> {
bus,
cs,
delay: super::NoDelay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}
}
Expand All @@ -88,6 +109,13 @@ where
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
let bus = &mut *self.bus.lock().unwrap();

transaction(operations, bus, &mut self.delay, &mut self.cs)
transaction(
operations,
bus,
&mut self.delay,
&mut self.cs,
self.cs_to_clock_delay_ns,
self.clock_to_cs_delay_ns,
)
}
}
32 changes: 30 additions & 2 deletions embedded-hal-bus/src/spi/refcell.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ pub struct RefCellDevice<'a, BUS, CS, D> {
bus: &'a RefCell<BUS>,
cs: CS,
delay: D,
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
cs_to_clock_delay_ns: u32,
clock_to_cs_delay_ns: u32,
}

impl<'a, BUS, CS, D> RefCellDevice<'a, BUS, CS, D> {
Expand All @@ -31,7 +34,23 @@ impl<'a, BUS, CS, D> RefCellDevice<'a, BUS, CS, D> {
CS: OutputPin,
{
cs.set_high()?;
Ok(Self { bus, cs, delay })
Ok(Self {
bus,
cs,
delay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}

/// Set the delay between the CS pin toggle and the first clock
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
self.cs_to_clock_delay_ns = delay_ns;
}

/// Set the delay between the last clock and the CS pin reset
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
self.clock_to_cs_delay_ns = delay_ns;
}
}

Expand Down Expand Up @@ -65,6 +84,8 @@ impl<'a, BUS, CS> RefCellDevice<'a, BUS, CS, super::NoDelay> {
bus,
cs,
delay: super::NoDelay,
cs_to_clock_delay_ns: 0,
clock_to_cs_delay_ns: 0,
})
}
}
Expand All @@ -87,6 +108,13 @@ where
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
let bus = &mut *self.bus.borrow_mut();

transaction(operations, bus, &mut self.delay, &mut self.cs)
transaction(
operations,
bus,
&mut self.delay,
&mut self.cs,
self.cs_to_clock_delay_ns,
self.clock_to_cs_delay_ns,
)
}
}
8 changes: 8 additions & 0 deletions embedded-hal-bus/src/spi/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ pub fn transaction<Word, BUS, CS, D>(
bus: &mut BUS,
delay: &mut D,
cs: &mut CS,
cs_to_clock_delay_ns: u32,
clock_to_cs_delay_ns: u32,
) -> Result<(), DeviceError<BUS::Error, CS::Error>>
where
BUS: SpiBus<Word> + ErrorType,
Expand All @@ -19,6 +21,9 @@ where
Word: Copy,
{
cs.set_low().map_err(DeviceError::Cs)?;
if cs_to_clock_delay_ns > 0 {
delay.delay_ns(cs_to_clock_delay_ns);
}

let op_res = operations.iter_mut().try_for_each(|op| match op {
Operation::Read(buf) => bus.read(buf),
Expand All @@ -34,6 +39,9 @@ where

// On failure, it's important to still flush and deassert CS.
let flush_res = bus.flush();
if clock_to_cs_delay_ns > 0 {
delay.delay_ns(cs_to_clock_delay_ns);
}
let cs_res = cs.set_high();

op_res.map_err(DeviceError::Spi)?;
Expand Down

0 comments on commit ab42bc6

Please sign in to comment.