Skip to content

Commit 27d51aa

Browse files
committed
sdio: add GPIO pins configuration
Adds `Pins` + `Mode` type for SDIO GPIO pin configuration.
1 parent 7d23f4d commit 27d51aa

File tree

2 files changed

+247
-9
lines changed

2 files changed

+247
-9
lines changed

esp-hal/src/sdio.rs

Lines changed: 70 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,13 @@ use embedded_hal::mmc::{
1717
tuning::{TuningMode, TuningWidth},
1818
};
1919

20+
mod pins;
2021
mod slc;
2122
mod slchost;
2223

23-
pub use slc::*;
24-
pub use slchost::*;
24+
pub use pins::Pins;
25+
pub use slc::{AnySlc, SlcInfo, SlcInstance};
26+
pub use slchost::{AnySlchost, SlchostInfo, SlchostInstance};
2527

2628
/// SDIO peripheral instance.
2729
pub trait PeripheralInstance: crate::private::Sealed {
@@ -33,30 +35,79 @@ pub trait PeripheralInstance: crate::private::Sealed {
3335
fn info(&self) -> &'static Self::Info;
3436
}
3537

38+
/// Represents the transmission modes for the SDIO peripheral.
39+
#[repr(u8)]
40+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
41+
pub enum Mode {
42+
/// SPI transmission mode.
43+
///
44+
/// Uses the following I/O signals:
45+
///
46+
/// - `SCLK`
47+
/// - `MOSI`
48+
/// - `MISO`
49+
/// - `IRQ`
50+
/// - `#CS`
51+
Spi,
52+
/// SD 1-bit transmission mode.
53+
///
54+
/// Uses the following I/O signals:
55+
///
56+
/// - `CLK`
57+
/// - `CMD`
58+
/// - `DAT0`
59+
/// - `IRQ`
60+
Sd1bit,
61+
/// SD 4-bit transmission mode.
62+
///
63+
/// Uses the following I/O signals:
64+
///
65+
/// - `CLK`
66+
/// - `CMD`
67+
/// - `DAT0`
68+
/// - `DAT1`
69+
/// - `DAT2`
70+
/// - `DAT3`
71+
Sd4bit,
72+
}
73+
3674
/// Represents the SDIO 2.0 peripheral for the microcontroller.
3775
#[derive(Debug)]
3876
pub struct Sdio<'d> {
3977
slc: AnySlc<'d>,
4078
slchost: AnySlchost<'d>,
79+
pins: Pins<'d>,
4180
}
4281

4382
impl<'d> Sdio<'d> {
4483
/// Creates a new [Sdio].
4584
///
4685
/// # Example
86+
#[doc = crate::before_snippet!()]
87+
/// ```rust, no_run
88+
/// use esp_hal::sdio::{Mode, Pins, Sdio};
4789
///
48-
/// ```rust,no_run
49-
/// use esp_hal::sdio::Sdio;
90+
/// let pins = Pins::new(
91+
/// Mode::Sd4bit,
92+
/// peripherals.GPIO19, // CLK/SCLK
93+
/// peripherals.GPIO18, // CMD/MOSI
94+
/// peripherals.GPIO20, // DAT0/MISO
95+
/// peripherals.GPIO21, // DAT1/IRQ
96+
/// peripherals.GPIO22, // DAT2
97+
/// peripherals.GPIO23, // DAT3/#CS
98+
/// );
5099
///
51-
/// use crate::peripheral::Peripherals;
52-
///
53-
/// let dp = Peripheral::take().unwrap();
54-
/// let _sdio = Sdio::new(dp.slc, dp.slchost);
100+
/// let _sdio = Sdio::new(peripherals.slc, peripherals.slchost, pins);
55101
/// ```
56-
pub fn new(slc: impl SlcInstance + 'd, slchost: impl SlchostInstance + 'd) -> Self {
102+
pub fn new(
103+
slc: impl SlcInstance + 'd,
104+
slchost: impl SlchostInstance + 'd,
105+
pins: Pins<'d>,
106+
) -> Self {
57107
Self {
58108
slc: slc.degrade(),
59109
slchost: slchost.degrade(),
110+
pins,
60111
}
61112
}
62113

@@ -69,6 +120,16 @@ impl<'d> Sdio<'d> {
69120
pub fn slchost(&self) -> &'static SlchostInfo {
70121
self.slchost.info()
71122
}
123+
124+
/// Gets a reference to the [Pins] information.
125+
pub const fn pins(&self) -> &Pins<'_> {
126+
&self.pins
127+
}
128+
129+
/// Gets the bus mode of the SDIO peripheral.
130+
pub const fn bus_mode(&self) -> Mode {
131+
self.pins.mode()
132+
}
72133
}
73134

74135
/// Represents the error variants for SDIO peripherals.

esp-hal/src/sdio/pins.rs

Lines changed: 177 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
1+
use super::{Error, Mode};
2+
use crate::gpio::{Flex, Level, Output, OutputConfig, OutputPin, Pin};
3+
4+
/// Represents the GPIO pins used for SDIO communication.
5+
///
6+
/// The pins are configurable for the SPI + SD (1-bit, 4-bit) operation modes.
7+
///
8+
/// The CLK/SCLK pin is configured as an output, all other pins are input/output
9+
/// `Flex` pins.
10+
#[derive(Debug)]
11+
pub struct Pins<'d> {
12+
mode: Mode,
13+
clk_sclk: Output<'d>,
14+
cmd_mosi: Flex<'d>,
15+
dat0_miso: Flex<'d>,
16+
dat1_irq: Flex<'d>,
17+
dat2: Flex<'d>,
18+
dat3_cs: Flex<'d>,
19+
}
20+
21+
impl<'d> Pins<'d> {
22+
/// Creates a new [Pins] from the provided GPIO pins.
23+
///
24+
/// ```rust, no_run
25+
#[doc = crate::before_snippet!()]
26+
/// use esp_hal::sdio::{Mode, Pins};
27+
///
28+
/// let _pins = Pins::new(
29+
/// Mode::Sd4bit,
30+
/// peripherals.GPIO19, // CLK/SCLK
31+
/// peripherals.GPIO18, // CMD/MOSI
32+
/// peripherals.GPIO20, // DAT0/MISO
33+
/// peripherals.GPIO21, // DAT1/IRQ
34+
/// peripherals.GPIO22, // DAT2
35+
/// peripherals.GPIO23, // DAT3/#CS
36+
/// );
37+
/// ```
38+
pub fn new(
39+
mode: Mode,
40+
clk_sclk: impl OutputPin + 'd,
41+
cmd_mosi: impl Pin + 'd,
42+
dat0_miso: impl Pin + 'd,
43+
dat1_irq: impl Pin + 'd,
44+
dat2: impl Pin + 'd,
45+
dat3_cs: impl Pin + 'd,
46+
) -> Self {
47+
Self {
48+
mode,
49+
clk_sclk: Output::new(clk_sclk, Level::Low, OutputConfig::default()),
50+
cmd_mosi: Flex::new(cmd_mosi),
51+
dat0_miso: Flex::new(dat0_miso),
52+
dat1_irq: Flex::new(dat1_irq),
53+
dat2: Flex::new(dat2),
54+
dat3_cs: Flex::new(dat3_cs),
55+
}
56+
}
57+
58+
/// Gets the [Mode] of the [Pins].
59+
pub const fn mode(&self) -> Mode {
60+
self.mode
61+
}
62+
63+
/// Sets the [Mode] of the [Pins].
64+
pub fn set_mode(&mut self, mode: Mode) {
65+
self.mode = mode;
66+
}
67+
68+
/// Gets the CLK signal for the [Pins].
69+
///
70+
/// Returns an [Error] if the [Mode] is SPI.
71+
pub const fn clk(&self) -> Result<&Output<'_>, Error> {
72+
match self.mode {
73+
Mode::Sd1bit | Mode::Sd4bit => Ok(&self.clk_sclk),
74+
Mode::Spi => Err(Error::General),
75+
}
76+
}
77+
78+
/// Gets the SCLK signal for the [Pins].
79+
///
80+
/// Returns an [Error] if the [Mode] is not SPI.
81+
pub const fn sclk(&self) -> Result<&Output<'_>, Error> {
82+
match self.mode {
83+
Mode::Spi => Ok(&self.clk_sclk),
84+
Mode::Sd1bit | Mode::Sd4bit => Err(Error::General),
85+
}
86+
}
87+
88+
/// Gets the CMD signal for the [Pins].
89+
///
90+
/// Returns an [Error] if the [Mode] is SPI.
91+
pub const fn cmd(&self) -> Result<&Flex<'_>, Error> {
92+
match self.mode {
93+
Mode::Sd1bit | Mode::Sd4bit => Ok(&self.cmd_mosi),
94+
Mode::Spi => Err(Error::General),
95+
}
96+
}
97+
98+
/// Gets the MOSI signal for the [Pins].
99+
///
100+
/// Returns an [Error] if the [Mode] is not SPI.
101+
pub const fn mosi(&self) -> Result<&Flex<'_>, Error> {
102+
match self.mode {
103+
Mode::Spi => Ok(&self.cmd_mosi),
104+
Mode::Sd1bit | Mode::Sd4bit => Err(Error::General),
105+
}
106+
}
107+
108+
/// Gets the DAT0 signal for the [Pins].
109+
///
110+
/// Returns an [Error] if the [Mode] is SPI.
111+
pub const fn dat0(&self) -> Result<&Flex<'_>, Error> {
112+
match self.mode {
113+
Mode::Sd1bit | Mode::Sd4bit => Ok(&self.dat0_miso),
114+
Mode::Spi => Err(Error::General),
115+
}
116+
}
117+
118+
/// Gets the MISO signal for the [Pins].
119+
///
120+
/// Returns an [Error] if the [Mode] is not SPI.
121+
pub const fn miso(&self) -> Result<&Flex<'_>, Error> {
122+
match self.mode {
123+
Mode::Spi => Ok(&self.cmd_mosi),
124+
Mode::Sd1bit | Mode::Sd4bit => Err(Error::General),
125+
}
126+
}
127+
128+
/// Gets the DAT1 signal for the [Pins].
129+
///
130+
/// Returns an [Error] if the [Mode] is not SD 4-bit.
131+
pub const fn dat1(&self) -> Result<&Flex<'_>, Error> {
132+
match self.mode {
133+
Mode::Sd4bit => Ok(&self.dat1_irq),
134+
Mode::Sd1bit | Mode::Spi => Err(Error::General),
135+
}
136+
}
137+
138+
/// Gets the IRQ signal for the [Pins].
139+
///
140+
/// Returns an [Error] if the [Mode] is SD 4-bit.
141+
pub const fn irq(&self) -> Result<&Flex<'_>, Error> {
142+
match self.mode {
143+
Mode::Sd1bit | Mode::Spi => Ok(&self.dat1_irq),
144+
Mode::Sd4bit => Err(Error::General),
145+
}
146+
}
147+
148+
/// Gets the DAT2 signal for the [Pins].
149+
///
150+
/// Returns an [Error] if the [Mode] is not SD 4-bit.
151+
pub const fn dat2(&self) -> Result<&Flex<'_>, Error> {
152+
match self.mode {
153+
Mode::Sd4bit => Ok(&self.dat2),
154+
Mode::Sd1bit | Mode::Spi => Err(Error::General),
155+
}
156+
}
157+
158+
/// Gets the DAT3 signal for the [Pins].
159+
///
160+
/// Returns an [Error] if the [Mode] is SPI.
161+
pub const fn dat3(&self) -> Result<&Flex<'_>, Error> {
162+
match self.mode {
163+
Mode::Sd4bit => Ok(&self.dat3_cs),
164+
Mode::Sd1bit | Mode::Spi => Err(Error::General),
165+
}
166+
}
167+
168+
/// Gets the CS signal for the [Pins].
169+
///
170+
/// Returns an [Error] if the [Mode] is not SPI.
171+
pub const fn cs(&self) -> Result<&Flex<'_>, Error> {
172+
match self.mode {
173+
Mode::Spi => Ok(&self.dat3_cs),
174+
Mode::Sd1bit | Mode::Sd4bit => Err(Error::General),
175+
}
176+
}
177+
}

0 commit comments

Comments
 (0)