Skip to content

Commit 9bf0162

Browse files
committed
Use named structs instead of tuples
1 parent bf5eca5 commit 9bf0162

File tree

3 files changed

+102
-55
lines changed

3 files changed

+102
-55
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ hex-literal = "0.4.1"
3232
sha2 = "0.10"
3333

3434
[features]
35-
default = ["log"]
35+
default = ["log", "embassy-sync-06", "embedded-hal-bus-03"]
3636
defmt-log = ["dep:defmt"]
3737
embassy-sync-06 = ["dep:embassy-sync-06"]
3838
embedded-hal-bus-03 = ["dep:embedded-hal-bus-03"]

examples/readme_test.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
use core::cell::RefCell;
99

10-
use embedded_sdmmc::{Error, SdCardError, TimeSource, Timestamp};
10+
use embedded_sdmmc::{sdcard::RefCellSdCardDevice, Error, SdCardError, TimeSource, Timestamp};
1111

1212
pub struct DummyCsPin;
1313

@@ -122,7 +122,8 @@ fn main() -> Result<(), MyError> {
122122

123123
use embedded_sdmmc::{Mode, SdCard, VolumeIdx, VolumeManager};
124124
// Build an SD Card interface out of an SPI device, a chip-select pin and the delay object
125-
let sdcard = SdCard::new((&spi_bus, DummyCsPin), delay);
125+
let spi_device = RefCellSdCardDevice::new(&spi_bus, DummyCsPin);
126+
let sdcard = SdCard::new(spi_device, delay);
126127
// Get the card size (this also triggers card initialisation because it's not been done yet)
127128
println!("Card size is {} bytes", sdcard.num_bytes()?);
128129
// Now let's look for volumes (also known as partitions) on our block device.

src/sdcard/sd_card_device.rs

Lines changed: 98 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,22 @@ pub enum SdCardDeviceError {
7474
Cs,
7575
}
7676

77-
impl<BUS, CS> SdCardDevice for (&RefCell<BUS>, CS)
77+
/// A wrapper around a SPI bus and a CS pin, using a `RefCell`.
78+
///
79+
/// This allows sharing the bus within the same thread.
80+
pub struct RefCellSdCardDevice<'a, BUS, CS> {
81+
bus: &'a RefCell<BUS>,
82+
cs: CS,
83+
}
84+
85+
impl<'a, BUS, CS> RefCellSdCardDevice<'a, BUS, CS> {
86+
/// Create a new `RefCellSdCardDevice`.
87+
pub fn new(bus: &'a RefCell<BUS>, cs: CS) -> Self {
88+
Self { bus, cs }
89+
}
90+
}
91+
92+
impl<BUS, CS> SdCardDevice for RefCellSdCardDevice<'_, BUS, CS>
7893
where
7994
BUS: SpiBus,
8095
CS: OutputPin,
@@ -83,75 +98,106 @@ where
8398
&mut self,
8499
operations: &mut [Operation<'_, u8>],
85100
) -> Result<(), SdCardDeviceError> {
86-
let (bus, cs) = self;
87-
let mut bus = bus.borrow_mut();
88-
bus_transaction(&mut *bus, cs, operations)
101+
let mut bus = self.bus.borrow_mut();
102+
bus_transaction(&mut *bus, &mut self.cs, operations)
89103
}
90104

91105
fn send_clock_pulses(&mut self) -> Result<(), SdCardDeviceError> {
92-
let (bus, cs) = self;
93-
let mut bus = bus.borrow_mut();
94-
send_clock_pulses(&mut *bus, cs)
106+
let mut bus = self.bus.borrow_mut();
107+
send_clock_pulses(&mut *bus, &mut self.cs)
95108
}
96109
}
97110

98111
#[cfg(feature = "embassy-sync-06")]
99-
impl<CS, BUS, M> SdCardDevice for (&embassy_sync_06::blocking_mutex::Mutex<M, RefCell<BUS>>, CS)
100-
where
101-
CS: OutputPin,
102-
BUS: SpiBus,
103-
M: embassy_sync_06::blocking_mutex::raw::RawMutex,
104-
{
105-
fn transaction(
106-
&mut self,
107-
operations: &mut [Operation<'_, u8>],
108-
) -> Result<(), SdCardDeviceError> {
109-
let (bus, cs) = self;
110-
bus.lock(|bus| {
111-
let mut bus = bus.borrow_mut();
112-
bus_transaction(&mut *bus, cs, operations)
113-
})
112+
mod embassy_sync_06 {
113+
use core::cell::RefCell;
114+
115+
use ::embassy_sync_06::blocking_mutex;
116+
117+
use super::*;
118+
119+
/// A wrapper around a SPI bus and a CS pin, using an `embassy-sync` blocking mutex.
120+
///
121+
/// This allows sharing the bus with according to the `embassy-sync` mutex model.
122+
/// See [`blocking_mutex::Mutex`] for more details.
123+
124+
pub struct EmbassyMutexSdCardDevice<'a, BUS, CS, M> {
125+
bus: &'a blocking_mutex::Mutex<M, RefCell<BUS>>,
126+
cs: CS,
114127
}
115128

116-
fn send_clock_pulses(&mut self) -> Result<(), SdCardDeviceError> {
117-
let (bus, cs) = self;
118-
bus.lock(|bus| {
119-
let mut bus = bus.borrow_mut();
120-
send_clock_pulses(&mut *bus, cs)
121-
})
129+
impl<'a, BUS, CS, M> EmbassyMutexSdCardDevice<'a, BUS, CS, M> {
130+
/// Create a new `EmbassyMutexSdCardDevice`.
131+
pub fn new(bus: &'a blocking_mutex::Mutex<M, RefCell<BUS>>, cs: CS) -> Self {
132+
Self { bus, cs }
133+
}
134+
}
135+
136+
impl<CS, BUS, M> SdCardDevice for EmbassyMutexSdCardDevice<'_, BUS, CS, M>
137+
where
138+
CS: OutputPin,
139+
BUS: SpiBus,
140+
M: blocking_mutex::raw::RawMutex,
141+
{
142+
fn transaction(
143+
&mut self,
144+
operations: &mut [Operation<'_, u8>],
145+
) -> Result<(), SdCardDeviceError> {
146+
self.bus.lock(|bus| {
147+
let mut bus = bus.borrow_mut();
148+
bus_transaction(&mut *bus, &mut self.cs, operations)
149+
})
150+
}
151+
152+
fn send_clock_pulses(&mut self) -> Result<(), SdCardDeviceError> {
153+
self.bus.lock(|bus| {
154+
let mut bus = bus.borrow_mut();
155+
send_clock_pulses(&mut *bus, &mut self.cs)
156+
})
157+
}
122158
}
123159
}
124160

125-
// `ExclusiveDevice` represents exclusive access to the bus so there's no need to send the dummy
126-
// byte after deasserting the CS pin. We can delegate the implementation to the `embedded_hal` trait.
161+
#[cfg(feature = "embassy-sync-06")]
162+
pub use embassy_sync_06::*;
163+
127164
#[cfg(feature = "embedded-hal-bus-03")]
128-
impl<CS, BUS, D> SdCardDevice for embedded_hal_bus_03::spi::ExclusiveDevice<BUS, CS, D>
129-
where
130-
BUS: SpiBus,
131-
CS: OutputPin,
132-
D: embedded_hal::delay::DelayNs,
133-
{
134-
fn transaction(
135-
&mut self,
136-
operations: &mut [Operation<'_, u8>],
137-
) -> Result<(), SdCardDeviceError> {
138-
<Self as embedded_hal::spi::SpiDevice>::transaction(self, operations)
139-
.map_err(|_| SdCardDeviceError::Spi)
140-
}
165+
mod embedded_hal_bus_03 {
166+
use ::embedded_hal_bus_03::spi::ExclusiveDevice;
167+
use embedded_hal::spi::SpiDevice;
141168

142-
fn send_clock_pulses(&mut self) -> Result<(), SdCardDeviceError> {
143-
let bus = self.bus_mut();
169+
use super::*;
144170

145-
// There's no way to access the CS pin here so we can't set it high. Most likely it is already high so this is probably fine(?)
171+
// `ExclusiveDevice` represents exclusive access to the bus so there's no need to send the dummy
172+
// byte after deasserting the CS pin. We can delegate the implementation to the `embedded_hal` trait.
146173

147-
let send_res = bus.write(&[0xFF; 10]);
174+
impl<CS, BUS, D> SdCardDevice for ExclusiveDevice<BUS, CS, D>
175+
where
176+
BUS: SpiBus,
177+
CS: OutputPin,
178+
D: embedded_hal::delay::DelayNs,
179+
{
180+
fn transaction(
181+
&mut self,
182+
operations: &mut [Operation<'_, u8>],
183+
) -> Result<(), SdCardDeviceError> {
184+
<Self as SpiDevice>::transaction(self, operations).map_err(|_| SdCardDeviceError::Spi)
185+
}
186+
187+
fn send_clock_pulses(&mut self) -> Result<(), SdCardDeviceError> {
188+
let bus = self.bus_mut();
189+
190+
// There's no way to access the CS pin here so we can't set it high. Most likely it is already high so this is probably fine(?)
148191

149-
// On failure, it's important to still flush.
150-
let flush_res = bus.flush().map_err(|_| SdCardDeviceError::Spi);
192+
let send_res = bus.write(&[0xFF; 10]);
151193

152-
send_res.map_err(|_| SdCardDeviceError::Spi)?;
153-
flush_res.map_err(|_| SdCardDeviceError::Spi)?;
154-
Ok(())
194+
// On failure, it's important to still flush.
195+
let flush_res = bus.flush().map_err(|_| SdCardDeviceError::Spi);
196+
197+
send_res.map_err(|_| SdCardDeviceError::Spi)?;
198+
flush_res.map_err(|_| SdCardDeviceError::Spi)?;
199+
Ok(())
200+
}
155201
}
156202
}
157203

0 commit comments

Comments
 (0)