1use core::cell::RefCell;
5
6use crate::{Block, BlockCount, BlockDevice, BlockIdx};
7use embedded_sdmmc_types::sdcard::*;
8
9pub struct SdCard<SPI, DELAYER>
30where
31 SPI: embedded_hal::spi::SpiDevice<u8>,
32 DELAYER: embedded_hal::delay::DelayNs,
33{
34 inner: RefCell<SdCardInner<SPI, DELAYER>>,
35}
36
37impl<SPI, DELAYER> SdCard<SPI, DELAYER>
38where
39 SPI: embedded_hal::spi::SpiDevice<u8>,
40 DELAYER: embedded_hal::delay::DelayNs,
41{
42 pub fn new(spi: SPI, delayer: DELAYER) -> Self {
49 Self::new_with_options(spi, delayer, AcquireOpts::default())
50 }
51
52 pub fn new_with_options(spi: SPI, delayer: DELAYER, options: AcquireOpts) -> Self {
60 SdCard {
61 inner: RefCell::new(SdCardInner {
62 spi,
63 delayer,
64 card_type: None,
65 options,
66 }),
67 }
68 }
69
70 pub fn spi<T, F>(&self, func: F) -> T
78 where
79 F: FnOnce(&mut SPI) -> T,
80 {
81 let mut inner = self.inner.borrow_mut();
82 func(&mut inner.spi)
83 }
84
85 pub fn num_bytes(&self) -> Result<u64, Error> {
89 let mut inner = self.inner.borrow_mut();
90 inner.check_init()?;
91 inner.num_bytes()
92 }
93
94 pub fn erase_single_block_enabled(&self) -> Result<bool, Error> {
98 let mut inner = self.inner.borrow_mut();
99 inner.check_init()?;
100 inner.erase_single_block_enabled()
101 }
102
103 pub fn mark_card_uninit(&self) {
107 let mut inner = self.inner.borrow_mut();
108 inner.card_type = None;
109 }
110
111 pub fn get_card_type(&self) -> Option<CardType> {
115 let mut inner = self.inner.borrow_mut();
116 inner.check_init().ok()?;
117 inner.card_type
118 }
119
120 pub unsafe fn mark_card_as_init(&self, card_type: CardType) {
137 let mut inner = self.inner.borrow_mut();
138 inner.card_type = Some(card_type);
139 }
140}
141
142impl<SPI, DELAYER> BlockDevice for SdCard<SPI, DELAYER>
143where
144 SPI: embedded_hal::spi::SpiDevice<u8>,
145 DELAYER: embedded_hal::delay::DelayNs,
146{
147 type Error = Error;
148
149 fn read(&self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> {
153 let mut inner = self.inner.borrow_mut();
154 crate::debug!("Read {} blocks @ {}", blocks.len(), start_block_idx.0,);
155 inner.check_init()?;
156 inner.read(blocks, start_block_idx)
157 }
158
159 fn write(&self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Self::Error> {
163 let mut inner = self.inner.borrow_mut();
164 crate::debug!("Writing {} blocks @ {}", blocks.len(), start_block_idx.0);
165 inner.check_init()?;
166 inner.write(blocks, start_block_idx)
167 }
168
169 fn num_blocks(&self) -> Result<BlockCount, Self::Error> {
173 let mut inner = self.inner.borrow_mut();
174 inner.check_init()?;
175 inner.num_blocks()
176 }
177}
178
179struct SdCardInner<SPI, DELAYER>
183where
184 SPI: embedded_hal::spi::SpiDevice<u8>,
185 DELAYER: embedded_hal::delay::DelayNs,
186{
187 spi: SPI,
188 delayer: DELAYER,
189 card_type: Option<CardType>,
190 options: AcquireOpts,
191}
192
193impl<SPI, DELAYER> SdCardInner<SPI, DELAYER>
194where
195 SPI: embedded_hal::spi::SpiDevice<u8>,
196 DELAYER: embedded_hal::delay::DelayNs,
197{
198 fn read(&mut self, blocks: &mut [Block], start_block_idx: BlockIdx) -> Result<(), Error> {
200 let start_idx = match self.card_type {
201 Some(CardType::SD1 | CardType::SD2) => start_block_idx.0 * 512,
202 Some(CardType::SdhcSdxc) => start_block_idx.0,
203 None => return Err(Error::CardNotFound),
204 };
205
206 if blocks.len() == 1 {
207 self.card_command(CmdId::CMD17_ReadSingleBlock, start_idx)?;
209 self.read_data(&mut blocks[0].contents)?;
210 } else {
211 self.card_command(CmdId::CMD18_ReadMultipleBlock, start_idx)?;
213 for block in blocks.iter_mut() {
214 self.read_data(&mut block.contents)?;
215 }
216 self.card_command(CmdId::CMD12_StopTransmission, 0)?;
218 }
219 Ok(())
220 }
221
222 fn write(&mut self, blocks: &[Block], start_block_idx: BlockIdx) -> Result<(), Error> {
224 let start_idx = match self.card_type {
225 Some(CardType::SD1 | CardType::SD2) => start_block_idx.0 * 512,
226 Some(CardType::SdhcSdxc) => start_block_idx.0,
227 None => return Err(Error::CardNotFound),
228 };
229 if blocks.len() == 1 {
230 self.card_command(CmdId::CMD24_WriteBlock, start_idx)?;
232 self.write_data(DATA_START_BLOCK, &blocks[0].contents)?;
233 self.wait_not_busy(Delay::new_write())?;
234 if self.card_command(CmdId::CMD13_SendStatus, 0)? != 0x00 {
235 return Err(Error::WriteError);
236 }
237 if self.read_byte()? != 0x00 {
238 return Err(Error::WriteError);
239 }
240 } else {
241 self.card_acmd(AcmdId::ACMD23_PreErase, blocks.len() as u32)?;
245 self.wait_not_busy(Delay::new_write())?;
247
248 self.card_command(CmdId::CMD25_WriteMultipleBlock, start_idx)?;
250 for block in blocks.iter() {
251 self.wait_not_busy(Delay::new_write())?;
252 self.write_data(WRITE_MULTIPLE_TOKEN, &block.contents)?;
253 }
254 self.wait_not_busy(Delay::new_write())?;
256 self.write_byte(STOP_TRAN_TOKEN)?;
257 }
258 Ok(())
259 }
260
261 fn num_blocks(&mut self) -> Result<BlockCount, Error> {
263 let csd = self.read_csd()?;
264 crate::debug!("CSD: {:?}", csd);
265 Ok(BlockCount(csd.card_capacity_blocks()))
266 }
267
268 fn num_bytes(&mut self) -> Result<u64, Error> {
270 let csd = self.read_csd()?;
271 crate::debug!("CSD: {:?}", csd);
272 Ok(csd.card_capacity_bytes())
273 }
274
275 pub fn erase_single_block_enabled(&mut self) -> Result<bool, Error> {
277 let csd = self.read_csd()?;
278 Ok(csd.erase_single_block_enabled())
279 }
280
281 fn read_csd(&mut self) -> Result<csd::Csd, Error> {
283 if self.card_type.is_none() {
284 return Err(Error::CardNotFound);
285 }
286
287 if self.card_command(CmdId::CMD9_SendCsd, 0)? != 0 {
288 return Err(Error::RegisterReadError);
289 }
290 let mut csd_raw: [u8; 16] = [0; 16];
291 self.read_data(&mut csd_raw)?;
292
293 csd::Csd::new(&csd_raw).map_err(|_| Error::RegisterReadError)
296 }
297
298 fn read_data(&mut self, buffer: &mut [u8]) -> Result<(), Error> {
302 let mut delay = Delay::new_read();
304 let status = loop {
305 let s = self.read_byte()?;
306 if s != 0xFF {
307 break s;
308 }
309 delay.delay(&mut self.delayer, Error::TimeoutReadBuffer)?;
310 };
311 if status != DATA_START_BLOCK {
312 return Err(Error::ReadError);
313 }
314
315 buffer.fill(0xFF);
316 self.transfer_bytes(buffer)?;
317
318 let mut crc_bytes = [0xFF; 2];
321 self.transfer_bytes(&mut crc_bytes)?;
322 if self.options.use_crc {
323 let crc = u16::from_be_bytes(crc_bytes);
324 let calc_crc = crc16(buffer);
325 if crc != calc_crc {
326 return Err(Error::CrcError(crc, calc_crc));
327 }
328 }
329
330 Ok(())
331 }
332
333 fn write_data(&mut self, token: u8, buffer: &[u8]) -> Result<(), Error> {
336 self.write_byte(token)?;
337 self.write_bytes(buffer)?;
338 let crc_bytes = if self.options.use_crc {
339 crc16(buffer).to_be_bytes()
340 } else {
341 [0xFF, 0xFF]
342 };
343 self.write_bytes(&crc_bytes)?;
346
347 let status = self.read_byte()?;
348 if (status & DATA_RES_MASK) != DATA_RES_ACCEPTED {
349 Err(Error::WriteError)
350 } else {
351 Ok(())
352 }
353 }
354
355 fn check_init(&mut self) -> Result<(), Error> {
357 if self.card_type.is_none() {
358 self.acquire()
361 } else {
362 Ok(())
363 }
364 }
365
366 fn acquire(&mut self) -> Result<(), Error> {
368 crate::debug!("acquiring card with opts: {:?}", self.options);
369 let f = |s: &mut Self| {
370 let mut card_type;
372 crate::trace!("Reset card..");
373 let mut delay = Delay::new(s.options.acquire_retries);
375 for _attempts in 1.. {
376 crate::trace!("Enter SPI mode, attempt: {}..", _attempts);
377 match s.card_command(CmdId::CMD0_GoIdleState, 0) {
378 Err(Error::TimeoutCommand(CmdId::CMD0_GoIdleState)) => {
379 crate::warn!("Timed out, trying again..");
381 for _ in 0..0xFF {
384 s.write_byte(0xFF)?;
385 }
386 }
387 Err(e) => {
388 return Err(e);
389 }
390 Ok(R1_IDLE_STATE) => {
391 break;
392 }
393 Ok(_r) => {
394 crate::trace!("Got response: {:x}, trying again..", _r);
396 }
397 }
398
399 delay.delay(&mut s.delayer, Error::CardNotFound)?;
400 }
401 crate::debug!("Enable CRC: {}", s.options.use_crc);
403 if s.options.use_crc && s.card_command(CmdId::CMD59_CrcOnOff, 1)? != R1_IDLE_STATE {
406 return Err(Error::CantEnableCRC);
407 }
408 let mut delay = Delay::new_command();
410 let arg = loop {
411 if s.card_command(CmdId::CMD8_SendIfCond, 0x1AA)?
412 == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)
413 {
414 card_type = CardType::SD1;
415 break 0;
416 }
417 let mut buffer = [0xFF; 4];
418 s.transfer_bytes(&mut buffer)?;
419 let status = buffer[3];
420 if status == 0xAA {
421 card_type = CardType::SD2;
422 break 0x4000_0000;
423 }
424 delay.delay(
425 &mut s.delayer,
426 Error::TimeoutCommand(CmdId::CMD8_SendIfCond),
427 )?;
428 };
429
430 let mut delay = Delay::new_command();
431 while s.card_acmd(AcmdId::ACMD41_SdSendOpCond, arg)? != R1_READY_STATE {
432 delay.delay(
433 &mut s.delayer,
434 Error::TimeoutACommand(AcmdId::ACMD41_SdSendOpCond),
435 )?;
436 }
437
438 if card_type == CardType::SD2 {
439 if s.card_command(CmdId::CMD58_ReadOcr, 0)? != 0 {
440 return Err(Error::Cmd58Error);
441 }
442 let mut buffer = [0xFF; 4];
443 s.transfer_bytes(&mut buffer)?;
444 if (buffer[0] & 0xC0) == 0xC0 {
445 card_type = CardType::SdhcSdxc;
446 }
447 }
449 crate::debug!("Card version: {:?}", card_type);
450 s.card_type = Some(card_type);
451 Ok(())
452 };
453 let result = f(self);
454 let _ = self.read_byte();
455 result
456 }
457
458 fn card_acmd(&mut self, command: AcmdId, arg: u32) -> Result<u8, Error> {
460 self.card_command(CmdId::CMD55_AppCmd, 0)?;
461 self.card_acmd_after_escape(command, arg)
462 }
463
464 fn card_acmd_after_escape(&mut self, command: AcmdId, arg: u32) -> Result<u8, Error> {
465 self.wait_not_busy(Delay::new_command())?;
468 let mut buf = [
469 0x40 | command as u8,
470 (arg >> 24) as u8,
471 (arg >> 16) as u8,
472 (arg >> 8) as u8,
473 arg as u8,
474 0,
475 ];
476 buf[5] = (crc7(&buf[0..5]) << 1) | 1;
477
478 self.write_bytes(&buf)?;
479
480 let mut delay = Delay::new_command();
481 loop {
482 let result = self.read_byte()?;
483 if (result & 0x80) == ERROR_OK {
484 return Ok(result);
485 }
486 delay.delay(&mut self.delayer, Error::TimeoutACommand(command))?;
487 }
488 }
489
490 fn card_command(&mut self, command: CmdId, arg: u32) -> Result<u8, Error> {
492 if command != CmdId::CMD0_GoIdleState && command != CmdId::CMD12_StopTransmission {
493 self.wait_not_busy(Delay::new_command())?;
494 }
495
496 let mut buf = [
497 0x40 | command as u8,
498 (arg >> 24) as u8,
499 (arg >> 16) as u8,
500 (arg >> 8) as u8,
501 arg as u8,
502 0,
503 ];
504 buf[5] = (crc7(&buf[0..5]) << 1) | 1;
505
506 self.write_bytes(&buf)?;
507
508 if command == CmdId::CMD12_StopTransmission {
510 let _result = self.read_byte()?;
511 }
512
513 let mut delay = Delay::new_command();
514 loop {
515 let result = self.read_byte()?;
516 if (result & 0x80) == ERROR_OK {
517 return Ok(result);
518 }
519 delay.delay(&mut self.delayer, Error::TimeoutCommand(command))?;
520 }
521 }
522
523 fn read_byte(&mut self) -> Result<u8, Error> {
525 self.transfer_byte(0xFF)
526 }
527
528 fn write_byte(&mut self, out: u8) -> Result<(), Error> {
530 let _ = self.transfer_byte(out)?;
531 Ok(())
532 }
533
534 fn transfer_byte(&mut self, out: u8) -> Result<u8, Error> {
536 let mut read_buf = [0u8; 1];
537 self.spi
538 .transfer(&mut read_buf, &[out])
539 .map_err(|_| Error::Transport)?;
540 Ok(read_buf[0])
541 }
542
543 fn write_bytes(&mut self, out: &[u8]) -> Result<(), Error> {
545 self.spi.write(out).map_err(|_e| Error::Transport)?;
546 Ok(())
547 }
548
549 fn transfer_bytes(&mut self, in_out: &mut [u8]) -> Result<(), Error> {
551 self.spi
552 .transfer_in_place(in_out)
553 .map_err(|_e| Error::Transport)?;
554 Ok(())
555 }
556
557 fn wait_not_busy(&mut self, mut delay: Delay) -> Result<(), Error> {
560 loop {
561 let s = self.read_byte()?;
562 if s == 0xFF {
563 break;
564 }
565 delay.delay(&mut self.delayer, Error::TimeoutWaitNotBusy)?;
566 }
567 Ok(())
568 }
569}
570
571#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
573#[derive(Debug)]
574pub struct AcquireOpts {
575 pub use_crc: bool,
583
584 pub acquire_retries: u32,
587}
588
589impl Default for AcquireOpts {
590 fn default() -> Self {
591 AcquireOpts {
592 use_crc: true,
593 acquire_retries: 50,
594 }
595 }
596}
597
598#[cfg_attr(feature = "defmt-log", derive(defmt::Format))]
600#[derive(Debug, Copy, Clone)]
601pub enum Error {
602 Transport,
604 CantEnableCRC,
606 TimeoutReadBuffer,
608 TimeoutWaitNotBusy,
610 TimeoutCommand(CmdId),
612 TimeoutACommand(AcmdId),
614 Cmd58Error,
616 RegisterReadError,
618 CrcError(u16, u16),
620 ReadError,
622 WriteError,
624 BadState,
626 CardNotFound,
628 GpioError,
630}
631
632impl core::fmt::Display for Error {
633 fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
634 match self {
635 Error::Transport => write!(f, "error from SPI peripheral"),
636 Error::CantEnableCRC => write!(f, "failed to enable CRC checking"),
637 Error::TimeoutReadBuffer => write!(f, "timeout when reading data"),
638 Error::TimeoutWaitNotBusy => write!(f, "timeout when waiting for card to not be busy"),
639 Error::TimeoutCommand(command) => {
640 write!(f, "timeout when executing command {command:?}")
641 }
642 Error::TimeoutACommand(command) => write!(
643 f,
644 "timeout when executing application-specific command {command:?}"
645 ),
646 Error::Cmd58Error => write!(f, "bad response from command 58"),
647 Error::RegisterReadError => write!(f, "failed to read Card Specific Data register"),
648 Error::CrcError(_, _) => write!(f, "CRC mismatch"),
649 Error::ReadError => write!(f, "read error"),
650 Error::WriteError => write!(f, "write error"),
651 Error::BadState => write!(f, "cannot perform operation with card in thiis state"),
652 Error::CardNotFound => write!(f, "card not found"),
653 Error::GpioError => write!(f, "cannot set GPIO pin"),
654 }
655 }
656}
657
658impl core::error::Error for Error {}
659
660struct Delay {
665 retries_left: u32,
666}
667
668impl Delay {
669 pub const DEFAULT_READ_RETRIES: u32 = 10_000;
675
676 pub const DEFAULT_WRITE_RETRIES: u32 = 50_000;
682
683 pub const DEFAULT_COMMAND_RETRIES: u32 = 10_000;
689
690 fn new(max_retries: u32) -> Delay {
692 Delay {
693 retries_left: max_retries,
694 }
695 }
696
697 fn new_read() -> Delay {
699 Delay::new(Self::DEFAULT_READ_RETRIES)
700 }
701
702 fn new_write() -> Delay {
704 Delay::new(Self::DEFAULT_WRITE_RETRIES)
705 }
706
707 fn new_command() -> Delay {
709 Delay::new(Self::DEFAULT_COMMAND_RETRIES)
710 }
711
712 fn delay<T>(&mut self, delayer: &mut T, err: Error) -> Result<(), Error>
718 where
719 T: embedded_hal::delay::DelayNs,
720 {
721 if self.retries_left == 0 {
722 Err(err)
723 } else {
724 delayer.delay_us(10);
725 self.retries_left -= 1;
726 Ok(())
727 }
728 }
729}
730
731