Skip to content

Commit ab42bc6

Browse files
author
vchapuis
committed
feat(embedded-hal-bus): Spi - Add support for cs to clock delay
1 parent a0ccb65 commit ab42bc6

File tree

6 files changed

+159
-11
lines changed

6 files changed

+159
-11
lines changed

embedded-hal-bus/src/spi/atomic.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,9 @@ pub struct AtomicDevice<'a, BUS, CS, D> {
3030
bus: &'a AtomicCell<BUS>,
3131
cs: CS,
3232
delay: D,
33+
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
34+
cs_to_clock_delay_ns: u32,
35+
clock_to_cs_delay_ns: u32,
3336
}
3437

3538
#[derive(Debug, Copy, Clone)]
@@ -55,7 +58,23 @@ impl<'a, BUS, CS, D> AtomicDevice<'a, BUS, CS, D> {
5558
CS: OutputPin,
5659
{
5760
cs.set_high()?;
58-
Ok(Self { bus, cs, delay })
61+
Ok(Self {
62+
bus,
63+
cs,
64+
delay,
65+
cs_to_clock_delay_ns: 0,
66+
clock_to_cs_delay_ns: 0,
67+
})
68+
}
69+
70+
/// Set the delay between the CS pin toggle and the first clock
71+
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
72+
self.cs_to_clock_delay_ns = delay_ns;
73+
}
74+
75+
/// Set the delay between the last clock and the CS pin reset
76+
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
77+
self.clock_to_cs_delay_ns = delay_ns;
5978
}
6079
}
6180

@@ -93,6 +112,8 @@ where
93112
bus,
94113
cs,
95114
delay: super::NoDelay,
115+
cs_to_clock_delay_ns: 0,
116+
clock_to_cs_delay_ns: 0,
96117
})
97118
}
98119
}
@@ -134,7 +155,14 @@ where
134155

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

137-
let result = transaction(operations, bus, &mut self.delay, &mut self.cs);
158+
let result = transaction(
159+
operations,
160+
bus,
161+
&mut self.delay,
162+
&mut self.cs,
163+
self.cs_to_clock_delay_ns,
164+
self.clock_to_cs_delay_ns,
165+
);
138166

139167
self.bus
140168
.busy

embedded-hal-bus/src/spi/critical_section.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ pub struct CriticalSectionDevice<'a, BUS, CS, D> {
2121
bus: &'a Mutex<RefCell<BUS>>,
2222
cs: CS,
2323
delay: D,
24+
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
25+
cs_to_clock_delay_ns: u32,
26+
clock_to_cs_delay_ns: u32,
2427
}
2528

2629
impl<'a, BUS, CS, D> CriticalSectionDevice<'a, BUS, CS, D> {
@@ -34,7 +37,23 @@ impl<'a, BUS, CS, D> CriticalSectionDevice<'a, BUS, CS, D> {
3437
CS: OutputPin,
3538
{
3639
cs.set_high()?;
37-
Ok(Self { bus, cs, delay })
40+
Ok(Self {
41+
bus,
42+
cs,
43+
delay,
44+
cs_to_clock_delay_ns: 0,
45+
clock_to_cs_delay_ns: 0,
46+
})
47+
}
48+
49+
/// Set the delay between the CS pin toggle and the first clock
50+
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
51+
self.cs_to_clock_delay_ns = delay_ns;
52+
}
53+
54+
/// Set the delay between the last clock and the CS pin reset
55+
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
56+
self.clock_to_cs_delay_ns = delay_ns;
3857
}
3958
}
4059

@@ -68,6 +87,8 @@ impl<'a, BUS, CS> CriticalSectionDevice<'a, BUS, CS, super::NoDelay> {
6887
bus,
6988
cs,
7089
delay: super::NoDelay,
90+
cs_to_clock_delay_ns: 0,
91+
clock_to_cs_delay_ns: 0,
7192
})
7293
}
7394
}
@@ -91,7 +112,14 @@ where
91112
critical_section::with(|cs| {
92113
let bus = &mut *self.bus.borrow_ref_mut(cs);
93114

94-
transaction(operations, bus, &mut self.delay, &mut self.cs)
115+
transaction(
116+
operations,
117+
bus,
118+
&mut self.delay,
119+
&mut self.cs,
120+
self.cs_to_clock_delay_ns,
121+
self.clock_to_cs_delay_ns,
122+
)
95123
})
96124
}
97125
}

embedded-hal-bus/src/spi/exclusive.rs

+31-3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,9 @@ pub struct ExclusiveDevice<BUS, CS, D> {
2020
bus: BUS,
2121
cs: CS,
2222
delay: D,
23+
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
24+
cs_to_clock_delay_ns: u32,
25+
clock_to_cs_delay_ns: u32,
2326
}
2427

2528
impl<BUS, CS, D> ExclusiveDevice<BUS, CS, D> {
@@ -28,12 +31,28 @@ impl<BUS, CS, D> ExclusiveDevice<BUS, CS, D> {
2831
/// This sets the `cs` pin high, and returns an error if that fails. It is recommended
2932
/// to set the pin high the moment it's configured as an output, to avoid glitches.
3033
#[inline]
31-
pub fn new(bus: BUS, mut cs: CS, delay: D) -> Result<Self, CS::Error>
34+
pub fn new(bus: BUS, mut cs: CS, delay: D, cs_to_clock_delay_ns: u32) -> Result<Self, CS::Error>
3235
where
3336
CS: OutputPin,
3437
{
3538
cs.set_high()?;
36-
Ok(Self { bus, cs, delay })
39+
Ok(Self {
40+
bus,
41+
cs,
42+
delay,
43+
cs_to_clock_delay_ns: 0,
44+
clock_to_cs_delay_ns: 0,
45+
})
46+
}
47+
48+
/// Set the delay between the CS pin toggle and the first clock
49+
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
50+
self.cs_to_clock_delay_ns = delay_ns;
51+
}
52+
53+
/// Set the delay between the last clock and the CS pin reset
54+
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
55+
self.clock_to_cs_delay_ns = delay_ns;
3756
}
3857

3958
/// Returns a reference to the underlying bus object.
@@ -79,6 +98,8 @@ impl<BUS, CS> ExclusiveDevice<BUS, CS, super::NoDelay> {
7998
bus,
8099
cs,
81100
delay: super::NoDelay,
101+
cs_to_clock_delay_ns: 0,
102+
clock_to_cs_delay_ns: 0,
82103
})
83104
}
84105
}
@@ -99,7 +120,14 @@ where
99120
{
100121
#[inline]
101122
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
102-
transaction(operations, &mut self.bus, &mut self.delay, &mut self.cs)
123+
transaction(
124+
operations,
125+
&mut self.bus,
126+
&mut self.delay,
127+
&mut self.cs,
128+
self.cs_to_clock_delay_ns,
129+
self.clock_to_cs_delay_ns,
130+
)
103131
}
104132
}
105133

embedded-hal-bus/src/spi/mutex.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,9 @@ pub struct MutexDevice<'a, BUS, CS, D> {
1919
bus: &'a Mutex<BUS>,
2020
cs: CS,
2121
delay: D,
22+
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
23+
cs_to_clock_delay_ns: u32,
24+
clock_to_cs_delay_ns: u32,
2225
}
2326

2427
impl<'a, BUS, CS, D> MutexDevice<'a, BUS, CS, D> {
@@ -32,7 +35,23 @@ impl<'a, BUS, CS, D> MutexDevice<'a, BUS, CS, D> {
3235
CS: OutputPin,
3336
{
3437
cs.set_high()?;
35-
Ok(Self { bus, cs, delay })
38+
Ok(Self {
39+
bus,
40+
cs,
41+
delay,
42+
cs_to_clock_delay_ns: 0,
43+
clock_to_cs_delay_ns: 0,
44+
})
45+
}
46+
47+
/// Set the delay between the CS pin toggle and the first clock
48+
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
49+
self.cs_to_clock_delay_ns = delay_ns;
50+
}
51+
52+
/// Set the delay between the last clock and the CS pin reset
53+
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
54+
self.clock_to_cs_delay_ns = delay_ns;
3655
}
3756
}
3857

@@ -66,6 +85,8 @@ impl<'a, BUS, CS> MutexDevice<'a, BUS, CS, super::NoDelay> {
6685
bus,
6786
cs,
6887
delay: super::NoDelay,
88+
cs_to_clock_delay_ns: 0,
89+
clock_to_cs_delay_ns: 0,
6990
})
7091
}
7192
}
@@ -88,6 +109,13 @@ where
88109
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
89110
let bus = &mut *self.bus.lock().unwrap();
90111

91-
transaction(operations, bus, &mut self.delay, &mut self.cs)
112+
transaction(
113+
operations,
114+
bus,
115+
&mut self.delay,
116+
&mut self.cs,
117+
self.cs_to_clock_delay_ns,
118+
self.clock_to_cs_delay_ns,
119+
)
92120
}
93121
}

embedded-hal-bus/src/spi/refcell.rs

+30-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ pub struct RefCellDevice<'a, BUS, CS, D> {
1818
bus: &'a RefCell<BUS>,
1919
cs: CS,
2020
delay: D,
21+
/// Implementation of <https://docs.rs/embedded-hal/latest/embedded_hal/spi/index.html#cs-to-clock-delays>
22+
cs_to_clock_delay_ns: u32,
23+
clock_to_cs_delay_ns: u32,
2124
}
2225

2326
impl<'a, BUS, CS, D> RefCellDevice<'a, BUS, CS, D> {
@@ -31,7 +34,23 @@ impl<'a, BUS, CS, D> RefCellDevice<'a, BUS, CS, D> {
3134
CS: OutputPin,
3235
{
3336
cs.set_high()?;
34-
Ok(Self { bus, cs, delay })
37+
Ok(Self {
38+
bus,
39+
cs,
40+
delay,
41+
cs_to_clock_delay_ns: 0,
42+
clock_to_cs_delay_ns: 0,
43+
})
44+
}
45+
46+
/// Set the delay between the CS pin toggle and the first clock
47+
pub fn set_cs_to_clock_delay_ns(&mut self, delay_ns: u32) {
48+
self.cs_to_clock_delay_ns = delay_ns;
49+
}
50+
51+
/// Set the delay between the last clock and the CS pin reset
52+
pub fn set_clock_to_cs_delay_ns(&mut self, delay_ns: u32) {
53+
self.clock_to_cs_delay_ns = delay_ns;
3554
}
3655
}
3756

@@ -65,6 +84,8 @@ impl<'a, BUS, CS> RefCellDevice<'a, BUS, CS, super::NoDelay> {
6584
bus,
6685
cs,
6786
delay: super::NoDelay,
87+
cs_to_clock_delay_ns: 0,
88+
clock_to_cs_delay_ns: 0,
6889
})
6990
}
7091
}
@@ -87,6 +108,13 @@ where
87108
fn transaction(&mut self, operations: &mut [Operation<'_, Word>]) -> Result<(), Self::Error> {
88109
let bus = &mut *self.bus.borrow_mut();
89110

90-
transaction(operations, bus, &mut self.delay, &mut self.cs)
111+
transaction(
112+
operations,
113+
bus,
114+
&mut self.delay,
115+
&mut self.cs,
116+
self.cs_to_clock_delay_ns,
117+
self.clock_to_cs_delay_ns,
118+
)
91119
}
92120
}

embedded-hal-bus/src/spi/shared.rs

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ pub fn transaction<Word, BUS, CS, D>(
1111
bus: &mut BUS,
1212
delay: &mut D,
1313
cs: &mut CS,
14+
cs_to_clock_delay_ns: u32,
15+
clock_to_cs_delay_ns: u32,
1416
) -> Result<(), DeviceError<BUS::Error, CS::Error>>
1517
where
1618
BUS: SpiBus<Word> + ErrorType,
@@ -19,6 +21,9 @@ where
1921
Word: Copy,
2022
{
2123
cs.set_low().map_err(DeviceError::Cs)?;
24+
if cs_to_clock_delay_ns > 0 {
25+
delay.delay_ns(cs_to_clock_delay_ns);
26+
}
2227

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

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

3947
op_res.map_err(DeviceError::Spi)?;

0 commit comments

Comments
 (0)