diff options
| author | Anton Lazarev <[email protected]> | 2025-03-26 23:26:11 -0700 |
|---|---|---|
| committer | Anton Lazarev <[email protected]> | 2025-03-31 12:47:41 -0700 |
| commit | 0a231505d8225f3f36f39b0be1ded4304fb7ccca (patch) | |
| tree | f9021b5e5622ec84e55ea9fdb32ac5442c42fdb3 /embassy-stm32/src/sdmmc | |
| parent | b92eb948b5de521205e3a8bb81548662c7fc5c1d (diff) | |
support 8 lane data bus
Diffstat (limited to 'embassy-stm32/src/sdmmc')
| -rw-r--r-- | embassy-stm32/src/sdmmc/mod.rs | 162 |
1 files changed, 158 insertions, 4 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index f92c0260b..a0c3573a9 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -145,6 +145,8 @@ pub enum Error { | |||
| 145 | Crc, | 145 | Crc, |
| 146 | /// No card inserted. | 146 | /// No card inserted. |
| 147 | NoCard, | 147 | NoCard, |
| 148 | /// 8-lane buses are not supported for SD cards. | ||
| 149 | BusWidth, | ||
| 148 | /// Bad clock supplied to the SDMMC peripheral. | 150 | /// Bad clock supplied to the SDMMC peripheral. |
| 149 | BadClock, | 151 | BadClock, |
| 150 | /// Signaling switch failed. | 152 | /// Signaling switch failed. |
| @@ -365,6 +367,10 @@ pub struct Sdmmc<'d, T: Instance> { | |||
| 365 | d1: Option<Peri<'d, AnyPin>>, | 367 | d1: Option<Peri<'d, AnyPin>>, |
| 366 | d2: Option<Peri<'d, AnyPin>>, | 368 | d2: Option<Peri<'d, AnyPin>>, |
| 367 | d3: Option<Peri<'d, AnyPin>>, | 369 | d3: Option<Peri<'d, AnyPin>>, |
| 370 | d4: Option<Peri<'d, AnyPin>>, | ||
| 371 | d5: Option<Peri<'d, AnyPin>>, | ||
| 372 | d6: Option<Peri<'d, AnyPin>>, | ||
| 373 | d7: Option<Peri<'d, AnyPin>>, | ||
| 368 | 374 | ||
| 369 | config: Config, | 375 | config: Config, |
| 370 | /// Current clock to card | 376 | /// Current clock to card |
| @@ -413,6 +419,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 413 | None, | 419 | None, |
| 414 | None, | 420 | None, |
| 415 | None, | 421 | None, |
| 422 | None, | ||
| 423 | None, | ||
| 424 | None, | ||
| 425 | None, | ||
| 416 | config, | 426 | config, |
| 417 | ) | 427 | ) |
| 418 | } | 428 | } |
| @@ -448,6 +458,60 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 448 | Some(d1.into()), | 458 | Some(d1.into()), |
| 449 | Some(d2.into()), | 459 | Some(d2.into()), |
| 450 | Some(d3.into()), | 460 | Some(d3.into()), |
| 461 | None, | ||
| 462 | None, | ||
| 463 | None, | ||
| 464 | None, | ||
| 465 | config, | ||
| 466 | ) | ||
| 467 | } | ||
| 468 | } | ||
| 469 | |||
| 470 | #[cfg(sdmmc_v1)] | ||
| 471 | impl<'d, T: Instance> Sdmmc<'d, T> { | ||
| 472 | /// Create a new SDMMC driver, with 8 data lanes. | ||
| 473 | pub fn new_8bit( | ||
| 474 | sdmmc: Peri<'d, T>, | ||
| 475 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||
| 476 | dma: Peri<'d, impl SdmmcDma<T>>, | ||
| 477 | clk: Peri<'d, impl CkPin<T>>, | ||
| 478 | cmd: Peri<'d, impl CmdPin<T>>, | ||
| 479 | d0: Peri<'d, impl D0Pin<T>>, | ||
| 480 | d1: Peri<'d, impl D1Pin<T>>, | ||
| 481 | d2: Peri<'d, impl D2Pin<T>>, | ||
| 482 | d3: Peri<'d, impl D3Pin<T>>, | ||
| 483 | d4: Peri<'d, impl D4Pin<T>>, | ||
| 484 | d5: Peri<'d, impl D5Pin<T>>, | ||
| 485 | d6: Peri<'d, impl D6Pin<T>>, | ||
| 486 | d7: Peri<'d, impl D7Pin<T>>, | ||
| 487 | config: Config, | ||
| 488 | ) -> Self { | ||
| 489 | critical_section::with(|_| { | ||
| 490 | clk.set_as_af(clk.af_num(), CLK_AF); | ||
| 491 | cmd.set_as_af(cmd.af_num(), CMD_AF); | ||
| 492 | d0.set_as_af(d0.af_num(), DATA_AF); | ||
| 493 | d1.set_as_af(d1.af_num(), DATA_AF); | ||
| 494 | d2.set_as_af(d2.af_num(), DATA_AF); | ||
| 495 | d3.set_as_af(d3.af_num(), DATA_AF); | ||
| 496 | d4.set_as_af(d4.af_num(), DATA_AF); | ||
| 497 | d5.set_as_af(d5.af_num(), DATA_AF); | ||
| 498 | d6.set_as_af(d6.af_num(), DATA_AF); | ||
| 499 | d7.set_as_af(d7.af_num(), DATA_AF); | ||
| 500 | }); | ||
| 501 | |||
| 502 | Self::new_inner( | ||
| 503 | sdmmc, | ||
| 504 | new_dma_nonopt!(dma), | ||
| 505 | clk.into(), | ||
| 506 | cmd.into(), | ||
| 507 | d0.into(), | ||
| 508 | Some(d1.into()), | ||
| 509 | Some(d2.into()), | ||
| 510 | Some(d3.into()), | ||
| 511 | Some(d4.into()), | ||
| 512 | Some(d5.into()), | ||
| 513 | Some(d6.into()), | ||
| 514 | Some(d7.into()), | ||
| 451 | config, | 515 | config, |
| 452 | ) | 516 | ) |
| 453 | } | 517 | } |
| @@ -470,7 +534,20 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 470 | d0.set_as_af(d0.af_num(), DATA_AF); | 534 | d0.set_as_af(d0.af_num(), DATA_AF); |
| 471 | }); | 535 | }); |
| 472 | 536 | ||
| 473 | Self::new_inner(sdmmc, clk.into(), cmd.into(), d0.into(), None, None, None, config) | 537 | Self::new_inner( |
| 538 | sdmmc, | ||
| 539 | clk.into(), | ||
| 540 | cmd.into(), | ||
| 541 | d0.into(), | ||
| 542 | None, | ||
| 543 | None, | ||
| 544 | None, | ||
| 545 | None, | ||
| 546 | None, | ||
| 547 | None, | ||
| 548 | None, | ||
| 549 | config, | ||
| 550 | ) | ||
| 474 | } | 551 | } |
| 475 | 552 | ||
| 476 | /// Create a new SDMMC driver, with 4 data lanes. | 553 | /// Create a new SDMMC driver, with 4 data lanes. |
| @@ -502,6 +579,58 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 502 | Some(d1.into()), | 579 | Some(d1.into()), |
| 503 | Some(d2.into()), | 580 | Some(d2.into()), |
| 504 | Some(d3.into()), | 581 | Some(d3.into()), |
| 582 | None, | ||
| 583 | None, | ||
| 584 | None, | ||
| 585 | None, | ||
| 586 | config, | ||
| 587 | ) | ||
| 588 | } | ||
| 589 | } | ||
| 590 | |||
| 591 | #[cfg(sdmmc_v2)] | ||
| 592 | impl<'d, T: Instance> Sdmmc<'d, T> { | ||
| 593 | /// Create a new SDMMC driver, with 8 data lanes. | ||
| 594 | pub fn new_8bit( | ||
| 595 | sdmmc: Peri<'d, T>, | ||
| 596 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | ||
| 597 | clk: Peri<'d, impl CkPin<T>>, | ||
| 598 | cmd: Peri<'d, impl CmdPin<T>>, | ||
| 599 | d0: Peri<'d, impl D0Pin<T>>, | ||
| 600 | d1: Peri<'d, impl D1Pin<T>>, | ||
| 601 | d2: Peri<'d, impl D2Pin<T>>, | ||
| 602 | d3: Peri<'d, impl D3Pin<T>>, | ||
| 603 | d4: Peri<'d, impl D4Pin<T>>, | ||
| 604 | d5: Peri<'d, impl D5Pin<T>>, | ||
| 605 | d6: Peri<'d, impl D6Pin<T>>, | ||
| 606 | d7: Peri<'d, impl D7Pin<T>>, | ||
| 607 | config: Config, | ||
| 608 | ) -> Self { | ||
| 609 | critical_section::with(|_| { | ||
| 610 | clk.set_as_af(clk.af_num(), CLK_AF); | ||
| 611 | cmd.set_as_af(cmd.af_num(), CMD_AF); | ||
| 612 | d0.set_as_af(d0.af_num(), DATA_AF); | ||
| 613 | d1.set_as_af(d1.af_num(), DATA_AF); | ||
| 614 | d2.set_as_af(d2.af_num(), DATA_AF); | ||
| 615 | d3.set_as_af(d3.af_num(), DATA_AF); | ||
| 616 | d4.set_as_af(d4.af_num(), DATA_AF); | ||
| 617 | d5.set_as_af(d5.af_num(), DATA_AF); | ||
| 618 | d6.set_as_af(d6.af_num(), DATA_AF); | ||
| 619 | d7.set_as_af(d7.af_num(), DATA_AF); | ||
| 620 | }); | ||
| 621 | |||
| 622 | Self::new_inner( | ||
| 623 | sdmmc, | ||
| 624 | clk.into(), | ||
| 625 | cmd.into(), | ||
| 626 | d0.into(), | ||
| 627 | Some(d1.into()), | ||
| 628 | Some(d2.into()), | ||
| 629 | Some(d3.into()), | ||
| 630 | Some(d4.into()), | ||
| 631 | Some(d5.into()), | ||
| 632 | Some(d6.into()), | ||
| 633 | Some(d7.into()), | ||
| 505 | config, | 634 | config, |
| 506 | ) | 635 | ) |
| 507 | } | 636 | } |
| @@ -517,6 +646,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 517 | d1: Option<Peri<'d, AnyPin>>, | 646 | d1: Option<Peri<'d, AnyPin>>, |
| 518 | d2: Option<Peri<'d, AnyPin>>, | 647 | d2: Option<Peri<'d, AnyPin>>, |
| 519 | d3: Option<Peri<'d, AnyPin>>, | 648 | d3: Option<Peri<'d, AnyPin>>, |
| 649 | d4: Option<Peri<'d, AnyPin>>, | ||
| 650 | d5: Option<Peri<'d, AnyPin>>, | ||
| 651 | d6: Option<Peri<'d, AnyPin>>, | ||
| 652 | d7: Option<Peri<'d, AnyPin>>, | ||
| 520 | config: Config, | 653 | config: Config, |
| 521 | ) -> Self { | 654 | ) -> Self { |
| 522 | rcc::enable_and_reset::<T>(); | 655 | rcc::enable_and_reset::<T>(); |
| @@ -555,6 +688,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 555 | d1, | 688 | d1, |
| 556 | d2, | 689 | d2, |
| 557 | d3, | 690 | d3, |
| 691 | d4, | ||
| 692 | d5, | ||
| 693 | d6, | ||
| 694 | d7, | ||
| 558 | 695 | ||
| 559 | config, | 696 | config, |
| 560 | clock: SD_INIT_FREQ, | 697 | clock: SD_INIT_FREQ, |
| @@ -1039,6 +1176,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1039 | impl<'d, T: Instance> Sdmmc<'d, T> { | 1176 | impl<'d, T: Instance> Sdmmc<'d, T> { |
| 1040 | /// Initializes card (if present) and sets the bus at the specified frequency. | 1177 | /// Initializes card (if present) and sets the bus at the specified frequency. |
| 1041 | pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> { | 1178 | pub async fn init_card(&mut self, freq: Hertz) -> Result<(), Error> { |
| 1179 | if self.d7.is_some() { | ||
| 1180 | return Err(Error::BusWidth); | ||
| 1181 | } | ||
| 1182 | |||
| 1042 | let regs = T::regs(); | 1183 | let regs = T::regs(); |
| 1043 | let ker_ck = T::frequency(); | 1184 | let ker_ck = T::frequency(); |
| 1044 | 1185 | ||
| @@ -1419,9 +1560,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1419 | let regs = T::regs(); | 1560 | let regs = T::regs(); |
| 1420 | let ker_ck = T::frequency(); | 1561 | let ker_ck = T::frequency(); |
| 1421 | 1562 | ||
| 1422 | let bus_width = match self.d3.is_some() { | 1563 | let bus_width = match (self.d3.is_some(), self.d7.is_some()) { |
| 1423 | true => BusWidth::Four, | 1564 | (true, true) => BusWidth::Eight, |
| 1424 | false => BusWidth::One, | 1565 | (true, false) => BusWidth::Four, |
| 1566 | _ => BusWidth::One, | ||
| 1425 | }; | 1567 | }; |
| 1426 | 1568 | ||
| 1427 | // While the SD/SDIO card or eMMC is in identification mode, | 1569 | // While the SD/SDIO card or eMMC is in identification mode, |
| @@ -1613,6 +1755,18 @@ impl<'d, T: Instance> Drop for Sdmmc<'d, T> { | |||
| 1613 | if let Some(x) = &mut self.d3 { | 1755 | if let Some(x) = &mut self.d3 { |
| 1614 | x.set_as_disconnected(); | 1756 | x.set_as_disconnected(); |
| 1615 | } | 1757 | } |
| 1758 | if let Some(x) = &mut self.d4 { | ||
| 1759 | x.set_as_disconnected(); | ||
| 1760 | } | ||
| 1761 | if let Some(x) = &mut self.d5 { | ||
| 1762 | x.set_as_disconnected(); | ||
| 1763 | } | ||
| 1764 | if let Some(x) = &mut self.d6 { | ||
| 1765 | x.set_as_disconnected(); | ||
| 1766 | } | ||
| 1767 | if let Some(x) = &mut self.d7 { | ||
| 1768 | x.set_as_disconnected(); | ||
| 1769 | } | ||
| 1616 | }); | 1770 | }); |
| 1617 | } | 1771 | } |
| 1618 | } | 1772 | } |
