Skip to content

Commit dad0624

Browse files
committed
Move SpiPinGuard into global state
1 parent 5699955 commit dad0624

File tree

2 files changed

+95
-46
lines changed

2 files changed

+95
-46
lines changed

esp-hal/src/spi/master/dma.rs

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ impl<'d> Spi<'d, Blocking> {
6767
/// ```
6868
#[instability::unstable]
6969
pub fn with_dma(self, channel: impl DmaChannelFor<AnySpi<'d>>) -> SpiDma<'d, Blocking> {
70-
SpiDma::new(self.spi, self.pins, channel.degrade())
70+
SpiDma::new(self.spi, channel.degrade())
7171
}
7272
}
7373

@@ -115,12 +115,10 @@ pub struct SpiDma<'d, Dm>
115115
where
116116
Dm: DriverMode,
117117
{
118-
pub(crate) spi: AnySpi<'d>,
118+
spi: SpiWrapper<'d>,
119119
pub(crate) channel: Channel<Dm, PeripheralDmaChannel<AnySpi<'d>>>,
120120
#[cfg(all(esp32, spi_address_workaround))]
121121
address_buffer: DmaTxBuf,
122-
guard: PeripheralGuard,
123-
pins: SpiPinGuard,
124122
}
125123

126124
impl<Dm> crate::private::Sealed for SpiDma<'_, Dm> where Dm: DriverMode {}
@@ -135,18 +133,12 @@ impl<'d> SpiDma<'d, Blocking> {
135133
channel: self.channel.into_async(),
136134
#[cfg(all(esp32, spi_address_workaround))]
137135
address_buffer: self.address_buffer,
138-
guard: self.guard,
139-
pins: self.pins,
140136
}
141137
}
142138

143-
pub(super) fn new(
144-
spi: AnySpi<'d>,
145-
pins: SpiPinGuard,
146-
channel: PeripheralDmaChannel<AnySpi<'d>>,
147-
) -> Self {
139+
pub(super) fn new(spi: SpiWrapper<'d>, channel: PeripheralDmaChannel<AnySpi<'d>>) -> Self {
148140
let channel = Channel::new(channel);
149-
channel.runtime_ensure_compatible(&spi);
141+
channel.runtime_ensure_compatible(&spi.spi);
150142
#[cfg(all(esp32, spi_address_workaround))]
151143
let address_buffer = {
152144
use crate::dma::DmaDescriptor;
@@ -167,8 +159,6 @@ impl<'d> SpiDma<'d, Blocking> {
167159
))
168160
};
169161

170-
let guard = PeripheralGuard::new(spi.info().peripheral);
171-
172162
let (_info, state) = spi.dma_parts();
173163

174164
state.tx_transfer_in_progress.set(false);
@@ -179,8 +169,6 @@ impl<'d> SpiDma<'d, Blocking> {
179169
channel,
180170
#[cfg(all(esp32, spi_address_workaround))]
181171
address_buffer,
182-
guard,
183-
pins,
184172
}
185173
}
186174

@@ -243,8 +231,6 @@ impl<'d> SpiDma<'d, Async> {
243231
channel: self.channel.into_blocking(),
244232
#[cfg(all(esp32, spi_address_workaround))]
245233
address_buffer: self.address_buffer,
246-
guard: self.guard,
247-
pins: self.pins,
248234
}
249235
}
250236

@@ -1537,3 +1523,15 @@ for_each_spi_master!(
15371523
}
15381524
};
15391525
);
1526+
1527+
impl SpiWrapper<'_> {
1528+
#[inline(always)]
1529+
fn dma_parts(&self) -> (&'static Info, &'static State) {
1530+
self.spi.dma_parts()
1531+
}
1532+
1533+
#[inline(always)]
1534+
fn dma_peripheral(&self) -> crate::dma::DmaPeripheral {
1535+
self.spi.dma_peripheral()
1536+
}
1537+
}

esp-hal/src/spi/master/mod.rs

Lines changed: 79 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#[cfg(esp32)]
3838
use core::cell::Cell;
3939
use core::{
40+
cell::RefCell,
4041
future::Future,
4142
marker::PhantomData,
4243
pin::Pin,
@@ -639,6 +640,16 @@ struct SpiPinGuard {
639640
sio_pins: [PinGuard; SIO_PIN_COUNT],
640641
}
641642

643+
impl SpiPinGuard {
644+
const fn new_unconnected() -> Self {
645+
Self {
646+
sclk_pin: PinGuard::new_unconnected(),
647+
cs_pin: PinGuard::new_unconnected(),
648+
sio_pins: [const { PinGuard::new_unconnected() }; SIO_PIN_COUNT],
649+
}
650+
}
651+
}
652+
642653
/// Configuration errors.
643654
#[non_exhaustive]
644655
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -659,6 +670,42 @@ impl core::fmt::Display for ConfigError {
659670
}
660671
}
661672
}
673+
674+
#[derive(Debug)]
675+
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
676+
struct SpiWrapper<'d> {
677+
spi: AnySpi<'d>,
678+
_guard: PeripheralGuard,
679+
}
680+
681+
impl SpiWrapper<'_> {
682+
fn info(&self) -> &'static Info {
683+
self.spi.info()
684+
}
685+
686+
fn state(&self) -> &'static State {
687+
self.spi.state()
688+
}
689+
690+
fn parts(&self) -> (&'static Info, &'static State) {
691+
self.spi.parts()
692+
}
693+
694+
fn disable_peri_interrupt_on_all_cores(&self) {
695+
self.spi.disable_peri_interrupt_on_all_cores();
696+
}
697+
698+
fn set_interrupt_handler(&self, handler: InterruptHandler) {
699+
self.spi.set_interrupt_handler(handler);
700+
}
701+
}
702+
703+
impl Drop for SpiWrapper<'_> {
704+
fn drop(&mut self) {
705+
self.spi.state().deinit();
706+
}
707+
}
708+
662709
#[procmacros::doc_replace]
663710
/// SPI peripheral driver
664711
///
@@ -684,10 +731,8 @@ impl core::fmt::Display for ConfigError {
684731
#[derive(Debug)]
685732
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
686733
pub struct Spi<'d, Dm: DriverMode> {
687-
spi: AnySpi<'d>,
734+
spi: SpiWrapper<'d>,
688735
_mode: PhantomData<Dm>,
689-
guard: PeripheralGuard,
690-
pins: SpiPinGuard,
691736
}
692737

693738
impl<Dm: DriverMode> Sealed for Spi<'_, Dm> {}
@@ -715,17 +760,14 @@ impl<'d> Spi<'d, Blocking> {
715760
/// # {after_snippet}
716761
/// ```
717762
pub fn new(spi: impl Instance + 'd, config: Config) -> Result<Self, ConfigError> {
718-
let guard = PeripheralGuard::new(spi.info().peripheral);
763+
let _guard = PeripheralGuard::new(spi.info().peripheral);
719764

720765
let mut this = Spi {
721766
_mode: PhantomData,
722-
guard,
723-
pins: SpiPinGuard {
724-
sclk_pin: PinGuard::new_unconnected(),
725-
cs_pin: PinGuard::new_unconnected(),
726-
sio_pins: [const { PinGuard::new_unconnected() }; SIO_PIN_COUNT],
767+
spi: SpiWrapper {
768+
spi: spi.degrade(),
769+
_guard,
727770
},
728-
spi: spi.degrade(),
729771
};
730772

731773
this.driver().init();
@@ -754,8 +796,6 @@ impl<'d> Spi<'d, Blocking> {
754796
Spi {
755797
spi: self.spi,
756798
_mode: PhantomData,
757-
guard: self.guard,
758-
pins: self.pins,
759799
}
760800
}
761801

@@ -803,8 +843,6 @@ impl<'d> Spi<'d, Async> {
803843
Spi {
804844
spi: self.spi,
805845
_mode: PhantomData,
806-
guard: self.guard,
807-
pins: self.pins,
808846
}
809847
}
810848

@@ -900,8 +938,9 @@ macro_rules! def_with_sio_pin {
900938
#[doc = " Enables both input and output functionality for the pin, and connects it"]
901939
#[doc = concat!(" to the SIO", stringify!($n), " output and input signals.")]
902940
#[instability::unstable]
903-
pub fn $fn(mut self, sio: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
904-
self.pins.sio_pins[$n] = self.connect_sio_pin(sio.into(), $n);
941+
pub fn $fn(self, sio: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
942+
self.driver().state.pins.borrow_mut().sio_pins[$n] =
943+
self.connect_sio_pin(sio.into(), $n);
905944

906945
self
907946
}
@@ -963,8 +1002,9 @@ where
9631002
///
9641003
/// # {after_snippet}
9651004
/// ```
966-
pub fn with_sck(mut self, sclk: impl PeripheralOutput<'d>) -> Self {
967-
self.pins.sclk_pin = self.connect_output_pin(sclk.into(), self.driver().info.sclk);
1005+
pub fn with_sck(self, sclk: impl PeripheralOutput<'d>) -> Self {
1006+
let (info, state) = self.spi.parts();
1007+
state.pins.borrow_mut().sclk_pin = self.connect_output_pin(sclk.into(), info.sclk);
9681008

9691009
self
9701010
}
@@ -991,8 +1031,9 @@ where
9911031
///
9921032
/// # {after_snippet}
9931033
/// ```
994-
pub fn with_mosi(mut self, mosi: impl PeripheralOutput<'d>) -> Self {
995-
self.pins.sio_pins[0] = self.connect_sio_output_pin(mosi.into(), 0);
1034+
pub fn with_mosi(self, mosi: impl PeripheralOutput<'d>) -> Self {
1035+
self.driver().state.pins.borrow_mut().sio_pins[0] =
1036+
self.connect_sio_output_pin(mosi.into(), 0);
9961037

9971038
self
9981039
}
@@ -1042,8 +1083,8 @@ where
10421083
/// See also [Self::with_mosi] when you only need a one-directional MOSI
10431084
/// signal.
10441085
#[instability::unstable]
1045-
pub fn with_sio0(mut self, mosi: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
1046-
self.pins.sio_pins[0] = self.connect_sio_pin(mosi.into(), 0);
1086+
pub fn with_sio0(self, mosi: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
1087+
self.driver().state.pins.borrow_mut().sio_pins[0] = self.connect_sio_pin(mosi.into(), 0);
10471088

10481089
self
10491090
}
@@ -1060,8 +1101,8 @@ where
10601101
/// See also [Self::with_miso] when you only need a one-directional MISO
10611102
/// signal.
10621103
#[instability::unstable]
1063-
pub fn with_sio1(mut self, sio1: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
1064-
self.pins.sio_pins[1] = self.connect_sio_pin(sio1.into(), 1);
1104+
pub fn with_sio1(self, sio1: impl PeripheralInput<'d> + PeripheralOutput<'d>) -> Self {
1105+
self.driver().state.pins.borrow_mut().sio_pins[1] = self.connect_sio_pin(sio1.into(), 1);
10651106

10661107
self
10671108
}
@@ -1093,8 +1134,10 @@ where
10931134
/// be set, regardless of the total number available. There is no
10941135
/// mechanism to select which CS line to use.
10951136
#[instability::unstable]
1096-
pub fn with_cs(mut self, cs: impl PeripheralOutput<'d>) -> Self {
1097-
self.pins.cs_pin = self.connect_output_pin(cs.into(), self.driver().info.cs(0));
1137+
pub fn with_cs(self, cs: impl PeripheralOutput<'d>) -> Self {
1138+
let (info, state) = self.spi.parts();
1139+
state.pins.borrow_mut().cs_pin = self.connect_output_pin(cs.into(), info.cs(0));
1140+
10981141
self
10991142
}
11001143

@@ -2417,6 +2460,8 @@ for_each_spi_master! {
24172460

24182461
static STATE: State = State {
24192462
waker: AtomicWaker::new(),
2463+
pins: RefCell::new(SpiPinGuard::new_unconnected()),
2464+
24202465
#[cfg(esp32)]
24212466
esp32_hack: Esp32Hack {
24222467
timing_miso_delay: Cell::new(None),
@@ -2441,19 +2486,25 @@ impl QspiInstance for AnySpi<'_> {}
24412486
#[doc(hidden)]
24422487
pub struct State {
24432488
waker: AtomicWaker,
2489+
pins: RefCell<SpiPinGuard>,
24442490

24452491
#[cfg(esp32)]
24462492
esp32_hack: Esp32Hack,
24472493
}
24482494

2495+
impl State {
2496+
fn deinit(&self) {
2497+
*self.pins.borrow_mut() = SpiPinGuard::new_unconnected();
2498+
}
2499+
}
2500+
24492501
#[cfg(esp32)]
24502502
struct Esp32Hack {
24512503
timing_miso_delay: Cell<Option<u8>>,
24522504
extra_dummy: Cell<u8>,
24532505
}
24542506

2455-
#[cfg(esp32)]
2456-
unsafe impl Sync for Esp32Hack {}
2507+
unsafe impl Sync for State {}
24572508

24582509
#[ram]
24592510
fn handle_async(info: &'static Info, state: &'static State) {

0 commit comments

Comments
 (0)