Skip to content

Commit 5fcb28e

Browse files
committed
sdio: initial SDIO HAL implementation
Provides the initial skeleton for the `embedded_hal::mmc::MmcOps` implementation for the SDIO peripherals on the ESP32C6 microcontroller.
1 parent 3cd3606 commit 5fcb28e

File tree

11 files changed

+295
-9
lines changed

11 files changed

+295
-9
lines changed

esp-hal/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4747
- UART: Added HW and SW flow control config option (#3435)
4848
- I2C master: `SoftwareTimeout` and `Config::with_software_timeout`. (#3577)
4949
- `esp_hal::time::{Instant, Duration}` now implement `Hash` (#3577)
50+
- Added `Sdio` support (#3503)
5051

5152
### Changed
5253

esp-hal/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ bitflags = "2.9.0"
2727
bytemuck = "1.22.0"
2828
cfg-if = "1.0.0"
2929
critical-section = { version = "1.2.0", features = ["restore-state-u32"] }
30-
embedded-hal = "1.0.0"
31-
embedded-hal-async = "1.0.0"
30+
embedded-hal = { version = "1.0.0", git = "https://github.com/rmsyn/embedded-hal", branch = "embedded-hal/mmc" }
31+
embedded-hal-async = { version = "1.0.0", git = "https://github.com/rmsyn/embedded-hal", branch = "embedded-hal/mmc" }
3232
enumset = "1.1.6"
3333
paste = "1.0.15"
3434
portable-atomic = { version = "1.11.0", default-features = false }

esp-hal/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,8 @@ pub mod i2c;
222222
pub mod peripheral;
223223
#[cfg(all(feature = "unstable", any(hmac, sha)))]
224224
mod reg_access;
225+
#[cfg(any(feature = "esp32", feature = "esp32c6"))]
226+
pub mod sdio;
225227
#[cfg(any(spi0, spi1, spi2, spi3))]
226228
pub mod spi;
227229
pub mod system;

esp-hal/src/sdio.rs

Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
//! # Secure Digital I/O - Slave Mode
2+
//!
3+
//! ## Overiew
4+
//!
5+
//! The peripheral can be used to transfer data over the SDIO bus in `Slave`
6+
//! mode.
7+
8+
use embedded_hal::mmc::{
9+
CardMode,
10+
CardType,
11+
FifoStatus,
12+
MmcCommon,
13+
MmcDevice,
14+
Reset,
15+
command::MmcCommand,
16+
response::MmcResponse,
17+
tuning::{TuningMode, TuningWidth},
18+
};
19+
20+
mod slc;
21+
mod slchost;
22+
23+
pub use slc::*;
24+
pub use slchost::*;
25+
26+
/// SDIO peripheral instance.
27+
pub trait PeripheralInstance: crate::private::Sealed {
28+
/// Represents the peripheral information type containing the register
29+
/// block.
30+
type Info;
31+
32+
/// Gets a static shared reference to the peripheral information.
33+
fn info(&self) -> &'static Self::Info;
34+
}
35+
36+
/// Represents the SDIO 2.0 peripheral for the microcontroller.
37+
#[derive(Debug)]
38+
pub struct Sdio<'d> {
39+
slc: AnySlc<'d>,
40+
slchost: AnySlchost<'d>,
41+
}
42+
43+
impl<'d> Sdio<'d> {
44+
/// Creates a new [Sdio].
45+
///
46+
/// # Example
47+
///
48+
/// ```rust,no_run
49+
/// use esp_hal::sdio::Sdio;
50+
///
51+
/// use crate::peripheral::Peripherals;
52+
///
53+
/// let dp = Peripheral::take().unwrap();
54+
/// let _sdio = Sdio::new(dp.slc, dp.slchost);
55+
/// ```
56+
pub fn new(slc: impl SlcInstance + 'd, slchost: impl SlchostInstance + 'd) -> Self {
57+
Self {
58+
slc: slc.degrade(),
59+
slchost: slchost.degrade(),
60+
}
61+
}
62+
63+
/// Gets a static reference to the SLC information.
64+
pub fn slc(&self) -> &'static SlcInfo {
65+
self.slc.info()
66+
}
67+
68+
/// Gets a static reference to the SLCHOST information.
69+
pub fn slchost(&self) -> &'static SlchostInfo {
70+
self.slchost.info()
71+
}
72+
}
73+
74+
/// Represents the error variants for SDIO peripherals.
75+
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
76+
pub enum Error {
77+
/// Indicates a general error occured.
78+
General,
79+
/// Indicates use of an illegal command.
80+
IllegalCommand,
81+
/// Indicates a CRC error from the previous command.
82+
Crc,
83+
/// The function and/or type is unimplemented.
84+
Unimplemented,
85+
}
86+
87+
impl Error {
88+
/// Creates a new [Error].
89+
pub const fn new() -> Self {
90+
Self::Unimplemented
91+
}
92+
93+
/// Creates an general [Error].
94+
#[inline]
95+
pub const fn general() -> Self {
96+
Self::General
97+
}
98+
99+
/// Creates an illegal command [Error].
100+
#[inline]
101+
pub const fn illegal_command() -> Self {
102+
Self::IllegalCommand
103+
}
104+
105+
/// Creates an crc [Error].
106+
#[inline]
107+
pub const fn crc() -> Self {
108+
Self::Crc
109+
}
110+
111+
/// Creates an unimplemented [Error].
112+
#[inline]
113+
pub const fn unimplemented() -> Self {
114+
Self::Unimplemented
115+
}
116+
}
117+
118+
impl Default for Error {
119+
fn default() -> Self {
120+
Self::new()
121+
}
122+
}
123+
124+
impl core::fmt::Display for Error {
125+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
126+
match self {
127+
Self::General => write!(f, "general"),
128+
Self::IllegalCommand => write!(f, "illegal command"),
129+
Self::Crc => write!(f, "CRC"),
130+
Self::Unimplemented => write!(f, "unimplemented"),
131+
}
132+
}
133+
}
134+
135+
impl core::error::Error for Error {}
136+
137+
impl<'d> MmcCommon for Sdio<'d> {
138+
type Error = Error;
139+
140+
fn card_type(&self) -> CardType {
141+
CardType::Sd
142+
}
143+
144+
fn card_mode(&self) -> CardMode {
145+
CardMode::Sdio
146+
}
147+
148+
fn setup_bus(&mut self) -> Result<(), Error> {
149+
Err(Error::unimplemented())
150+
}
151+
152+
<<<<<<< Updated upstream
153+
fn init(&mut self) -> Result<(), Self::Error> {
154+
=======
155+
fn init(&mut self) -> Result<(), Error> {
156+
// TODO: perform peripheral configuration
157+
self.state_transition(State::Standby)?;
158+
159+
>>>>>>> Stashed changes
160+
Err(Error::unimplemented())
161+
}
162+
163+
fn set_sample_phase(&mut self, _sample_phase: u8) {}
164+
165+
fn fifo_ready(&self, _fifo_status: FifoStatus) -> Result<(), Error> {
166+
Err(Error::unimplemented())
167+
}
168+
169+
fn wait_for_reset(&mut self, _reset: Reset, _timeout: u64) -> Result<(), Error> {
170+
Err(Error::unimplemented())
171+
}
172+
173+
fn wait_while_busy(&mut self, _timout_us: u64) -> Result<(), Error> {
174+
Err(Error::unimplemented())
175+
}
176+
177+
fn read_data(&mut self, _data: &mut [u8]) -> Result<(), Error> {
178+
Err(Error::unimplemented())
179+
}
180+
181+
fn write_data(&mut self, _data: &[u8]) -> Result<(), Error> {
182+
Err(Error::unimplemented())
183+
}
184+
185+
fn send_tuning(&mut self, _mode: TuningMode, _width: TuningWidth) -> Result<(), Error> {
186+
Err(Error::unimplemented())
187+
}
188+
189+
fn interrupt(&self) -> u32 {
190+
0
191+
}
192+
193+
fn set_interrupt(&mut self, _int: u32) {}
194+
195+
fn clear_all_interrupt(&mut self) {}
196+
197+
fn response_interrupt(&self) -> u32 {
198+
0
199+
}
200+
201+
fn set_response_interrupt(&mut self, _int: u32) {}
202+
203+
fn clear_all_response_interrupt(&mut self) {}
204+
}
205+
206+
impl<'d> MmcDevice for Sdio<'d> {
207+
fn read_command<C: MmcCommand>(&mut self) -> Result<C, Error> {
208+
Err(Error::unimplemented())
209+
}
210+
211+
fn write_response<R: MmcResponse>(&mut self, _response: &R) -> Result<(), Error> {
212+
Err(Error::unimplemented())
213+
}
214+
}

esp-hal/src/sdio/slc.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use super::PeripheralInstance;
2+
use crate::pac::slc;
3+
4+
crate::any_peripheral! {
5+
/// Any SDIO SLC peripheral.
6+
pub peripheral AnySlc<'d> {
7+
Slc(crate::peripherals::SLC<'d>)
8+
}
9+
}
10+
11+
/// Represents the SLC registers for SDIO peripherals.
12+
pub struct SlcInfo {
13+
/// Represents the SLC register block.
14+
pub register_block: *const slc::RegisterBlock,
15+
}
16+
17+
unsafe impl Sync for SlcInfo {}
18+
19+
impl PeripheralInstance for AnySlc<'_> {
20+
type Info = SlcInfo;
21+
22+
fn info(&self) -> &'static Self::Info {
23+
static INFO: SlcInfo = SlcInfo {
24+
register_block: crate::peripherals::SLC::ptr(),
25+
};
26+
27+
&INFO
28+
}
29+
}
30+
31+
/// A peripheral singleton compatible with the SDIO SLC driver.
32+
pub trait SlcInstance: PeripheralInstance + IntoAnySlc {}
33+
34+
impl<'d> SlcInstance for AnySlc<'d> {}

esp-hal/src/sdio/slchost.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
use super::PeripheralInstance;
2+
use crate::pac::slchost;
3+
4+
crate::any_peripheral! {
5+
/// Any SDIO peripheral.
6+
pub peripheral AnySlchost<'d> {
7+
Slchost(crate::peripherals::SLCHOST<'d>)
8+
}
9+
}
10+
11+
/// Represents the SLCHOST registers for SDIO peripherals.
12+
pub struct SlchostInfo {
13+
/// Represents the SLCHOST register block.
14+
pub register_block: *const slchost::RegisterBlock,
15+
}
16+
17+
unsafe impl Sync for SlchostInfo {}
18+
19+
impl PeripheralInstance for AnySlchost<'_> {
20+
type Info = SlchostInfo;
21+
22+
fn info(&self) -> &'static Self::Info {
23+
static INFO: SlchostInfo = SlchostInfo {
24+
register_block: crate::peripherals::SLCHOST::ptr(),
25+
};
26+
27+
&INFO
28+
}
29+
}
30+
31+
/// A peripheral singleton compatible with the SDIO SLCHOST driver.
32+
pub trait SlchostInstance: PeripheralInstance + IntoAnySlchost {}
33+
34+
impl<'d> SlchostInstance for AnySlchost<'d> {}

esp-hal/src/soc/esp32c6/peripherals.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ crate::peripherals! {
7979
RNG <= RNG,
8080
RSA <= RSA,
8181
SHA <= SHA,
82+
SLC <= SLC,
8283
SLCHOST <= SLCHOST,
8384
SOC_ETM <= SOC_ETM,
8485
SPI0 <= SPI0,

esp-lp-hal/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ test = false
2222
[dependencies]
2323
cfg-if = "1.0.0"
2424
document-features = "0.2.10"
25-
embedded-hal = { version = "1.0.0", optional = true }
26-
embedded-hal-nb = { version = "1.0.0", optional = true }
25+
embedded-hal = { version = "1.0.0", git = "https://github.com/rmsyn/embedded-hal", branch = "embedded-hal/mmc", optional = true }
26+
embedded-hal-nb = { version = "1.0.0", git = "https://github.com/rmsyn/embedded-hal", branch = "embedded-hal/mmc", optional = true }
2727
embedded-io = { version = "0.6.1", optional = true }
2828
esp32c6-lp = { version = "0.3.0", features = ["critical-section"], optional = true }
2929
esp32s2-ulp = { version = "0.3.0", features = ["critical-section"], optional = true }

examples/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ embassy-net = { version = "0.6.0", features = [ "tcp", "udp", "dhcpv4", "medium-
1717
embassy-sync = "0.6.2"
1818
embassy-time = "0.4.0"
1919
embassy-usb = { version = "0.4.0", default-features = false }
20-
embedded-hal-async = "1.0.0"
20+
embedded-hal-async = { version = "1.0.0", git = "https://github.com/rmsyn/embedded-hal", branch = "embedded-hal/mmc" }
2121
embedded-io = { version = "0.6.1", default-features = false }
2222
embedded-io-async = "0.6.1"
2323
embedded-storage = "0.3.1"

hil-test/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -230,12 +230,12 @@ embassy-futures = "0.1.1"
230230
embedded-storage = "0.3.1"
231231
embassy-sync = "0.6.0"
232232
embassy-time = "0.4.0"
233-
embedded-hal = "1.0.0"
233+
embedded-hal = { version = "1.0.0", git = "https://github.com/rmsyn/embedded-hal", branch = "embedded-hal/mmc" }
234234
embedded-io = "0.6.1"
235235
embedded-io-async = "0.6.1"
236236
embedded-can = "0.4.1"
237-
embedded-hal-async = "1.0.0"
238-
embedded-hal-nb = "1.0.0"
237+
embedded-hal-async = { version = "1.0.0", git = "https://github.com/rmsyn/embedded-hal", branch = "embedded-hal/mmc" }
238+
embedded-hal-nb = { version = "1.0.0", git = "https://github.com/rmsyn/embedded-hal", branch = "embedded-hal/mmc" }
239239
esp-alloc = { path = "../esp-alloc", optional = true }
240240
esp-backtrace = { path = "../esp-backtrace", default-features = false, features = ["exception-handler", "defmt", "semihosting"] }
241241
esp-bootloader-esp-idf = { path = "../esp-bootloader-esp-idf" }

0 commit comments

Comments
 (0)