aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs718
-rw-r--r--embassy-stm32/src/time.rs2
2 files changed, 403 insertions, 317 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 74a6f13fa..f862d73b1 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -9,7 +9,6 @@ use core::task::Poll;
9 9
10use embassy_hal_internal::drop::OnDrop; 10use embassy_hal_internal::drop::OnDrop;
11use embassy_hal_internal::{Peri, PeripheralType}; 11use embassy_hal_internal::{Peri, PeripheralType};
12use embassy_sync::mutex::Mutex;
13use embassy_sync::waitqueue::AtomicWaker; 12use embassy_sync::waitqueue::AtomicWaker;
14use sdio_host::common_cmd::{self, Resp, ResponseLen}; 13use sdio_host::common_cmd::{self, Resp, ResponseLen};
15use sdio_host::emmc::{EMMC, ExtCSD}; 14use sdio_host::emmc::{EMMC, ExtCSD};
@@ -165,6 +164,55 @@ pub enum Error {
165 StBitErr, 164 StBitErr,
166} 165}
167 166
167pub trait Addressable: Sized {
168 type Ext;
169
170 /// Get this peripheral's address on the SDMMC bus
171 fn get_address(&self) -> u16;
172
173 /// Is this a standard or high capacity peripheral?
174 fn get_capacity(&self) -> CardCapacity;
175
176 /// Size in bytes
177 fn size(&self) -> u64;
178
179 async fn write_block<'a>(
180 &mut self,
181 sdmmc: &mut Sdmmc<'a>,
182 block_idx: u32,
183 buffer: &DataBlock,
184 ) -> Result<(), Error> {
185 sdmmc.write_block(self, block_idx, buffer).await
186 }
187
188 async fn write_blocks<'a>(
189 &mut self,
190 sdmmc: &mut Sdmmc<'a>,
191 block_idx: u32,
192 blocks: &[DataBlock],
193 ) -> Result<(), Error> {
194 sdmmc.write_blocks(self, block_idx, blocks).await
195 }
196
197 async fn read_block<'a>(
198 &mut self,
199 sdmmc: &mut Sdmmc<'a>,
200 block_idx: u32,
201 buffer: &mut DataBlock,
202 ) -> Result<(), Error> {
203 sdmmc.read_block(self, block_idx, buffer).await
204 }
205
206 async fn read_blocks<'a>(
207 &mut self,
208 sdmmc: &mut Sdmmc<'a>,
209 block_idx: u32,
210 blocks: &mut [DataBlock],
211 ) -> Result<(), Error> {
212 sdmmc.read_blocks(self, block_idx, blocks).await
213 }
214}
215
168#[derive(Clone, Copy, Debug, Default)] 216#[derive(Clone, Copy, Debug, Default)]
169/// SD Card 217/// SD Card
170pub struct Card { 218pub struct Card {
@@ -184,6 +232,178 @@ pub struct Card {
184 pub status: SDStatus, 232 pub status: SDStatus,
185} 233}
186 234
235impl Card {
236 /// Switch mode using CMD6.
237 ///
238 /// Attempt to set a new signalling mode. The selected
239 /// signalling mode is returned. Expects the current clock
240 /// frequency to be > 12.5MHz.
241 ///
242 /// SD only.
243 pub async fn switch_signalling_mode<'a>(
244 &mut self,
245 sdmmc: &mut Sdmmc<'a>,
246 cmd_block: &mut CmdBlock,
247 signalling: Signalling,
248 ) -> Result<Signalling, Error> {
249 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
250 // necessary"
251
252 let set_function = 0x8000_0000
253 | match signalling {
254 // See PLSS v7_10 Table 4-11
255 Signalling::DDR50 => 0xFF_FF04,
256 Signalling::SDR104 => 0xFF_1F03,
257 Signalling::SDR50 => 0xFF_1F02,
258 Signalling::SDR25 => 0xFF_FF01,
259 Signalling::SDR12 => 0xFF_FF00,
260 };
261
262 // Arm `OnDrop` after the buffer, so it will be dropped first
263 let on_drop = OnDrop::new(|| sdmmc.on_drop());
264
265 let transfer = sdmmc.prepare_datapath_read(
266 &sdmmc.config,
267 #[cfg(sdmmc_v1)]
268 &mut self.dma,
269 cmd_block.as_mut(),
270 64,
271 6,
272 );
273 sdmmc.enable_interrupts();
274 sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
275
276 let res = sdmmc.complete_datapath_transfer(true).await;
277
278 // Host is allowed to use the new functions at least 8
279 // clocks after the end of the switch command
280 // transaction. We know the current clock period is < 80ns,
281 // so a total delay of 640ns is required here
282 for _ in 0..300 {
283 cortex_m::asm::nop();
284 }
285
286 match res {
287 Ok(_) => {
288 on_drop.defuse();
289 sdmmc.stop_datapath();
290 drop(transfer);
291
292 // Function Selection of Function Group 1
293 let selection = (u32::from_be(cmd_block[4]) >> 24) & 0xF;
294
295 match selection {
296 0 => Ok(Signalling::SDR12),
297 1 => Ok(Signalling::SDR25),
298 2 => Ok(Signalling::SDR50),
299 3 => Ok(Signalling::SDR104),
300 4 => Ok(Signalling::DDR50),
301 _ => Err(Error::UnsupportedCardType),
302 }
303 }
304 Err(e) => Err(e),
305 }
306 }
307
308 /// Reads the SCR register.
309 ///
310 /// SD only.
311 pub async fn get_scr<'a>(&mut self, sdmmc: &mut Sdmmc<'a>, cmd_block: &mut CmdBlock) -> Result<(), Error> {
312 // Read the 64-bit SCR register
313 sdmmc.cmd(common_cmd::set_block_length(8), false)?; // CMD16
314 sdmmc.cmd(common_cmd::app_cmd(self.rca), false)?;
315
316 let scr = &mut cmd_block.0[..2];
317
318 // Arm `OnDrop` after the buffer, so it will be dropped first
319 let on_drop = OnDrop::new(|| sdmmc.on_drop());
320
321 let transfer = sdmmc.prepare_datapath_read(
322 &sdmmc.config,
323 #[cfg(sdmmc_v1)]
324 &mut self.dma,
325 scr,
326 8,
327 3,
328 );
329 sdmmc.enable_interrupts();
330 sdmmc.cmd(sd_cmd::send_scr(), true)?;
331
332 let res = sdmmc.complete_datapath_transfer(true).await;
333
334 if res.is_ok() {
335 on_drop.defuse();
336 sdmmc.stop_datapath();
337 drop(transfer);
338
339 unsafe {
340 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
341 self.scr = SCR(u64::from_be_bytes(*scr_bytes));
342 }
343 }
344 res
345 }
346
347 /// Reads the SD Status (ACMD13)
348 ///
349 /// SD only.
350 pub async fn read_sd_status<'a>(&mut self, sdmmc: &mut Sdmmc<'a>, cmd_block: &mut CmdBlock) -> Result<(), Error> {
351 let rca = self.rca;
352
353 sdmmc.cmd(common_cmd::set_block_length(64), false)?; // CMD16
354 sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP
355
356 let status = cmd_block;
357
358 // Arm `OnDrop` after the buffer, so it will be dropped first
359 let on_drop = OnDrop::new(|| sdmmc.on_drop());
360
361 let transfer = sdmmc.prepare_datapath_read(
362 &sdmmc.config,
363 #[cfg(sdmmc_v1)]
364 &mut self.dma,
365 status.as_mut(),
366 64,
367 6,
368 );
369 sdmmc.enable_interrupts();
370 sdmmc.cmd(sd_cmd::sd_status(), true)?;
371
372 let res = sdmmc.complete_datapath_transfer(true).await;
373
374 if res.is_ok() {
375 on_drop.defuse();
376 sdmmc.stop_datapath();
377 drop(transfer);
378
379 for byte in status.iter_mut() {
380 *byte = u32::from_be(*byte);
381 }
382 self.status = status.0.into();
383 }
384 res
385 }
386}
387
388impl Addressable for Card {
389 type Ext = SD;
390
391 /// Get this peripheral's address on the SDMMC bus
392 fn get_address(&self) -> u16 {
393 self.rca
394 }
395
396 /// Is this a standard or high capacity peripheral?
397 fn get_capacity(&self) -> CardCapacity {
398 self.card_type
399 }
400
401 /// Size in bytes
402 fn size(&self) -> u64 {
403 u64::from(self.csd.block_count()) * 512
404 }
405}
406
187#[derive(Clone, Copy, Debug, Default)] 407#[derive(Clone, Copy, Debug, Default)]
188/// eMMC storage 408/// eMMC storage
189pub struct Emmc { 409pub struct Emmc {
@@ -201,6 +421,66 @@ pub struct Emmc {
201 pub ext_csd: ExtCSD, 421 pub ext_csd: ExtCSD,
202} 422}
203 423
424impl Emmc {
425 /// Gets the EXT_CSD register.
426 ///
427 /// eMMC only.
428 async fn read_ext_csd<'a>(&mut self, sdmmc: &mut Sdmmc<'a>) -> Result<(), Error> {
429 // Note: cmd_block can't be used because ExtCSD is too long to fit.
430 let mut data_block = DataBlock([0u8; 512]);
431
432 // NOTE(unsafe) DataBlock uses align 4
433 let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) };
434
435 sdmmc.cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16
436
437 let transfer = sdmmc.prepare_datapath_read(
438 &sdmmc.config,
439 #[cfg(sdmmc_v1)]
440 &mut self.dma,
441 buffer,
442 512,
443 9,
444 );
445 sdmmc.enable_interrupts();
446 sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?;
447
448 // Arm `OnDrop` after the buffer, so it will be dropped first
449 let on_drop = OnDrop::new(|| sdmmc.on_drop());
450
451 let res = sdmmc.complete_datapath_transfer(true).await;
452
453 if res.is_ok() {
454 on_drop.defuse();
455 sdmmc.stop_datapath();
456 drop(transfer);
457
458 self.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into();
459 }
460
461 res
462 }
463}
464
465impl Addressable for Emmc {
466 type Ext = EMMC;
467
468 /// Get this peripheral's address on the SDMMC bus
469 fn get_address(&self) -> u16 {
470 self.rca
471 }
472
473 /// Is this a standard or high capacity peripheral?
474 fn get_capacity(&self) -> CardCapacity {
475 self.capacity
476 }
477
478 /// Size in bytes
479 fn size(&self) -> u64 {
480 u64::from(self.ext_csd.sector_count()) * 512
481 }
482}
483
204#[repr(u8)] 484#[repr(u8)]
205enum PowerCtrl { 485enum PowerCtrl {
206 Off = 0b00, 486 Off = 0b00,
@@ -386,12 +666,6 @@ pub struct Sdmmc<'d> {
386 clock: Hertz, 666 clock: Hertz,
387 /// Current signalling scheme to card 667 /// Current signalling scheme to card
388 signalling: Signalling, 668 signalling: Signalling,
389 /// Card
390 card: Option<SdmmcPeripheral>,
391
392 /// An optional buffer to be used for commands
393 /// This should be used if there are special memory location requirements for dma
394 cmd_block: Option<&'d mut CmdBlock>,
395} 669}
396 670
397const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh); 671const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh);
@@ -725,8 +999,6 @@ impl<'d> Sdmmc<'d> {
725 config, 999 config,
726 clock: SD_INIT_FREQ, 1000 clock: SD_INIT_FREQ,
727 signalling: Default::default(), 1001 signalling: Default::default(),
728 card: None,
729 cmd_block: None,
730 } 1002 }
731 } 1003 }
732 1004
@@ -889,9 +1161,9 @@ impl<'d> Sdmmc<'d> {
889 } 1161 }
890 1162
891 /// Query the card status (CMD13, returns R1) 1163 /// Query the card status (CMD13, returns R1)
892 fn read_status<Ext>(&self, card: &SdmmcPeripheral) -> Result<CardStatus<Ext>, Error> 1164 fn read_status<A: Addressable>(&self, card: &A) -> Result<CardStatus<A::Ext>, Error>
893 where 1165 where
894 CardStatus<Ext>: From<u32>, 1166 CardStatus<A::Ext>: From<u32>,
895 { 1167 {
896 let regs = self.info.regs; 1168 let regs = self.info.regs;
897 let rca = card.get_address(); 1169 let rca = card.get_address();
@@ -1080,9 +1352,14 @@ impl<'d> Sdmmc<'d> {
1080 1352
1081 /// Read a data block. 1353 /// Read a data block.
1082 #[inline] 1354 #[inline]
1083 pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> { 1355 pub async fn read_block(
1356 &mut self,
1357 card: &mut impl Addressable,
1358 block_idx: u32,
1359 buffer: &mut DataBlock,
1360 ) -> Result<(), Error> {
1084 let _scoped_block_stop = self.info.rcc.block_stop(); 1361 let _scoped_block_stop = self.info.rcc.block_stop();
1085 let card_capacity = self.card()?.get_capacity(); 1362 let card_capacity = card.get_capacity();
1086 1363
1087 // NOTE(unsafe) DataBlock uses align 4 1364 // NOTE(unsafe) DataBlock uses align 4
1088 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) }; 1365 let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) };
@@ -1120,9 +1397,14 @@ impl<'d> Sdmmc<'d> {
1120 1397
1121 /// Read multiple data blocks. 1398 /// Read multiple data blocks.
1122 #[inline] 1399 #[inline]
1123 pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> { 1400 pub async fn read_blocks(
1401 &mut self,
1402 card: &mut impl Addressable,
1403 block_idx: u32,
1404 blocks: &mut [DataBlock],
1405 ) -> Result<(), Error> {
1124 let _scoped_block_stop = self.info.rcc.block_stop(); 1406 let _scoped_block_stop = self.info.rcc.block_stop();
1125 let card_capacity = self.card()?.get_capacity(); 1407 let card_capacity = card.get_capacity();
1126 1408
1127 // NOTE(unsafe) reinterpret buffer as &mut [u32] 1409 // NOTE(unsafe) reinterpret buffer as &mut [u32]
1128 let buffer = unsafe { 1410 let buffer = unsafe {
@@ -1167,9 +1449,16 @@ impl<'d> Sdmmc<'d> {
1167 } 1449 }
1168 1450
1169 /// Write a data block. 1451 /// Write a data block.
1170 pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { 1452 pub async fn write_block<A: Addressable>(
1453 &mut self,
1454 card: &mut A,
1455 block_idx: u32,
1456 buffer: &DataBlock,
1457 ) -> Result<(), Error>
1458 where
1459 CardStatus<A::Ext>: From<u32>,
1460 {
1171 let _scoped_block_stop = self.info.rcc.block_stop(); 1461 let _scoped_block_stop = self.info.rcc.block_stop();
1172 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1173 1462
1174 // NOTE(unsafe) DataBlock uses align 4 1463 // NOTE(unsafe) DataBlock uses align 4
1175 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) }; 1464 let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) };
@@ -1205,13 +1494,8 @@ impl<'d> Sdmmc<'d> {
1205 // TODO: Make this configurable 1494 // TODO: Make this configurable
1206 let mut timeout: u32 = 0x00FF_FFFF; 1495 let mut timeout: u32 = 0x00FF_FFFF;
1207 1496
1208 let card = self.card.as_ref().unwrap();
1209 while timeout > 0 { 1497 while timeout > 0 {
1210 let ready_for_data = match card { 1498 let ready_for_data = self.read_status(card)?.ready_for_data();
1211 SdmmcPeripheral::Emmc(_) => self.read_status::<EMMC>(card)?.ready_for_data(),
1212 SdmmcPeripheral::SdCard(_) => self.read_status::<SD>(card)?.ready_for_data(),
1213 };
1214
1215 if ready_for_data { 1499 if ready_for_data {
1216 return Ok(()); 1500 return Ok(());
1217 } 1501 }
@@ -1224,9 +1508,16 @@ impl<'d> Sdmmc<'d> {
1224 } 1508 }
1225 1509
1226 /// Write multiple data blocks. 1510 /// Write multiple data blocks.
1227 pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error> { 1511 pub async fn write_blocks<A: Addressable>(
1512 &mut self,
1513 card: &mut A,
1514 block_idx: u32,
1515 blocks: &[DataBlock],
1516 ) -> Result<(), Error>
1517 where
1518 CardStatus<A::Ext>: From<u32>,
1519 {
1228 let _scoped_block_stop = self.info.rcc.block_stop(); 1520 let _scoped_block_stop = self.info.rcc.block_stop();
1229 let card = self.card.as_mut().ok_or(Error::NoCard)?;
1230 1521
1231 // NOTE(unsafe) reinterpret buffer as &[u32] 1522 // NOTE(unsafe) reinterpret buffer as &[u32]
1232 let buffer = unsafe { 1523 let buffer = unsafe {
@@ -1272,12 +1563,11 @@ impl<'d> Sdmmc<'d> {
1272 // TODO: Make this configurable 1563 // TODO: Make this configurable
1273 let mut timeout: u32 = 0x00FF_FFFF; 1564 let mut timeout: u32 = 0x00FF_FFFF;
1274 1565
1275 // Try to read card status (ACMD13)
1276 while timeout > 0 { 1566 while timeout > 0 {
1277 match self.read_sd_status().await { 1567 let ready_for_data = self.read_status(card)?.ready_for_data();
1278 Ok(_) => return Ok(()), 1568
1279 Err(Error::Timeout) => (), // Try again 1569 if ready_for_data {
1280 Err(e) => return Err(e), 1570 return Ok(());
1281 } 1571 }
1282 timeout -= 1; 1572 timeout -= 1;
1283 } 1573 }
@@ -1287,31 +1577,17 @@ impl<'d> Sdmmc<'d> {
1287 } 1577 }
1288 } 1578 }
1289 1579
1290 /// Get a reference to the initialized card
1291 ///
1292 /// # Errors
1293 ///
1294 /// Returns Error::NoCard if [`init_sd_card`](#method.init_sd_card) or
1295 /// [`init_emmc`](#method.init_emmc) has not previously succeeded
1296 #[inline]
1297 pub fn card(&self) -> Result<&SdmmcPeripheral, Error> {
1298 self.card.as_ref().ok_or(Error::NoCard)
1299 }
1300
1301 /// Get the current SDMMC bus clock 1580 /// Get the current SDMMC bus clock
1302 pub fn clock(&self) -> Hertz { 1581 pub fn clock(&self) -> Hertz {
1303 self.clock 1582 self.clock
1304 } 1583 }
1305 1584
1306 /// Set a specific cmd buffer rather than using the default stack allocated one. 1585 async fn init_internal(
1307 /// This is required if stack RAM cannot be used with DMA and usually manifests 1586 &mut self,
1308 /// itself as an indefinite wait on a dma transfer because the dma peripheral 1587 cmd_block: &mut CmdBlock,
1309 /// cannot access the memory. 1588 freq: Hertz,
1310 pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) { 1589 card: &mut SdmmcPeripheral,
1311 self.cmd_block = Some(cmd_block) 1590 ) -> Result<(), Error> {
1312 }
1313
1314 async fn init_internal(&mut self, freq: Hertz, mut card: SdmmcPeripheral) -> Result<(), Error> {
1315 let regs = self.info.regs; 1591 let regs = self.info.regs;
1316 1592
1317 let bus_width = match (self.d3.is_some(), self.d7.is_some()) { 1593 let bus_width = match (self.d3.is_some(), self.d7.is_some()) {
@@ -1346,7 +1622,7 @@ impl<'d> Sdmmc<'d> {
1346 self.cmd(common_cmd::idle(), false)?; 1622 self.cmd(common_cmd::idle(), false)?;
1347 1623
1348 match card { 1624 match card {
1349 SdmmcPeripheral::SdCard(ref mut card) => { 1625 SdmmcPeripheral::SdCard(card) => {
1350 // Check if cards supports CMD8 (with pattern) 1626 // Check if cards supports CMD8 (with pattern)
1351 self.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?; 1627 self.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?;
1352 let cic = CIC::from(regs.respr(0).read().cardstatus()); 1628 let cic = CIC::from(regs.respr(0).read().cardstatus());
@@ -1387,7 +1663,7 @@ impl<'d> Sdmmc<'d> {
1387 } 1663 }
1388 card.ocr = ocr; 1664 card.ocr = ocr;
1389 } 1665 }
1390 SdmmcPeripheral::Emmc(ref mut emmc) => { 1666 SdmmcPeripheral::Emmc(emmc) => {
1391 let ocr = loop { 1667 let ocr = loop {
1392 let high_voltage = 0b0 << 7; 1668 let high_voltage = 0b0 << 7;
1393 let access_mode = 0b10 << 29; 1669 let access_mode = 0b10 << 29;
@@ -1423,14 +1699,14 @@ impl<'d> Sdmmc<'d> {
1423 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); 1699 let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3);
1424 1700
1425 match card { 1701 match card {
1426 SdmmcPeripheral::SdCard(ref mut card) => { 1702 SdmmcPeripheral::SdCard(card) => {
1427 card.cid = cid.into(); 1703 card.cid = cid.into();
1428 1704
1429 self.cmd(sd_cmd::send_relative_address(), false)?; 1705 self.cmd(sd_cmd::send_relative_address(), false)?;
1430 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus()); 1706 let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus());
1431 card.rca = rca.address(); 1707 card.rca = rca.address();
1432 } 1708 }
1433 SdmmcPeripheral::Emmc(ref mut emmc) => { 1709 SdmmcPeripheral::Emmc(emmc) => {
1434 emmc.cid = cid.into(); 1710 emmc.cid = cid.into();
1435 1711
1436 emmc.rca = 1u16.into(); 1712 emmc.rca = 1u16.into();
@@ -1448,10 +1724,10 @@ impl<'d> Sdmmc<'d> {
1448 self.select_card(Some(card.get_address()))?; 1724 self.select_card(Some(card.get_address()))?;
1449 1725
1450 let bus_width = match card { 1726 let bus_width = match card {
1451 SdmmcPeripheral::SdCard(ref mut card) => { 1727 SdmmcPeripheral::SdCard(card) => {
1452 card.csd = csd.into(); 1728 card.csd = csd.into();
1453 1729
1454 self.get_scr(card).await?; 1730 card.get_scr(self, cmd_block).await?;
1455 1731
1456 if !card.scr.bus_width_four() { 1732 if !card.scr.bus_width_four() {
1457 BusWidth::One 1733 BusWidth::One
@@ -1459,7 +1735,7 @@ impl<'d> Sdmmc<'d> {
1459 BusWidth::Four 1735 BusWidth::Four
1460 } 1736 }
1461 } 1737 }
1462 SdmmcPeripheral::Emmc(ref mut emmc) => { 1738 SdmmcPeripheral::Emmc(emmc) => {
1463 emmc.csd = csd.into(); 1739 emmc.csd = csd.into();
1464 1740
1465 bus_width 1741 bus_width
@@ -1475,7 +1751,7 @@ impl<'d> Sdmmc<'d> {
1475 }; 1751 };
1476 1752
1477 match card { 1753 match card {
1478 SdmmcPeripheral::SdCard(ref mut card) => { 1754 SdmmcPeripheral::SdCard(card) => {
1479 let acmd_arg = match bus_width { 1755 let acmd_arg = match bus_width {
1480 BusWidth::Four if card.scr.bus_width_four() => 2, 1756 BusWidth::Four if card.scr.bus_width_four() => 2,
1481 _ => 0, 1757 _ => 0,
@@ -1483,7 +1759,7 @@ impl<'d> Sdmmc<'d> {
1483 self.cmd(common_cmd::app_cmd(card.rca), false)?; 1759 self.cmd(common_cmd::app_cmd(card.rca), false)?;
1484 self.cmd(sd_cmd::cmd6(acmd_arg), false)?; 1760 self.cmd(sd_cmd::cmd6(acmd_arg), false)?;
1485 } 1761 }
1486 SdmmcPeripheral::Emmc(_) => { 1762 SdmmcPeripheral::Emmc(emmc) => {
1487 // Write bus width to ExtCSD byte 183 1763 // Write bus width to ExtCSD byte 183
1488 self.cmd( 1764 self.cmd(
1489 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus), 1765 emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus),
@@ -1492,7 +1768,7 @@ impl<'d> Sdmmc<'d> {
1492 1768
1493 // Wait for ready after R1b response 1769 // Wait for ready after R1b response
1494 loop { 1770 loop {
1495 let status = self.read_status::<EMMC>(&card)?; 1771 let status = self.read_status(emmc)?;
1496 1772
1497 if status.ready_for_data() { 1773 if status.ready_for_data() {
1498 break; 1774 break;
@@ -1515,32 +1791,30 @@ impl<'d> Sdmmc<'d> {
1515 self.clkcr_set_clkdiv(25_000_000, bus_width)?; 1791 self.clkcr_set_clkdiv(25_000_000, bus_width)?;
1516 } 1792 }
1517 1793
1518 self.card = Some(card);
1519
1520 match card { 1794 match card {
1521 SdmmcPeripheral::SdCard(_) => { 1795 SdmmcPeripheral::SdCard(card) => {
1522 // Read status 1796 // Read status
1523 self.read_sd_status().await?; 1797 card.read_sd_status(self, cmd_block).await?;
1524 1798
1525 if freq.0 > 25_000_000 { 1799 if freq.0 > 25_000_000 {
1526 // Switch to SDR25 1800 // Switch to SDR25
1527 self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; 1801 self.signalling = card.switch_signalling_mode(self, cmd_block, Signalling::SDR25).await?;
1528 1802
1529 if self.signalling == Signalling::SDR25 { 1803 if self.signalling == Signalling::SDR25 {
1530 // Set final clock frequency 1804 // Set final clock frequency
1531 self.clkcr_set_clkdiv(freq.0, bus_width)?; 1805 self.clkcr_set_clkdiv(freq.0, bus_width)?;
1532 1806
1533 if self.read_status::<SD>(self.card.as_ref().unwrap())?.state() != CurrentState::Transfer { 1807 if self.read_status(card)?.state() != CurrentState::Transfer {
1534 return Err(Error::SignalingSwitchFailed); 1808 return Err(Error::SignalingSwitchFailed);
1535 } 1809 }
1536 } 1810 }
1537 } 1811 }
1538 1812
1539 // Read status after signalling change 1813 // Read status after signalling change
1540 self.read_sd_status().await?; 1814 card.read_sd_status(self, cmd_block).await?;
1541 } 1815 }
1542 SdmmcPeripheral::Emmc(_) => { 1816 SdmmcPeripheral::Emmc(emmc) => {
1543 self.read_ext_csd().await?; 1817 emmc.read_ext_csd(self).await?;
1544 } 1818 }
1545 } 1819 }
1546 1820
@@ -1550,223 +1824,35 @@ impl<'d> Sdmmc<'d> {
1550 /// Initializes card (if present) and sets the bus at the specified frequency. 1824 /// Initializes card (if present) and sets the bus at the specified frequency.
1551 /// 1825 ///
1552 /// SD only. 1826 /// SD only.
1553 pub async fn init_sd_card(&mut self, freq: Hertz) -> Result<(), Error> { 1827 pub async fn init_sd_card(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Card, Error> {
1554 let _scoped_block_stop = self.info.rcc.block_stop(); 1828 let _scoped_block_stop = self.info.rcc.block_stop();
1555 1829
1556 self.init_internal(freq, SdmmcPeripheral::SdCard(Card::default())).await 1830 let mut card = SdmmcPeripheral::SdCard(Card::default());
1557 } 1831 self.init_internal(cmd_block, freq, &mut card).await?;
1558
1559 /// Switch mode using CMD6.
1560 ///
1561 /// Attempt to set a new signalling mode. The selected
1562 /// signalling mode is returned. Expects the current clock
1563 /// frequency to be > 12.5MHz.
1564 ///
1565 /// SD only.
1566 async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> {
1567 let _ = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1568 // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not
1569 // necessary"
1570
1571 let set_function = 0x8000_0000
1572 | match signalling {
1573 // See PLSS v7_10 Table 4-11
1574 Signalling::DDR50 => 0xFF_FF04,
1575 Signalling::SDR104 => 0xFF_1F03,
1576 Signalling::SDR50 => 0xFF_1F02,
1577 Signalling::SDR25 => 0xFF_FF01,
1578 Signalling::SDR12 => 0xFF_FF00,
1579 };
1580
1581 let status = match self.cmd_block.as_deref_mut() {
1582 Some(x) => x,
1583 None => &mut CmdBlock::new(),
1584 };
1585
1586 // Arm `OnDrop` after the buffer, so it will be dropped first
1587 let on_drop = OnDrop::new(|| self.on_drop());
1588
1589 let transfer = self.prepare_datapath_read(
1590 &self.config,
1591 #[cfg(sdmmc_v1)]
1592 &mut self.dma,
1593 status.as_mut(),
1594 64,
1595 6,
1596 );
1597 self.enable_interrupts();
1598 self.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6
1599
1600 let res = self.complete_datapath_transfer(true).await;
1601
1602 // Host is allowed to use the new functions at least 8
1603 // clocks after the end of the switch command
1604 // transaction. We know the current clock period is < 80ns,
1605 // so a total delay of 640ns is required here
1606 for _ in 0..300 {
1607 cortex_m::asm::nop();
1608 }
1609
1610 match res {
1611 Ok(_) => {
1612 on_drop.defuse();
1613 self.stop_datapath();
1614 drop(transfer);
1615
1616 // Function Selection of Function Group 1
1617 let selection = (u32::from_be(status[4]) >> 24) & 0xF;
1618
1619 match selection {
1620 0 => Ok(Signalling::SDR12),
1621 1 => Ok(Signalling::SDR25),
1622 2 => Ok(Signalling::SDR50),
1623 3 => Ok(Signalling::SDR104),
1624 4 => Ok(Signalling::DDR50),
1625 _ => Err(Error::UnsupportedCardType),
1626 }
1627 }
1628 Err(e) => Err(e),
1629 }
1630 }
1631
1632 /// Reads the SCR register.
1633 ///
1634 /// SD only.
1635 async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> {
1636 // Read the 64-bit SCR register
1637 self.cmd(common_cmd::set_block_length(8), false)?; // CMD16
1638 self.cmd(common_cmd::app_cmd(card.rca), false)?;
1639
1640 let cmd_block = match self.cmd_block.as_deref_mut() {
1641 Some(x) => x,
1642 None => &mut CmdBlock::new(),
1643 };
1644 let scr = &mut cmd_block.0[..2];
1645
1646 // Arm `OnDrop` after the buffer, so it will be dropped first
1647 let on_drop = OnDrop::new(|| self.on_drop());
1648
1649 let transfer = self.prepare_datapath_read(
1650 &self.config,
1651 #[cfg(sdmmc_v1)]
1652 &mut self.dma,
1653 scr,
1654 8,
1655 3,
1656 );
1657 self.enable_interrupts();
1658 self.cmd(sd_cmd::send_scr(), true)?;
1659 1832
1660 let res = self.complete_datapath_transfer(true).await; 1833 let card = match card {
1661 1834 SdmmcPeripheral::SdCard(card) => card,
1662 if res.is_ok() { 1835 _ => unreachable!(),
1663 on_drop.defuse();
1664 self.stop_datapath();
1665 drop(transfer);
1666
1667 unsafe {
1668 let scr_bytes = &*(&scr as *const _ as *const [u8; 8]);
1669 card.scr = SCR(u64::from_be_bytes(*scr_bytes));
1670 }
1671 }
1672 res
1673 }
1674
1675 /// Reads the SD Status (ACMD13)
1676 ///
1677 /// SD only.
1678 async fn read_sd_status(&mut self) -> Result<(), Error> {
1679 let card = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card();
1680 let rca = card.rca;
1681
1682 let cmd_block = match self.cmd_block.as_deref_mut() {
1683 Some(x) => x,
1684 None => &mut CmdBlock::new(),
1685 }; 1836 };
1686 1837
1687 self.cmd(common_cmd::set_block_length(64), false)?; // CMD16 1838 Ok(card)
1688 self.cmd(common_cmd::app_cmd(rca), false)?; // APP
1689
1690 let status = cmd_block;
1691
1692 // Arm `OnDrop` after the buffer, so it will be dropped first
1693 let on_drop = OnDrop::new(|| self.on_drop());
1694
1695 let transfer = self.prepare_datapath_read(
1696 &self.config,
1697 #[cfg(sdmmc_v1)]
1698 &mut self.dma,
1699 status.as_mut(),
1700 64,
1701 6,
1702 );
1703 self.enable_interrupts();
1704 self.cmd(sd_cmd::sd_status(), true)?;
1705
1706 let res = self.complete_datapath_transfer(true).await;
1707
1708 if res.is_ok() {
1709 on_drop.defuse();
1710 self.stop_datapath();
1711 drop(transfer);
1712
1713 for byte in status.iter_mut() {
1714 *byte = u32::from_be(*byte);
1715 }
1716 card.status = status.0.into();
1717 }
1718 res
1719 } 1839 }
1720 1840
1721 /// Initializes eMMC and sets the bus at the specified frequency. 1841 /// Initializes eMMC and sets the bus at the specified frequency.
1722 /// 1842 ///
1723 /// eMMC only. 1843 /// eMMC only.
1724 pub async fn init_emmc(&mut self, freq: Hertz) -> Result<(), Error> { 1844 pub async fn init_emmc(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Emmc, Error> {
1725 let _scoped_block_stop = self.info.rcc.block_stop(); 1845 let _scoped_block_stop = self.info.rcc.block_stop();
1726 1846
1727 self.init_internal(freq, SdmmcPeripheral::Emmc(Emmc::default())).await 1847 let mut card = SdmmcPeripheral::Emmc(Emmc::default());
1728 } 1848 self.init_internal(cmd_block, freq, &mut card).await?;
1729
1730 /// Gets the EXT_CSD register.
1731 ///
1732 /// eMMC only.
1733 async fn read_ext_csd(&mut self) -> Result<(), Error> {
1734 let mut card = self.card.take().ok_or(Error::NoCard)?;
1735 let emmc = card.get_emmc();
1736
1737 // Note: cmd_block can't be used because ExtCSD is too long to fit.
1738 let mut data_block = DataBlock([0u8; 512]);
1739
1740 // NOTE(unsafe) DataBlock uses align 4
1741 let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) };
1742
1743 self.cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16
1744
1745 let transfer = self.prepare_datapath_read(
1746 &self.config,
1747 #[cfg(sdmmc_v1)]
1748 &mut self.dma,
1749 buffer,
1750 512,
1751 9,
1752 );
1753 self.enable_interrupts();
1754 self.cmd(emmc_cmd::send_ext_csd(), true)?;
1755
1756 // Arm `OnDrop` after the buffer, so it will be dropped first
1757 let on_drop = OnDrop::new(|| self.on_drop());
1758
1759 let res = self.complete_datapath_transfer(true).await;
1760
1761 if res.is_ok() {
1762 on_drop.defuse();
1763 self.stop_datapath();
1764 drop(transfer);
1765 1849
1766 emmc.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into(); 1850 let card = match card {
1767 } 1851 SdmmcPeripheral::Emmc(card) => card,
1852 _ => unreachable!(),
1853 };
1768 1854
1769 res 1855 Ok(card)
1770 } 1856 }
1771} 1857}
1772 1858
@@ -1874,47 +1960,47 @@ foreach_peripheral!(
1874 }; 1960 };
1875); 1961);
1876 1962
1877impl<'d> block_device_driver::BlockDevice<512> for Sdmmc<'d> { 1963// impl<'d, A: Addressable> block_device_driver::BlockDevice<512> for Sdmmc<'d>, A {
1878 type Error = Error; 1964// type Error = Error;
1879 type Align = aligned::A4; 1965// type Align = aligned::A4;
1880 1966//
1881 async fn read( 1967// async fn read(
1882 &mut self, 1968// &mut self,
1883 block_address: u32, 1969// block_address: u32,
1884 buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>], 1970// buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>],
1885 ) -> Result<(), Self::Error> { 1971// ) -> Result<(), Self::Error> {
1886 let _scoped_block_stop = self.info.rcc.block_stop(); 1972// let _scoped_block_stop = self.info.rcc.block_stop();
1887 // TODO: I think block_address needs to be adjusted by the partition start offset 1973// // TODO: I think block_address needs to be adjusted by the partition start offset
1888 if buf.len() == 1 { 1974// if buf.len() == 1 {
1889 let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut crate::sdmmc::DataBlock) }; 1975// let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut crate::sdmmc::DataBlock) };
1890 self.read_block(block_address, block).await?; 1976// self.read_block(block_address, block).await?;
1891 } else { 1977// } else {
1892 let blocks: &mut [DataBlock] = 1978// let blocks: &mut [DataBlock] =
1893 unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) }; 1979// unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) };
1894 self.read_blocks(block_address, blocks).await?; 1980// self.read_blocks(block_address, blocks).await?;
1895 } 1981// }
1896 Ok(()) 1982// Ok(())
1897 } 1983// }
1898 1984//
1899 async fn write( 1985// async fn write(
1900 &mut self, 1986// &mut self,
1901 block_address: u32, 1987// block_address: u32,
1902 buf: &[aligned::Aligned<Self::Align, [u8; 512]>], 1988// buf: &[aligned::Aligned<Self::Align, [u8; 512]>],
1903 ) -> Result<(), Self::Error> { 1989// ) -> Result<(), Self::Error> {
1904 let _scoped_block_stop = self.info.rcc.block_stop(); 1990// let _scoped_block_stop = self.info.rcc.block_stop();
1905 // TODO: I think block_address needs to be adjusted by the partition start offset 1991// // TODO: I think block_address needs to be adjusted by the partition start offset
1906 if buf.len() == 1 { 1992// if buf.len() == 1 {
1907 let block = unsafe { &*(&buf[0] as *const _ as *const crate::sdmmc::DataBlock) }; 1993// let block = unsafe { &*(&buf[0] as *const _ as *const crate::sdmmc::DataBlock) };
1908 self.write_block(block_address, block).await?; 1994// self.write_block(block_address, block).await?;
1909 } else { 1995// } else {
1910 let blocks: &[DataBlock] = 1996// let blocks: &[DataBlock] =
1911 unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) }; 1997// unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) };
1912 self.write_blocks(block_address, blocks).await?; 1998// self.write_blocks(block_address, blocks).await?;
1913 } 1999// }
1914 Ok(()) 2000// Ok(())
1915 } 2001// }
1916 2002//
1917 async fn size(&mut self) -> Result<u64, Self::Error> { 2003// async fn size(&mut self) -> Result<u64, Self::Error> {
1918 Ok(self.card()?.size()) 2004// Ok(self.card()?.size())
1919 } 2005// }
1920} 2006// }
diff --git a/embassy-stm32/src/time.rs b/embassy-stm32/src/time.rs
index 532877f70..88a28ee3d 100644
--- a/embassy-stm32/src/time.rs
+++ b/embassy-stm32/src/time.rs
@@ -4,7 +4,7 @@ use core::fmt::Display;
4use core::ops::{Div, Mul}; 4use core::ops::{Div, Mul};
5 5
6/// Hertz 6/// Hertz
7#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug)] 7#[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug, Default)]
8pub struct Hertz(pub u32); 8pub struct Hertz(pub u32);
9 9
10impl Display for Hertz { 10impl Display for Hertz {