1use crate::gpio::alt::sdio as alt;
4use crate::pac::{self, SDIO};
5use crate::rcc::{Enable, Rcc, Reset};
6#[allow(unused_imports)]
7use fugit::HertzU32 as Hertz;
8pub use sdio_host::{
9 common_cmd::{self, ResponseLen},
10 emmc::{CardCapacity, CardStatus, CurrentState, CID, CSD, EMMC, OCR, RCA},
11 emmc_cmd,
12 sd::{SDStatus, CIC, SCR, SD},
13 sd_cmd, Cmd,
14};
15
16pub trait Pins {
17 const BUSWIDTH: Buswidth;
18
19 type SdPins;
20 fn convert(self) -> Self::SdPins;
21}
22
23impl<CLK, CMD, D0, D1, D2, D3, D4, D5, D6, D7> Pins for (CLK, CMD, D0, D1, D2, D3, D4, D5, D6, D7)
24where
25 CLK: Into<alt::Ck>,
26 CMD: Into<alt::Cmd>,
27 D0: Into<alt::D0>,
28 D1: Into<alt::D1>,
29 D2: Into<alt::D2>,
30 D3: Into<alt::D3>,
31 D4: Into<alt::D4>,
32 D5: Into<alt::D5>,
33 D6: Into<alt::D6>,
34 D7: Into<alt::D7>,
35{
36 const BUSWIDTH: Buswidth = Buswidth::Buswidth8;
37
38 type SdPins = (
39 alt::Ck,
40 alt::Cmd,
41 alt::D0,
42 alt::D1,
43 alt::D2,
44 alt::D3,
45 alt::D4,
46 alt::D5,
47 alt::D6,
48 alt::D7,
49 );
50 fn convert(self) -> Self::SdPins {
51 (
52 self.0.into(),
53 self.1.into(),
54 self.2.into(),
55 self.3.into(),
56 self.4.into(),
57 self.5.into(),
58 self.6.into(),
59 self.7.into(),
60 self.8.into(),
61 self.9.into(),
62 )
63 }
64}
65
66impl<CLK, CMD, D0, D1, D2, D3> Pins for (CLK, CMD, D0, D1, D2, D3)
67where
68 CLK: Into<alt::Ck>,
69 CMD: Into<alt::Cmd>,
70 D0: Into<alt::D0>,
71 D1: Into<alt::D1>,
72 D2: Into<alt::D2>,
73 D3: Into<alt::D3>,
74{
75 const BUSWIDTH: Buswidth = Buswidth::Buswidth4;
76
77 type SdPins = (alt::Ck, alt::Cmd, alt::D0, alt::D1, alt::D2, alt::D3);
78 fn convert(self) -> Self::SdPins {
79 (
80 self.0.into(),
81 self.1.into(),
82 self.2.into(),
83 self.3.into(),
84 self.4.into(),
85 self.5.into(),
86 )
87 }
88}
89
90impl<CLK, CMD, D0> Pins for (CLK, CMD, D0)
91where
92 CLK: Into<alt::Ck>,
93 CMD: Into<alt::Cmd>,
94 D0: Into<alt::D0>,
95{
96 const BUSWIDTH: Buswidth = Buswidth::Buswidth1;
97
98 type SdPins = (alt::Ck, alt::Cmd, alt::D0);
99 fn convert(self) -> Self::SdPins {
100 (self.0.into(), self.1.into(), self.2.into())
101 }
102}
103
104#[derive(Copy, Clone, Eq, PartialEq)]
105pub enum Buswidth {
106 Buswidth1 = 0,
107 Buswidth4 = 1,
108 Buswidth8 = 2,
109}
110
111pub enum ClockFreq {
113 F24Mhz = 0,
114 F16Mhz = 1,
115 F12Mhz = 2,
116 F8Mhz = 8,
117 F4Mhz = 10,
118 F1Mhz = 46,
119 F400Khz = 118,
120}
121
122#[derive(Debug, Eq, PartialEq, Copy, Clone)]
123pub enum Error {
124 Timeout,
125 SoftwareTimeout,
126 Crc,
127 UnsupportedCardVersion,
128 UnsupportedCardType,
129 UnsupportedVoltage,
130 DataCrcFail,
131 RxOverFlow,
132 TxUnderErr,
133 NoCard,
134}
135
136#[derive(Debug, Copy, Clone)]
137pub enum AddressMode {
138 Byte,
139 Block512,
140}
141
142pub struct Sdio<P: SdioPeripheral> {
144 sdio: SDIO,
145 bw: Buswidth,
146 card: Option<P>,
147 clock: Hertz,
148}
149
150pub struct SdCard {
152 pub capacity: CardCapacity,
153 pub ocr: OCR<SD>,
154 pub rca: RCA<SD>, pub cid: CID<SD>,
156 pub csd: CSD<SD>,
157 pub scr: SCR,
158}
159
160pub struct Emmc {
162 pub ocr: OCR<EMMC>,
163 pub rca: RCA<EMMC>, pub cid: CID<EMMC>,
165 pub csd: CSD<EMMC>,
166}
167
168impl<P: SdioPeripheral> Sdio<P> {
169 pub fn new<PINS: Pins>(sdio: SDIO, pins: PINS, rcc: &mut Rcc) -> Self {
171 SDIO::enable(rcc);
173 SDIO::reset(rcc);
174
175 sdio.clkcr().write(|w| {
177 w.widbus().bus_width1();
178 w.clken().enabled();
179 w.clkdiv().set(ClockFreq::F400Khz as u8);
180 w.pwrsav().disabled();
181 w.bypass().disabled();
182 w.negedge().rising();
183 w.hwfc_en().disabled()
189 });
190
191 let _pins = pins.convert();
192
193 let mut host = Self {
194 sdio,
195 bw: PINS::BUSWIDTH,
196 card: None,
197 clock: rcc.clocks.sysclk(),
198 };
199
200 host.power_card(false);
202 host
203 }
204
205 fn power_card(&mut self, on: bool) {
206 use crate::pac::sdio::power::PWRCTRL;
207
208 self.sdio.power().modify(|_, w| {
209 w.pwrctrl().variant(if on {
210 PWRCTRL::PowerOn
211 } else {
212 PWRCTRL::PowerOff
213 })
214 });
215
216 cortex_m::asm::delay(2 * (self.clock.raw() / 1000));
218 }
219
220 pub fn card(&self) -> Result<&P, Error> {
222 self.card.as_ref().ok_or(Error::NoCard)
223 }
224
225 pub fn read_block(&mut self, blockaddr: u32, block: &mut [u8; 512]) -> Result<(), Error> {
227 let card = self.card()?;
228
229 let blockaddr = match card.get_address_mode() {
232 AddressMode::Byte => blockaddr * 512,
233 AddressMode::Block512 => blockaddr,
234 };
235 self.cmd(common_cmd::set_block_length(512))?;
236 self.start_datapath_transfer(512, 9, true);
237 self.cmd(common_cmd::read_single_block(blockaddr))?;
238
239 let mut i = 0;
240
241 let status = loop {
242 let sta = self.sdio.sta().read();
243
244 if sta.rxact().bit_is_clear() {
245 break sta;
246 }
247
248 if sta.rxfifohf().bit() {
249 for _ in 0..8 {
250 let bytes = self.sdio.fifo().read().bits().to_le_bytes();
251 block[i..i + 4].copy_from_slice(&bytes);
252 i += 4;
253 }
254 }
255
256 if i == block.len() {
257 break sta;
258 }
259 };
260
261 status_to_error(status)?;
262
263 while !self.card_ready()? {}
265
266 Ok(())
267 }
268
269 pub fn write_block(&mut self, blockaddr: u32, block: &[u8; 512]) -> Result<(), Error> {
271 let card = self.card()?;
272
273 let blockaddr = match card.get_address_mode() {
276 AddressMode::Byte => blockaddr * 512,
277 AddressMode::Block512 => blockaddr,
278 };
279 self.cmd(common_cmd::set_block_length(512))?;
280 self.start_datapath_transfer(512, 9, false);
281 self.cmd(common_cmd::write_single_block(blockaddr))?;
282
283 let mut i = 0;
284
285 let status = loop {
286 let sta = self.sdio.sta().read();
287
288 if sta.txact().bit_is_clear() {
289 break sta;
290 }
291
292 if sta.txfifohe().bit() {
293 for _ in 0..8 {
294 let mut wb = [0u8; 4];
295 wb.copy_from_slice(&block[i..i + 4]);
296 let word = u32::from_le_bytes(wb);
297 self.sdio.fifo().write(|w| w.set(word));
298 i += 4;
299 }
300 }
301
302 if i == block.len() {
303 break sta;
304 }
305 };
306
307 status_to_error(status)?;
308
309 loop {
311 let sta = self.sdio.sta().read();
312 if !sta.txact().bit_is_set() {
313 break;
314 }
315 }
316
317 while !self.card_ready()? {}
319
320 Ok(())
321 }
322
323 fn start_datapath_transfer(&self, length_bytes: u32, block_size: u8, card_to_controller: bool) {
324 use crate::pac::sdio::dctrl::DTDIR;
325
326 assert!(block_size <= 14);
328
329 loop {
331 let status = self.sdio.sta().read();
332
333 if status.cmdact().bit_is_clear()
334 && status.rxact().bit_is_clear()
335 && status.txact().bit_is_clear()
336 {
337 break;
338 }
339 }
340
341 let dtdir = if card_to_controller {
342 DTDIR::CardToController
343 } else {
344 DTDIR::ControllerToCard
345 };
346
347 self.sdio.dtimer().write(|w| w.datatime().set(0xFFFF_FFFF));
349 self.sdio.dlen().write(|w| w.datalength().set(length_bytes));
351 self.sdio.dctrl().write(|w| {
353 unsafe {
354 w.dblocksize().bits(block_size);
355 } w.dtdir().variant(dtdir);
357 w.dten().enabled() });
359 }
360
361 fn read_status(&mut self) -> Result<CardStatus<P>, Error> {
363 let card = self.card()?;
364
365 self.cmd(common_cmd::card_status(card.get_address(), false))?;
366
367 let r1 = self.sdio.resp1().read().bits();
368 Ok(CardStatus::from(r1))
369 }
370
371 fn card_ready(&mut self) -> Result<bool, Error> {
373 Ok(self.read_status()?.state() == CurrentState::Transfer)
374 }
375
376 fn select_card(&self, rca: u16) -> Result<(), Error> {
378 let r = self.cmd(common_cmd::select_card(rca));
379 match (r, rca) {
380 (Err(Error::Timeout), 0) => Ok(()),
381 _ => r,
382 }
383 }
384
385 fn app_cmd<R: common_cmd::Resp>(&self, acmd: Cmd<R>) -> Result<(), Error> {
386 let rca = self.card().map(|card| card.get_address()).unwrap_or(0);
387 self.cmd(common_cmd::app_cmd(rca))?;
388 self.cmd(acmd)
389 }
390
391 fn cmd<R: common_cmd::Resp>(&self, cmd: Cmd<R>) -> Result<(), Error> {
393 use crate::pac::sdio::cmd::WAITRESP;
394
395 while self.sdio.sta().read().cmdact().bit_is_set() {}
397
398 clear_all_interrupts(self.sdio.icr());
400
401 self.sdio.arg().write(|w| w.cmdarg().set(cmd.arg));
403
404 let waitresp = match cmd.response_len() {
406 ResponseLen::Zero => WAITRESP::NoResponse,
407 ResponseLen::R48 => WAITRESP::ShortResponse,
408 ResponseLen::R136 => WAITRESP::LongResponse,
409 };
410
411 self.sdio.cmd().write(|w| {
413 w.waitresp().variant(waitresp);
414 w.cmdindex().set(cmd.cmd);
415 w.waitint().disabled();
416 w.cpsmen().enabled()
417 });
418
419 let mut timeout: u32 = 0xFFFF_FFFF;
420
421 let status = if cmd.response_len() == ResponseLen::Zero {
422 loop {
424 let sta = self.sdio.sta().read();
425
426 if sta.cmdact().bit_is_clear()
427 && (sta.ctimeout().bit_is_set() || sta.cmdsent().bit_is_set())
428 {
429 break sta;
430 }
431
432 if timeout == 0 {
433 return Err(Error::SoftwareTimeout);
434 }
435
436 timeout -= 1;
437 }
438 } else {
439 loop {
440 let sta = self.sdio.sta().read();
441
442 if sta.cmdact().bit_is_clear()
443 && (sta.ctimeout().bit()
444 || sta.cmdrend().bit_is_set()
445 || sta.ccrcfail().bit_is_set())
446 {
447 break sta;
448 }
449
450 if timeout == 0 {
451 return Err(Error::SoftwareTimeout);
452 }
453
454 timeout -= 1;
455 }
456 };
457
458 status_to_error(status)
459 }
460}
461
462impl Sdio<SdCard> {
463 pub fn init(&mut self, freq: ClockFreq) -> Result<(), Error> {
465 self.power_card(true);
467
468 self.sdio.clkcr().modify(|_, w| w.clken().enabled());
470 self.cmd(common_cmd::idle())?;
472
473 self.cmd(sd_cmd::send_if_cond(1, 0xAA))?;
475 let cic = CIC::from(self.sdio.resp1().read().bits());
476
477 if cic.pattern() != 0xAA {
479 return Err(Error::UnsupportedCardVersion);
480 }
481
482 if cic.voltage_accepted() & 1 == 0 {
483 return Err(Error::UnsupportedVoltage);
484 }
485
486 let ocr = loop {
487 let voltage_window = 1 << 5;
491 match self.app_cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window)) {
492 Ok(_) => (),
493 Err(Error::Crc) => (),
494 Err(err) => return Err(err),
495 }
496 let ocr = OCR::from(self.sdio.resp1().read().bits());
497 if ocr.is_busy() {
498 continue;
500 }
501 break ocr;
502 };
503
504 let capacity = if ocr.high_capacity() {
506 CardCapacity::HighCapacity
507 } else {
508 CardCapacity::StandardCapacity
509 };
510
511 self.cmd(common_cmd::all_send_cid())?;
513 let mut cid = [0; 4];
514 cid[3] = self.sdio.resp1().read().bits();
515 cid[2] = self.sdio.resp2().read().bits();
516 cid[1] = self.sdio.resp3().read().bits();
517 cid[0] = self.sdio.resp4().read().bits();
518 let cid = CID::from(cid);
519
520 self.cmd(sd_cmd::send_relative_address())?;
522 let rca = RCA::from(self.sdio.resp1().read().bits());
523 let card_addr = rca.address();
524
525 self.cmd(common_cmd::send_csd(card_addr))?;
527
528 let mut csd = [0; 4];
529 csd[3] = self.sdio.resp1().read().bits();
530 csd[2] = self.sdio.resp2().read().bits();
531 csd[1] = self.sdio.resp3().read().bits();
532 csd[0] = self.sdio.resp4().read().bits();
533 let csd = CSD::from(csd);
534
535 self.select_card(card_addr)?;
536 let scr = self.get_scr(card_addr)?;
537
538 let card = SdCard {
539 capacity,
540 ocr,
541 rca,
542 cid,
543 csd,
544 scr,
545 };
546
547 self.card.replace(card);
548
549 while !self.card_ready()? {}
551
552 self.set_bus(self.bw, freq)?;
553 Ok(())
554 }
555
556 pub fn read_sd_status(&mut self) -> Result<SDStatus, Error> {
558 let _card = self.card()?;
559 self.cmd(common_cmd::set_block_length(64))?;
560 self.start_datapath_transfer(64, 6, true);
561 self.app_cmd(sd_cmd::sd_status())?;
562
563 let mut status = [0u32; 16];
564 let mut idx = 0;
565
566 let s = loop {
567 let sta = self.sdio.sta().read();
568
569 if sta.rxact().bit_is_clear() {
570 break sta;
571 }
572
573 if sta.rxfifohf().bit() {
574 for _ in 0..8 {
575 status[15 - idx] = self.sdio.fifo().read().bits().swap_bytes();
576 idx += 1;
577 }
578 }
579
580 if idx == status.len() {
581 break sta;
582 }
583 };
584
585 status_to_error(s)?;
586 Ok(SDStatus::from(status))
587 }
588
589 fn get_scr(&self, rca: u16) -> Result<SCR, Error> {
591 self.cmd(common_cmd::set_block_length(8))?;
592 self.start_datapath_transfer(8, 3, true);
593 self.cmd(common_cmd::app_cmd(rca))?;
594 self.cmd(sd_cmd::send_scr())?;
595
596 let mut buf = [0; 2];
597 let mut i = 0;
598
599 let status = loop {
600 let sta = self.sdio.sta().read();
601
602 if sta.rxact().bit_is_clear() {
603 break sta;
604 }
605
606 if sta.rxdavl().bit() {
607 buf[1 - i] = self.sdio.fifo().read().bits().swap_bytes();
608 i += 1;
609 }
610
611 if i == 2 {
612 break sta;
613 }
614 };
615
616 status_to_error(status)?;
617 Ok(SCR::from(buf))
618 }
619
620 fn set_bus(&self, width: Buswidth, freq: ClockFreq) -> Result<(), Error> {
622 use crate::pac::sdio::clkcr::WIDBUS;
623
624 let card_widebus = self.card()?.supports_widebus();
625
626 let width = match width {
627 Buswidth::Buswidth4 if card_widebus => WIDBUS::BusWidth4,
628 _ => WIDBUS::BusWidth1,
630 };
631
632 self.app_cmd(sd_cmd::set_bus_width(width == WIDBUS::BusWidth4))?;
633
634 self.sdio.clkcr().modify(|_, w| {
635 w.clkdiv().set(freq as u8);
636 w.widbus().variant(width);
637 w.clken().enabled()
638 });
639 Ok(())
640 }
641}
642
643impl Sdio<Emmc> {
644 pub fn init(&mut self, freq: ClockFreq) -> Result<(), Error> {
646 let card_addr: RCA<EMMC> = RCA::from(1u16);
647
648 self.power_card(true);
650
651 self.sdio.clkcr().modify(|_, w| w.clken().enabled());
653 self.cmd(common_cmd::idle())?;
655
656 let ocr = loop {
657 match self.cmd(emmc_cmd::send_op_cond(0b01000000111111111000000000000000)) {
662 Ok(_) => (),
663 Err(Error::Crc) => (),
664 Err(err) => return Err(err),
665 };
666 let ocr = OCR::<EMMC>::from(self.sdio.resp1().read().bits());
667 if !ocr.is_busy() {
668 break ocr;
669 }
670 };
671
672 self.cmd(common_cmd::all_send_cid())?;
674 let mut cid = [0; 4];
675 cid[3] = self.sdio.resp1().read().bits();
676 cid[2] = self.sdio.resp2().read().bits();
677 cid[1] = self.sdio.resp3().read().bits();
678 cid[0] = self.sdio.resp4().read().bits();
679 let cid = CID::<EMMC>::from(cid);
680
681 self.cmd(emmc_cmd::assign_relative_address(card_addr.address()))?;
682
683 self.cmd(common_cmd::send_csd(card_addr.address()))?;
684
685 let mut csd = [0; 4];
686 csd[3] = self.sdio.resp1().read().bits();
687 csd[2] = self.sdio.resp2().read().bits();
688 csd[1] = self.sdio.resp3().read().bits();
689 csd[0] = self.sdio.resp4().read().bits();
690 let csd = CSD::<EMMC>::from(csd);
691
692 self.select_card(card_addr.address())?;
693
694 let card = Emmc {
695 ocr,
696 rca: card_addr,
697 cid,
698 csd,
699 };
700
701 self.card.replace(card);
702
703 while !self.card_ready()? {}
705
706 self.set_bus(self.bw, freq)?;
707 Ok(())
708 }
709
710 pub fn set_bus(&mut self, width: Buswidth, freq: ClockFreq) -> Result<(), Error> {
711 use crate::pac::sdio::clkcr::WIDBUS;
712
713 self.cmd(emmc_cmd::modify_ext_csd(
715 emmc_cmd::AccessMode::WriteByte,
716 183,
717 width as u8,
718 ))?;
719
720 let width = match width {
721 Buswidth::Buswidth1 => WIDBUS::BusWidth1,
722 Buswidth::Buswidth4 => WIDBUS::BusWidth4,
723 Buswidth::Buswidth8 => WIDBUS::BusWidth8,
724 };
725
726 while !self.card_ready()? {}
728 self.sdio.clkcr().modify(|_, w| {
729 w.clkdiv().set(freq as u8);
730 w.widbus().variant(width);
731 w.clken().enabled()
732 });
733 Ok(())
734 }
735}
736
737fn status_to_error(sta: pac::sdio::sta::R) -> Result<(), Error> {
738 if sta.ctimeout().bit_is_set() {
739 return Err(Error::Timeout);
740 } else if sta.ccrcfail().bit() {
741 return Err(Error::Crc);
742 } else if sta.dcrcfail().bit() {
743 return Err(Error::DataCrcFail);
744 } else if sta.rxoverr().bit() {
745 return Err(Error::RxOverFlow);
746 } else if sta.dtimeout().bit() {
747 return Err(Error::Timeout);
748 } else if sta.txunderr().bit() {
749 return Err(Error::TxUnderErr);
750 }
751 Ok(())
752}
753
754fn clear_all_interrupts(icr: &pac::sdio::ICR) {
755 icr.modify(|_, w| {
756 w.ccrcfailc().set_bit();
757 w.ctimeoutc().set_bit();
758 #[cfg(not(feature = "stm32f446"))]
759 w.ceataendc().set_bit();
760 w.cmdrendc().set_bit();
761 w.cmdsentc().set_bit();
762 w.dataendc().set_bit();
763 w.dbckendc().set_bit();
764 w.dcrcfailc().set_bit();
765 w.dtimeoutc().set_bit();
766 w.sdioitc().set_bit();
767 #[cfg(not(feature = "stm32f446"))]
768 w.stbiterrc().set_bit();
769 w.rxoverrc().set_bit();
770 w.txunderrc().set_bit()
771 });
772}
773
774impl SdCard {
775 pub fn block_count(&self) -> u64 {
777 self.csd.block_count()
778 }
779
780 fn supports_widebus(&self) -> bool {
782 self.scr.bus_width_four()
783 }
784}
785
786impl SdioPeripheral for SdCard {
787 fn get_address(&self) -> u16 {
788 self.rca.address()
789 }
790 fn get_address_mode(&self) -> AddressMode {
791 match self.capacity {
792 CardCapacity::StandardCapacity => AddressMode::Byte,
793 CardCapacity::HighCapacity => AddressMode::Block512,
794 _ => AddressMode::Block512,
795 }
796 }
797}
798
799impl SdioPeripheral for Emmc {
800 fn get_address(&self) -> u16 {
801 self.rca.address()
802 }
803 fn get_address_mode(&self) -> AddressMode {
804 AddressMode::Block512
805 }
806}
807
808pub trait SdioPeripheral {
809 fn get_address(&self) -> u16;
810 fn get_address_mode(&self) -> AddressMode;
811}