stm32f4xx_hal/
sdio.rs

1//! Sdio host
2
3use 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
111/// Clock frequency of a SDIO bus.
112pub 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
142/// A peripheral that uses the SDIO hardware, generic over the particular type of device.
143pub struct Sdio<P: SdioPeripheral> {
144    sdio: SDIO,
145    bw: Buswidth,
146    card: Option<P>,
147    clock: Hertz,
148}
149
150/// Sd card peripheral
151pub struct SdCard {
152    pub capacity: CardCapacity,
153    pub ocr: OCR<SD>,
154    pub rca: RCA<SD>, // Relative Card Address
155    pub cid: CID<SD>,
156    pub csd: CSD<SD>,
157    pub scr: SCR,
158}
159
160/// eMMC device peripheral
161pub struct Emmc {
162    pub ocr: OCR<EMMC>,
163    pub rca: RCA<EMMC>, // Relative Card Address
164    pub cid: CID<EMMC>,
165    pub csd: CSD<EMMC>,
166}
167
168impl<P: SdioPeripheral> Sdio<P> {
169    /// Create and enable the Sdio device
170    pub fn new<PINS: Pins>(sdio: SDIO, pins: PINS, rcc: &mut Rcc) -> Self {
171        // Enable and reset the sdio peripheral, it's the same bit position for both registers
172        SDIO::enable(rcc);
173        SDIO::reset(rcc);
174
175        // Configure clock
176        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            // Do not use hardware flow control.
184            // Using it causes clock glitches and CRC errors.
185            // See chip errata SDIO section:
186            // - F42x/F43x: https://www.st.com/resource/en/errata_sheet/es0206-stm32f427437-and-stm32f429439-line-limitations-stmicroelectronics.pdf
187            // - F40x/F41x: https://www.st.com/resource/en/errata_sheet/es0182-stm32f405407xx-and-stm32f415417xx-device-limitations-stmicroelectronics.pdf
188            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        // Make sure card is powered off
201        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        // Wait for 2 ms after changing power settings
217        cortex_m::asm::delay(2 * (self.clock.raw() / 1000));
218    }
219
220    /// Get a reference to the initialized card
221    pub fn card(&self) -> Result<&P, Error> {
222        self.card.as_ref().ok_or(Error::NoCard)
223    }
224
225    /// Read a block from the card
226    pub fn read_block(&mut self, blockaddr: u32, block: &mut [u8; 512]) -> Result<(), Error> {
227        let card = self.card()?;
228
229        // Always read 1 block of 512 bytes
230        // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
231        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        // Wait for card to be ready
264        while !self.card_ready()? {}
265
266        Ok(())
267    }
268
269    /// Write a block to card
270    pub fn write_block(&mut self, blockaddr: u32, block: &[u8; 512]) -> Result<(), Error> {
271        let card = self.card()?;
272
273        // Always write 1 block of 512 bytes
274        // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes
275        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        // Wait for SDIO module to finish transmitting data
310        loop {
311            let sta = self.sdio.sta().read();
312            if !sta.txact().bit_is_set() {
313                break;
314            }
315        }
316
317        // Wait for card to finish writing data
318        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        // Block Size up to 2^14 bytes
327        assert!(block_size <= 14);
328
329        // Command AND Data state machines must be idle
330        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        // Data timeout, in bus cycles
348        self.sdio.dtimer().write(|w| w.datatime().set(0xFFFF_FFFF));
349        // Data length, in bytes
350        self.sdio.dlen().write(|w| w.datalength().set(length_bytes));
351        // Transfer
352        self.sdio.dctrl().write(|w| {
353            unsafe {
354                w.dblocksize().bits(block_size);
355            } // 2^n bytes block size
356            w.dtdir().variant(dtdir);
357            w.dten().enabled() // Enable transfer
358        });
359    }
360
361    /// Read the state bits of the status
362    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    /// Check if card is done writing/reading and back in transfer state
372    fn card_ready(&mut self) -> Result<bool, Error> {
373        Ok(self.read_status()?.state() == CurrentState::Transfer)
374    }
375
376    /// Select the card with `address`
377    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    /// Send command to card
392    fn cmd<R: common_cmd::Resp>(&self, cmd: Cmd<R>) -> Result<(), Error> {
393        use crate::pac::sdio::cmd::WAITRESP;
394
395        // Command state machines must be idle
396        while self.sdio.sta().read().cmdact().bit_is_set() {}
397
398        // Clear the interrupts before we start
399        clear_all_interrupts(self.sdio.icr());
400
401        // Command arg
402        self.sdio.arg().write(|w| w.cmdarg().set(cmd.arg));
403
404        // Determine what kind of response the CPSM should wait for
405        let waitresp = match cmd.response_len() {
406            ResponseLen::Zero => WAITRESP::NoResponse,
407            ResponseLen::R48 => WAITRESP::ShortResponse,
408            ResponseLen::R136 => WAITRESP::LongResponse,
409        };
410
411        // Send the command
412        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            // Wait for command sent or a timeout
423            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    /// Initializes card (if present) and sets the bus at the specified frequency.
464    pub fn init(&mut self, freq: ClockFreq) -> Result<(), Error> {
465        // Enable power to card
466        self.power_card(true);
467
468        // Enable clock
469        self.sdio.clkcr().modify(|_, w| w.clken().enabled());
470        // Send card to idle state
471        self.cmd(common_cmd::idle())?;
472
473        // Check if cards supports CMD 8 (with pattern)
474        self.cmd(sd_cmd::send_if_cond(1, 0xAA))?;
475        let cic = CIC::from(self.sdio.resp1().read().bits());
476
477        // If card did't echo back the pattern, we do not have a v2 card
478        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            // Initialize card
488
489            // 3.2-3.3V
490            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                // Still powering up
499                continue;
500            }
501            break ocr;
502        };
503
504        // True for SDHC and SDXC False for SDSC
505        let capacity = if ocr.high_capacity() {
506            CardCapacity::HighCapacity
507        } else {
508            CardCapacity::StandardCapacity
509        };
510
511        // Get CID
512        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        // Get RCA
521        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        // Get CSD
526        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        // Wait before setting the bus witdth and frequency to avoid timeouts on SDSC cards
550        while !self.card_ready()? {}
551
552        self.set_bus(self.bw, freq)?;
553        Ok(())
554    }
555
556    /// Read the SDStatus struct
557    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    /// Get the Card configuration for card at `address`
590    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    /// Set bus width and clock frequency
621    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            // Buswidth8 is not supported for SD cards
629            _ => 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    /// Initializes eMMC device (if present) and sets the bus at the specified frequency. eMMC device must support 512 byte blocks.
645    pub fn init(&mut self, freq: ClockFreq) -> Result<(), Error> {
646        let card_addr: RCA<EMMC> = RCA::from(1u16);
647
648        // Enable power to card
649        self.power_card(true);
650
651        // Enable clock
652        self.sdio.clkcr().modify(|_, w| w.clken().enabled());
653        // Send card to idle state
654        self.cmd(common_cmd::idle())?;
655
656        let ocr = loop {
657            // Initialize card
658
659            // 3.2-3.3V
660            //let voltage_window = 1 << 20;
661            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        // Get CID
673        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        // Wait before setting the bus width and frequency to avoid timeouts on SDSC cards
704        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        // Use access mode 0b11 to write a value of 0x02 to byte 183. Cmd Set is 0 (not used).
714        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        // CMD6 is R1b, so wait for the card to be ready again before proceeding.
727        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    /// Size in blocks
776    pub fn block_count(&self) -> u64 {
777        self.csd.block_count()
778    }
779
780    /// Card supports wide bus
781    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}