diff options
| author | xoviat <[email protected]> | 2025-12-09 09:34:50 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-12-09 09:34:50 -0600 |
| commit | 7087ad7d45396e139fcbd710084db0d9dac7ecb8 (patch) | |
| tree | 621e04b09979ef7d96dc459258b596d998f503c6 /embassy-stm32/src | |
| parent | 4f322f4a03d336e90d530045255f46cce93e6252 (diff) | |
type-erase sdmmc
Diffstat (limited to 'embassy-stm32/src')
| -rw-r--r-- | embassy-stm32/src/sdmmc/mod.rs | 394 |
1 files changed, 212 insertions, 182 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 37ef7099f..74a6f13fa 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -9,6 +9,7 @@ use core::task::Poll; | |||
| 9 | 9 | ||
| 10 | use embassy_hal_internal::drop::OnDrop; | 10 | use embassy_hal_internal::drop::OnDrop; |
| 11 | use embassy_hal_internal::{Peri, PeripheralType}; | 11 | use embassy_hal_internal::{Peri, PeripheralType}; |
| 12 | use embassy_sync::mutex::Mutex; | ||
| 12 | use embassy_sync::waitqueue::AtomicWaker; | 13 | use embassy_sync::waitqueue::AtomicWaker; |
| 13 | use sdio_host::common_cmd::{self, Resp, ResponseLen}; | 14 | use sdio_host::common_cmd::{self, Resp, ResponseLen}; |
| 14 | use sdio_host::emmc::{EMMC, ExtCSD}; | 15 | use sdio_host::emmc::{EMMC, ExtCSD}; |
| @@ -22,7 +23,7 @@ use crate::gpio::Pull; | |||
| 22 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; | 23 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; |
| 23 | use crate::interrupt::typelevel::Interrupt; | 24 | use crate::interrupt::typelevel::Interrupt; |
| 24 | use crate::pac::sdmmc::Sdmmc as RegBlock; | 25 | use crate::pac::sdmmc::Sdmmc as RegBlock; |
| 25 | use crate::rcc::{self, RccPeripheral}; | 26 | use crate::rcc::{self, RccInfo, RccPeripheral, SealedRccPeripheral}; |
| 26 | use crate::time::Hertz; | 27 | use crate::time::Hertz; |
| 27 | use crate::{interrupt, peripherals}; | 28 | use crate::{interrupt, peripherals}; |
| 28 | 29 | ||
| @@ -31,28 +32,11 @@ pub struct InterruptHandler<T: Instance> { | |||
| 31 | _phantom: PhantomData<T>, | 32 | _phantom: PhantomData<T>, |
| 32 | } | 33 | } |
| 33 | 34 | ||
| 34 | impl<T: Instance> InterruptHandler<T> { | ||
| 35 | fn enable_interrupts() { | ||
| 36 | let regs = T::regs(); | ||
| 37 | regs.maskr().write(|w| { | ||
| 38 | w.set_dcrcfailie(true); | ||
| 39 | w.set_dtimeoutie(true); | ||
| 40 | w.set_dataendie(true); | ||
| 41 | w.set_dbckendie(true); | ||
| 42 | |||
| 43 | #[cfg(sdmmc_v1)] | ||
| 44 | w.set_stbiterre(true); | ||
| 45 | #[cfg(sdmmc_v2)] | ||
| 46 | w.set_dabortie(true); | ||
| 47 | }); | ||
| 48 | } | ||
| 49 | } | ||
| 50 | |||
| 51 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { | 35 | impl<T: Instance> interrupt::typelevel::Handler<T::Interrupt> for InterruptHandler<T> { |
| 52 | unsafe fn on_interrupt() { | 36 | unsafe fn on_interrupt() { |
| 53 | T::state().wake(); | 37 | T::state().waker.wake(); |
| 54 | let status = T::regs().star().read(); | 38 | let status = T::info().regs.star().read(); |
| 55 | T::regs().maskr().modify(|w| { | 39 | T::info().regs.maskr().modify(|w| { |
| 56 | if status.dcrcfail() { | 40 | if status.dcrcfail() { |
| 57 | w.set_dcrcfailie(false) | 41 | w.set_dcrcfailie(false) |
| 58 | } | 42 | } |
| @@ -379,8 +363,10 @@ impl SdmmcPeripheral { | |||
| 379 | } | 363 | } |
| 380 | 364 | ||
| 381 | /// Sdmmc device | 365 | /// Sdmmc device |
| 382 | pub struct Sdmmc<'d, T: Instance> { | 366 | pub struct Sdmmc<'d> { |
| 383 | _peri: Peri<'d, T>, | 367 | info: &'static Info, |
| 368 | state: &'static State, | ||
| 369 | ker_clk: Hertz, | ||
| 384 | #[cfg(sdmmc_v1)] | 370 | #[cfg(sdmmc_v1)] |
| 385 | dma: ChannelAndRequest<'d>, | 371 | dma: ChannelAndRequest<'d>, |
| 386 | 372 | ||
| @@ -416,9 +402,9 @@ const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh | |||
| 416 | const DATA_AF: AfType = CMD_AF; | 402 | const DATA_AF: AfType = CMD_AF; |
| 417 | 403 | ||
| 418 | #[cfg(sdmmc_v1)] | 404 | #[cfg(sdmmc_v1)] |
| 419 | impl<'d, T: Instance> Sdmmc<'d, T> { | 405 | impl<'d> Sdmmc<'d> { |
| 420 | /// Create a new SDMMC driver, with 1 data lane. | 406 | /// Create a new SDMMC driver, with 1 data lane. |
| 421 | pub fn new_1bit( | 407 | pub fn new_1bit<T: Instance>( |
| 422 | sdmmc: Peri<'d, T>, | 408 | sdmmc: Peri<'d, T>, |
| 423 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 409 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 424 | dma: Peri<'d, impl SdmmcDma<T>>, | 410 | dma: Peri<'d, impl SdmmcDma<T>>, |
| @@ -451,7 +437,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 451 | } | 437 | } |
| 452 | 438 | ||
| 453 | /// Create a new SDMMC driver, with 4 data lanes. | 439 | /// Create a new SDMMC driver, with 4 data lanes. |
| 454 | pub fn new_4bit( | 440 | pub fn new_4bit<T: Instance>( |
| 455 | sdmmc: Peri<'d, T>, | 441 | sdmmc: Peri<'d, T>, |
| 456 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 442 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 457 | dma: Peri<'d, impl SdmmcDma<T>>, | 443 | dma: Peri<'d, impl SdmmcDma<T>>, |
| @@ -491,9 +477,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 491 | } | 477 | } |
| 492 | 478 | ||
| 493 | #[cfg(sdmmc_v1)] | 479 | #[cfg(sdmmc_v1)] |
| 494 | impl<'d, T: Instance> Sdmmc<'d, T> { | 480 | impl<'d> Sdmmc<'d> { |
| 495 | /// Create a new SDMMC driver, with 8 data lanes. | 481 | /// Create a new SDMMC driver, with 8 data lanes. |
| 496 | pub fn new_8bit( | 482 | pub fn new_8bit<T: Instance>( |
| 497 | sdmmc: Peri<'d, T>, | 483 | sdmmc: Peri<'d, T>, |
| 498 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 484 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 499 | dma: Peri<'d, impl SdmmcDma<T>>, | 485 | dma: Peri<'d, impl SdmmcDma<T>>, |
| @@ -541,9 +527,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 541 | } | 527 | } |
| 542 | 528 | ||
| 543 | #[cfg(sdmmc_v2)] | 529 | #[cfg(sdmmc_v2)] |
| 544 | impl<'d, T: Instance> Sdmmc<'d, T> { | 530 | impl<'d> Sdmmc<'d> { |
| 545 | /// Create a new SDMMC driver, with 1 data lane. | 531 | /// Create a new SDMMC driver, with 1 data lane. |
| 546 | pub fn new_1bit( | 532 | pub fn new_1bit<T: Instance>( |
| 547 | sdmmc: Peri<'d, T>, | 533 | sdmmc: Peri<'d, T>, |
| 548 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 534 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 549 | clk: Peri<'d, impl CkPin<T>>, | 535 | clk: Peri<'d, impl CkPin<T>>, |
| @@ -574,7 +560,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 574 | } | 560 | } |
| 575 | 561 | ||
| 576 | /// Create a new SDMMC driver, with 4 data lanes. | 562 | /// Create a new SDMMC driver, with 4 data lanes. |
| 577 | pub fn new_4bit( | 563 | pub fn new_4bit<T: Instance>( |
| 578 | sdmmc: Peri<'d, T>, | 564 | sdmmc: Peri<'d, T>, |
| 579 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 565 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 580 | clk: Peri<'d, impl CkPin<T>>, | 566 | clk: Peri<'d, impl CkPin<T>>, |
| @@ -612,9 +598,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 612 | } | 598 | } |
| 613 | 599 | ||
| 614 | #[cfg(sdmmc_v2)] | 600 | #[cfg(sdmmc_v2)] |
| 615 | impl<'d, T: Instance> Sdmmc<'d, T> { | 601 | impl<'d> Sdmmc<'d> { |
| 616 | /// Create a new SDMMC driver, with 8 data lanes. | 602 | /// Create a new SDMMC driver, with 8 data lanes. |
| 617 | pub fn new_8bit( | 603 | pub fn new_8bit<T: Instance>( |
| 618 | sdmmc: Peri<'d, T>, | 604 | sdmmc: Peri<'d, T>, |
| 619 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 605 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 620 | clk: Peri<'d, impl CkPin<T>>, | 606 | clk: Peri<'d, impl CkPin<T>>, |
| @@ -659,9 +645,24 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 659 | } | 645 | } |
| 660 | } | 646 | } |
| 661 | 647 | ||
| 662 | impl<'d, T: Instance> Sdmmc<'d, T> { | 648 | impl<'d> Sdmmc<'d> { |
| 663 | fn new_inner( | 649 | fn enable_interrupts(&self) { |
| 664 | sdmmc: Peri<'d, T>, | 650 | let regs = self.info.regs; |
| 651 | regs.maskr().write(|w| { | ||
| 652 | w.set_dcrcfailie(true); | ||
| 653 | w.set_dtimeoutie(true); | ||
| 654 | w.set_dataendie(true); | ||
| 655 | w.set_dbckendie(true); | ||
| 656 | |||
| 657 | #[cfg(sdmmc_v1)] | ||
| 658 | w.set_stbiterre(true); | ||
| 659 | #[cfg(sdmmc_v2)] | ||
| 660 | w.set_dabortie(true); | ||
| 661 | }); | ||
| 662 | } | ||
| 663 | |||
| 664 | fn new_inner<T: Instance>( | ||
| 665 | _sdmmc: Peri<'d, T>, | ||
| 665 | #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>, | 666 | #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>, |
| 666 | clk: Peri<'d, AnyPin>, | 667 | clk: Peri<'d, AnyPin>, |
| 667 | cmd: Peri<'d, AnyPin>, | 668 | cmd: Peri<'d, AnyPin>, |
| @@ -680,8 +681,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 680 | T::Interrupt::unpend(); | 681 | T::Interrupt::unpend(); |
| 681 | unsafe { T::Interrupt::enable() }; | 682 | unsafe { T::Interrupt::enable() }; |
| 682 | 683 | ||
| 683 | let regs = T::regs(); | 684 | let info = T::info(); |
| 684 | regs.clkcr().write(|w| { | 685 | let state = T::state(); |
| 686 | let ker_clk = T::frequency(); | ||
| 687 | |||
| 688 | info.regs.clkcr().write(|w| { | ||
| 685 | w.set_pwrsav(false); | 689 | w.set_pwrsav(false); |
| 686 | w.set_negedge(false); | 690 | w.set_negedge(false); |
| 687 | 691 | ||
| @@ -698,10 +702,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 698 | 702 | ||
| 699 | // Power off, writen 00: Clock to the card is stopped; | 703 | // Power off, writen 00: Clock to the card is stopped; |
| 700 | // D[7:0], CMD, and CK are driven high. | 704 | // D[7:0], CMD, and CK are driven high. |
| 701 | regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); | 705 | info.regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::Off as u8)); |
| 702 | 706 | ||
| 703 | Self { | 707 | Self { |
| 704 | _peri: sdmmc, | 708 | info, |
| 709 | state, | ||
| 710 | ker_clk, | ||
| 705 | #[cfg(sdmmc_v1)] | 711 | #[cfg(sdmmc_v1)] |
| 706 | dma, | 712 | dma, |
| 707 | 713 | ||
| @@ -726,8 +732,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 726 | 732 | ||
| 727 | /// Data transfer is in progress | 733 | /// Data transfer is in progress |
| 728 | #[inline] | 734 | #[inline] |
| 729 | fn data_active() -> bool { | 735 | fn data_active(&self) -> bool { |
| 730 | let regs = T::regs(); | 736 | let regs = self.info.regs; |
| 731 | 737 | ||
| 732 | let status = regs.star().read(); | 738 | let status = regs.star().read(); |
| 733 | #[cfg(sdmmc_v1)] | 739 | #[cfg(sdmmc_v1)] |
| @@ -738,8 +744,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 738 | 744 | ||
| 739 | /// Coammand transfer is in progress | 745 | /// Coammand transfer is in progress |
| 740 | #[inline] | 746 | #[inline] |
| 741 | fn cmd_active() -> bool { | 747 | fn cmd_active(&self) -> bool { |
| 742 | let regs = T::regs(); | 748 | let regs = self.info.regs; |
| 743 | 749 | ||
| 744 | let status = regs.star().read(); | 750 | let status = regs.star().read(); |
| 745 | #[cfg(sdmmc_v1)] | 751 | #[cfg(sdmmc_v1)] |
| @@ -750,8 +756,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 750 | 756 | ||
| 751 | /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) | 757 | /// Wait idle on CMDACT, RXACT and TXACT (v1) or DOSNACT and CPSMACT (v2) |
| 752 | #[inline] | 758 | #[inline] |
| 753 | fn wait_idle() { | 759 | fn wait_idle(&self) { |
| 754 | while Self::data_active() || Self::cmd_active() {} | 760 | while self.data_active() || self.cmd_active() {} |
| 755 | } | 761 | } |
| 756 | 762 | ||
| 757 | /// # Safety | 763 | /// # Safety |
| @@ -759,6 +765,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 759 | /// `buffer` must be valid for the whole transfer and word aligned | 765 | /// `buffer` must be valid for the whole transfer and word aligned |
| 760 | #[allow(unused_variables)] | 766 | #[allow(unused_variables)] |
| 761 | fn prepare_datapath_read<'a>( | 767 | fn prepare_datapath_read<'a>( |
| 768 | &self, | ||
| 762 | config: &Config, | 769 | config: &Config, |
| 763 | #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>, | 770 | #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>, |
| 764 | buffer: &'a mut [u32], | 771 | buffer: &'a mut [u32], |
| @@ -766,11 +773,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 766 | block_size: u8, | 773 | block_size: u8, |
| 767 | ) -> Transfer<'a> { | 774 | ) -> Transfer<'a> { |
| 768 | assert!(block_size <= 14, "Block size up to 2^14 bytes"); | 775 | assert!(block_size <= 14, "Block size up to 2^14 bytes"); |
| 769 | let regs = T::regs(); | 776 | let regs = self.info.regs; |
| 770 | 777 | ||
| 771 | // Command AND Data state machines must be idle | 778 | // Command AND Data state machines must be idle |
| 772 | Self::wait_idle(); | 779 | self.wait_idle(); |
| 773 | Self::clear_interrupt_flags(); | 780 | self.clear_interrupt_flags(); |
| 774 | 781 | ||
| 775 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); | 782 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); |
| 776 | 783 | ||
| @@ -801,13 +808,13 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 801 | /// # Safety | 808 | /// # Safety |
| 802 | /// | 809 | /// |
| 803 | /// `buffer` must be valid for the whole transfer and word aligned | 810 | /// `buffer` must be valid for the whole transfer and word aligned |
| 804 | fn prepare_datapath_write<'a>(&'a mut self, buffer: &'a [u32], length_bytes: u32, block_size: u8) -> Transfer<'a> { | 811 | fn prepare_datapath_write<'a>(&self, buffer: &'a [u32], length_bytes: u32, block_size: u8) -> Transfer<'a> { |
| 805 | assert!(block_size <= 14, "Block size up to 2^14 bytes"); | 812 | assert!(block_size <= 14, "Block size up to 2^14 bytes"); |
| 806 | let regs = T::regs(); | 813 | let regs = self.info.regs; |
| 807 | 814 | ||
| 808 | // Command AND Data state machines must be idle | 815 | // Command AND Data state machines must be idle |
| 809 | Self::wait_idle(); | 816 | self.wait_idle(); |
| 810 | Self::clear_interrupt_flags(); | 817 | self.clear_interrupt_flags(); |
| 811 | 818 | ||
| 812 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); | 819 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); |
| 813 | 820 | ||
| @@ -839,8 +846,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 839 | } | 846 | } |
| 840 | 847 | ||
| 841 | /// Stops the DMA datapath | 848 | /// Stops the DMA datapath |
| 842 | fn stop_datapath() { | 849 | fn stop_datapath(&self) { |
| 843 | let regs = T::regs(); | 850 | let regs = self.info.regs; |
| 844 | 851 | ||
| 845 | #[cfg(sdmmc_v1)] | 852 | #[cfg(sdmmc_v1)] |
| 846 | regs.dctrl().modify(|w| { | 853 | regs.dctrl().modify(|w| { |
| @@ -853,7 +860,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 853 | 860 | ||
| 854 | /// Sets the CLKDIV field in CLKCR. Updates clock field in self | 861 | /// Sets the CLKDIV field in CLKCR. Updates clock field in self |
| 855 | fn clkcr_set_clkdiv(&mut self, freq: u32, width: BusWidth) -> Result<(), Error> { | 862 | fn clkcr_set_clkdiv(&mut self, freq: u32, width: BusWidth) -> Result<(), Error> { |
| 856 | let regs = T::regs(); | 863 | let regs = self.info.regs; |
| 857 | 864 | ||
| 858 | let width_u32 = match width { | 865 | let width_u32 = match width { |
| 859 | BusWidth::One => 1u32, | 866 | BusWidth::One => 1u32, |
| @@ -862,17 +869,16 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 862 | _ => panic!("Invalid Bus Width"), | 869 | _ => panic!("Invalid Bus Width"), |
| 863 | }; | 870 | }; |
| 864 | 871 | ||
| 865 | let ker_ck = T::frequency(); | 872 | let (_bypass, clkdiv, new_clock) = clk_div(self.ker_clk, freq)?; |
| 866 | let (_bypass, clkdiv, new_clock) = clk_div(ker_ck, freq)?; | ||
| 867 | 873 | ||
| 868 | // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 | 874 | // Enforce AHB and SDMMC_CK clock relation. See RM0433 Rev 7 |
| 869 | // Section 55.5.8 | 875 | // Section 55.5.8 |
| 870 | let sdmmc_bus_bandwidth = new_clock.0 * width_u32; | 876 | let sdmmc_bus_bandwidth = new_clock.0 * width_u32; |
| 871 | assert!(ker_ck.0 > 3 * sdmmc_bus_bandwidth / 32); | 877 | assert!(self.ker_clk.0 > 3 * sdmmc_bus_bandwidth / 32); |
| 872 | self.clock = new_clock; | 878 | self.clock = new_clock; |
| 873 | 879 | ||
| 874 | // CPSMACT and DPSMACT must be 0 to set CLKDIV | 880 | // CPSMACT and DPSMACT must be 0 to set CLKDIV |
| 875 | Self::wait_idle(); | 881 | self.wait_idle(); |
| 876 | regs.clkcr().modify(|w| { | 882 | regs.clkcr().modify(|w| { |
| 877 | w.set_clkdiv(clkdiv); | 883 | w.set_clkdiv(clkdiv); |
| 878 | #[cfg(sdmmc_v1)] | 884 | #[cfg(sdmmc_v1)] |
| @@ -887,10 +893,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 887 | where | 893 | where |
| 888 | CardStatus<Ext>: From<u32>, | 894 | CardStatus<Ext>: From<u32>, |
| 889 | { | 895 | { |
| 890 | let regs = T::regs(); | 896 | let regs = self.info.regs; |
| 891 | let rca = card.get_address(); | 897 | let rca = card.get_address(); |
| 892 | 898 | ||
| 893 | Self::cmd(common_cmd::card_status(rca, false), false)?; // CMD13 | 899 | self.cmd(common_cmd::card_status(rca, false), false)?; // CMD13 |
| 894 | 900 | ||
| 895 | let r1 = regs.respr(0).read().cardstatus(); | 901 | let r1 = regs.respr(0).read().cardstatus(); |
| 896 | Ok(r1.into()) | 902 | Ok(r1.into()) |
| @@ -904,7 +910,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 904 | // Determine Relative Card Address (RCA) of given card | 910 | // Determine Relative Card Address (RCA) of given card |
| 905 | let rca = rca.unwrap_or(0); | 911 | let rca = rca.unwrap_or(0); |
| 906 | 912 | ||
| 907 | let r = Self::cmd(common_cmd::select_card(rca), false); | 913 | let r = self.cmd(common_cmd::select_card(rca), false); |
| 908 | match (r, rca) { | 914 | match (r, rca) { |
| 909 | (Err(Error::Timeout), 0) => Ok(()), | 915 | (Err(Error::Timeout), 0) => Ok(()), |
| 910 | _ => r, | 916 | _ => r, |
| @@ -913,8 +919,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 913 | 919 | ||
| 914 | /// Clear flags in interrupt clear register | 920 | /// Clear flags in interrupt clear register |
| 915 | #[inline] | 921 | #[inline] |
| 916 | fn clear_interrupt_flags() { | 922 | fn clear_interrupt_flags(&self) { |
| 917 | let regs = T::regs(); | 923 | let regs = self.info.regs; |
| 918 | regs.icr().write(|w| { | 924 | regs.icr().write(|w| { |
| 919 | w.set_ccrcfailc(true); | 925 | w.set_ccrcfailc(true); |
| 920 | w.set_dcrcfailc(true); | 926 | w.set_dcrcfailc(true); |
| @@ -947,12 +953,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 947 | 953 | ||
| 948 | /// Send command to card | 954 | /// Send command to card |
| 949 | #[allow(unused_variables)] | 955 | #[allow(unused_variables)] |
| 950 | fn cmd<R: Resp>(cmd: Cmd<R>, data: bool) -> Result<(), Error> { | 956 | fn cmd<R: Resp>(&self, cmd: Cmd<R>, data: bool) -> Result<(), Error> { |
| 951 | let regs = T::regs(); | 957 | let regs = self.info.regs; |
| 952 | 958 | ||
| 953 | Self::clear_interrupt_flags(); | 959 | self.clear_interrupt_flags(); |
| 954 | // CP state machine must be idle | 960 | // CP state machine must be idle |
| 955 | while Self::cmd_active() {} | 961 | while self.cmd_active() {} |
| 956 | 962 | ||
| 957 | // Command arg | 963 | // Command arg |
| 958 | regs.argr().write(|w| w.set_cmdarg(cmd.arg)); | 964 | regs.argr().write(|w| w.set_cmdarg(cmd.arg)); |
| @@ -997,13 +1003,13 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 997 | Ok(()) | 1003 | Ok(()) |
| 998 | } | 1004 | } |
| 999 | 1005 | ||
| 1000 | fn on_drop() { | 1006 | fn on_drop(&self) { |
| 1001 | let regs = T::regs(); | 1007 | let regs = self.info.regs; |
| 1002 | if Self::data_active() { | 1008 | if self.data_active() { |
| 1003 | Self::clear_interrupt_flags(); | 1009 | self.clear_interrupt_flags(); |
| 1004 | // Send abort | 1010 | // Send abort |
| 1005 | // CP state machine must be idle | 1011 | // CP state machine must be idle |
| 1006 | while Self::cmd_active() {} | 1012 | while self.cmd_active() {} |
| 1007 | 1013 | ||
| 1008 | // Command arg | 1014 | // Command arg |
| 1009 | regs.argr().write(|w| w.set_cmdarg(0)); | 1015 | regs.argr().write(|w| w.set_cmdarg(0)); |
| @@ -1023,22 +1029,22 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1023 | }); | 1029 | }); |
| 1024 | 1030 | ||
| 1025 | // Wait for the abort | 1031 | // Wait for the abort |
| 1026 | while Self::data_active() {} | 1032 | while self.data_active() {} |
| 1027 | } | 1033 | } |
| 1028 | regs.maskr().write(|_| ()); // disable irqs | 1034 | regs.maskr().write(|_| ()); // disable irqs |
| 1029 | Self::clear_interrupt_flags(); | 1035 | self.clear_interrupt_flags(); |
| 1030 | Self::stop_datapath(); | 1036 | self.stop_datapath(); |
| 1031 | } | 1037 | } |
| 1032 | 1038 | ||
| 1033 | /// Wait for a previously started datapath transfer to complete from an interrupt. | 1039 | /// Wait for a previously started datapath transfer to complete from an interrupt. |
| 1034 | #[inline] | 1040 | #[inline] |
| 1035 | #[allow(unused)] | 1041 | #[allow(unused)] |
| 1036 | async fn complete_datapath_transfer(block: bool) -> Result<(), Error> { | 1042 | async fn complete_datapath_transfer(&self, block: bool) -> Result<(), Error> { |
| 1037 | let res = poll_fn(|cx| { | 1043 | let res = poll_fn(|cx| { |
| 1038 | // Compiler might not be sufficiently constrained here | 1044 | // Compiler might not be sufficiently constrained here |
| 1039 | // https://github.com/embassy-rs/embassy/issues/4723 | 1045 | // https://github.com/embassy-rs/embassy/issues/4723 |
| 1040 | T::state().register(cx.waker()); | 1046 | self.state.waker.register(cx.waker()); |
| 1041 | let status = T::regs().star().read(); | 1047 | let status = self.info.regs.star().read(); |
| 1042 | 1048 | ||
| 1043 | if status.dcrcfail() { | 1049 | if status.dcrcfail() { |
| 1044 | return Poll::Ready(Err(Error::Crc)); | 1050 | return Poll::Ready(Err(Error::Crc)); |
| @@ -1067,7 +1073,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1067 | }) | 1073 | }) |
| 1068 | .await; | 1074 | .await; |
| 1069 | 1075 | ||
| 1070 | Self::clear_interrupt_flags(); | 1076 | self.clear_interrupt_flags(); |
| 1071 | 1077 | ||
| 1072 | res | 1078 | res |
| 1073 | } | 1079 | } |
| @@ -1075,7 +1081,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1075 | /// Read a data block. | 1081 | /// Read a data block. |
| 1076 | #[inline] | 1082 | #[inline] |
| 1077 | pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> { | 1083 | pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> { |
| 1078 | let _scoped_block_stop = T::RCC_INFO.block_stop(); | 1084 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1079 | let card_capacity = self.card()?.get_capacity(); | 1085 | let card_capacity = self.card()?.get_capacity(); |
| 1080 | 1086 | ||
| 1081 | // NOTE(unsafe) DataBlock uses align 4 | 1087 | // NOTE(unsafe) DataBlock uses align 4 |
| @@ -1087,11 +1093,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1087 | CardCapacity::StandardCapacity => block_idx * 512, | 1093 | CardCapacity::StandardCapacity => block_idx * 512, |
| 1088 | _ => block_idx, | 1094 | _ => block_idx, |
| 1089 | }; | 1095 | }; |
| 1090 | Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16 | 1096 | self.cmd(common_cmd::set_block_length(512), false)?; // CMD16 |
| 1091 | 1097 | ||
| 1092 | let on_drop = OnDrop::new(|| Self::on_drop()); | 1098 | let on_drop = OnDrop::new(|| self.on_drop()); |
| 1093 | 1099 | ||
| 1094 | let transfer = Self::prepare_datapath_read( | 1100 | let transfer = self.prepare_datapath_read( |
| 1095 | &self.config, | 1101 | &self.config, |
| 1096 | #[cfg(sdmmc_v1)] | 1102 | #[cfg(sdmmc_v1)] |
| 1097 | &mut self.dma, | 1103 | &mut self.dma, |
| @@ -1099,14 +1105,14 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1099 | 512, | 1105 | 512, |
| 1100 | 9, | 1106 | 9, |
| 1101 | ); | 1107 | ); |
| 1102 | InterruptHandler::<T>::enable_interrupts(); | 1108 | self.enable_interrupts(); |
| 1103 | Self::cmd(common_cmd::read_single_block(address), true)?; | 1109 | self.cmd(common_cmd::read_single_block(address), true)?; |
| 1104 | 1110 | ||
| 1105 | let res = Self::complete_datapath_transfer(true).await; | 1111 | let res = self.complete_datapath_transfer(true).await; |
| 1106 | 1112 | ||
| 1107 | if res.is_ok() { | 1113 | if res.is_ok() { |
| 1108 | on_drop.defuse(); | 1114 | on_drop.defuse(); |
| 1109 | Self::stop_datapath(); | 1115 | self.stop_datapath(); |
| 1110 | drop(transfer); | 1116 | drop(transfer); |
| 1111 | } | 1117 | } |
| 1112 | res | 1118 | res |
| @@ -1115,7 +1121,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1115 | /// Read multiple data blocks. | 1121 | /// Read multiple data blocks. |
| 1116 | #[inline] | 1122 | #[inline] |
| 1117 | pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> { | 1123 | pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> { |
| 1118 | let _scoped_block_stop = T::RCC_INFO.block_stop(); | 1124 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1119 | let card_capacity = self.card()?.get_capacity(); | 1125 | let card_capacity = self.card()?.get_capacity(); |
| 1120 | 1126 | ||
| 1121 | // NOTE(unsafe) reinterpret buffer as &mut [u32] | 1127 | // NOTE(unsafe) reinterpret buffer as &mut [u32] |
| @@ -1131,11 +1137,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1131 | CardCapacity::StandardCapacity => block_idx * 512, | 1137 | CardCapacity::StandardCapacity => block_idx * 512, |
| 1132 | _ => block_idx, | 1138 | _ => block_idx, |
| 1133 | }; | 1139 | }; |
| 1134 | Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16 | 1140 | self.cmd(common_cmd::set_block_length(512), false)?; // CMD16 |
| 1135 | 1141 | ||
| 1136 | let on_drop = OnDrop::new(|| Self::on_drop()); | 1142 | let on_drop = OnDrop::new(|| self.on_drop()); |
| 1137 | 1143 | ||
| 1138 | let transfer = Self::prepare_datapath_read( | 1144 | let transfer = self.prepare_datapath_read( |
| 1139 | &self.config, | 1145 | &self.config, |
| 1140 | #[cfg(sdmmc_v1)] | 1146 | #[cfg(sdmmc_v1)] |
| 1141 | &mut self.dma, | 1147 | &mut self.dma, |
| @@ -1143,18 +1149,18 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1143 | 512 * blocks.len() as u32, | 1149 | 512 * blocks.len() as u32, |
| 1144 | 9, | 1150 | 9, |
| 1145 | ); | 1151 | ); |
| 1146 | InterruptHandler::<T>::enable_interrupts(); | 1152 | self.enable_interrupts(); |
| 1147 | 1153 | ||
| 1148 | Self::cmd(common_cmd::read_multiple_blocks(address), true)?; | 1154 | self.cmd(common_cmd::read_multiple_blocks(address), true)?; |
| 1149 | 1155 | ||
| 1150 | let res = Self::complete_datapath_transfer(false).await; | 1156 | let res = self.complete_datapath_transfer(false).await; |
| 1151 | 1157 | ||
| 1152 | Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12 | 1158 | self.cmd(common_cmd::stop_transmission(), false)?; // CMD12 |
| 1153 | Self::clear_interrupt_flags(); | 1159 | self.clear_interrupt_flags(); |
| 1154 | 1160 | ||
| 1155 | if res.is_ok() { | 1161 | if res.is_ok() { |
| 1156 | on_drop.defuse(); | 1162 | on_drop.defuse(); |
| 1157 | Self::stop_datapath(); | 1163 | self.stop_datapath(); |
| 1158 | drop(transfer); | 1164 | drop(transfer); |
| 1159 | } | 1165 | } |
| 1160 | res | 1166 | res |
| @@ -1162,7 +1168,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1162 | 1168 | ||
| 1163 | /// Write a data block. | 1169 | /// Write a data block. |
| 1164 | pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { | 1170 | pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { |
| 1165 | let _scoped_block_stop = T::RCC_INFO.block_stop(); | 1171 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1166 | let card = self.card.as_mut().ok_or(Error::NoCard)?; | 1172 | let card = self.card.as_mut().ok_or(Error::NoCard)?; |
| 1167 | 1173 | ||
| 1168 | // NOTE(unsafe) DataBlock uses align 4 | 1174 | // NOTE(unsafe) DataBlock uses align 4 |
| @@ -1174,26 +1180,26 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1174 | CardCapacity::StandardCapacity => block_idx * 512, | 1180 | CardCapacity::StandardCapacity => block_idx * 512, |
| 1175 | _ => block_idx, | 1181 | _ => block_idx, |
| 1176 | }; | 1182 | }; |
| 1177 | Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16 | 1183 | self.cmd(common_cmd::set_block_length(512), false)?; // CMD16 |
| 1178 | 1184 | ||
| 1179 | let on_drop = OnDrop::new(|| Self::on_drop()); | 1185 | let on_drop = OnDrop::new(|| self.on_drop()); |
| 1180 | 1186 | ||
| 1181 | // sdmmc_v1 uses different cmd/dma order than v2, but only for writes | 1187 | // sdmmc_v1 uses different cmd/dma order than v2, but only for writes |
| 1182 | #[cfg(sdmmc_v1)] | 1188 | #[cfg(sdmmc_v1)] |
| 1183 | Self::cmd(common_cmd::write_single_block(address), true)?; | 1189 | self.cmd(common_cmd::write_single_block(address), true)?; |
| 1184 | 1190 | ||
| 1185 | let transfer = self.prepare_datapath_write(buffer, 512, 9); | 1191 | let transfer = self.prepare_datapath_write(buffer, 512, 9); |
| 1186 | InterruptHandler::<T>::enable_interrupts(); | 1192 | self.enable_interrupts(); |
| 1187 | 1193 | ||
| 1188 | #[cfg(sdmmc_v2)] | 1194 | #[cfg(sdmmc_v2)] |
| 1189 | Self::cmd(common_cmd::write_single_block(address), true)?; | 1195 | self.cmd(common_cmd::write_single_block(address), true)?; |
| 1190 | 1196 | ||
| 1191 | let res = Self::complete_datapath_transfer(true).await; | 1197 | let res = self.complete_datapath_transfer(true).await; |
| 1192 | 1198 | ||
| 1193 | match res { | 1199 | match res { |
| 1194 | Ok(_) => { | 1200 | Ok(_) => { |
| 1195 | on_drop.defuse(); | 1201 | on_drop.defuse(); |
| 1196 | Self::stop_datapath(); | 1202 | self.stop_datapath(); |
| 1197 | drop(transfer); | 1203 | drop(transfer); |
| 1198 | 1204 | ||
| 1199 | // TODO: Make this configurable | 1205 | // TODO: Make this configurable |
| @@ -1219,7 +1225,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1219 | 1225 | ||
| 1220 | /// Write multiple data blocks. | 1226 | /// Write multiple data blocks. |
| 1221 | pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error> { | 1227 | pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error> { |
| 1222 | let _scoped_block_stop = T::RCC_INFO.block_stop(); | 1228 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1223 | let card = self.card.as_mut().ok_or(Error::NoCard)?; | 1229 | let card = self.card.as_mut().ok_or(Error::NoCard)?; |
| 1224 | 1230 | ||
| 1225 | // NOTE(unsafe) reinterpret buffer as &[u32] | 1231 | // NOTE(unsafe) reinterpret buffer as &[u32] |
| @@ -1236,31 +1242,31 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1236 | _ => block_idx, | 1242 | _ => block_idx, |
| 1237 | }; | 1243 | }; |
| 1238 | 1244 | ||
| 1239 | Self::cmd(common_cmd::set_block_length(512), false)?; // CMD16 | 1245 | self.cmd(common_cmd::set_block_length(512), false)?; // CMD16 |
| 1240 | 1246 | ||
| 1241 | let block_count = blocks.len(); | 1247 | let block_count = blocks.len(); |
| 1242 | 1248 | ||
| 1243 | let on_drop = OnDrop::new(|| Self::on_drop()); | 1249 | let on_drop = OnDrop::new(|| self.on_drop()); |
| 1244 | 1250 | ||
| 1245 | #[cfg(sdmmc_v1)] | 1251 | #[cfg(sdmmc_v1)] |
| 1246 | Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25 | 1252 | self.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25 |
| 1247 | 1253 | ||
| 1248 | // Setup write command | 1254 | // Setup write command |
| 1249 | let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9); | 1255 | let transfer = self.prepare_datapath_write(buffer, 512 * block_count as u32, 9); |
| 1250 | InterruptHandler::<T>::enable_interrupts(); | 1256 | self.enable_interrupts(); |
| 1251 | 1257 | ||
| 1252 | #[cfg(sdmmc_v2)] | 1258 | #[cfg(sdmmc_v2)] |
| 1253 | Self::cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25 | 1259 | self.cmd(common_cmd::write_multiple_blocks(address), true)?; // CMD25 |
| 1254 | 1260 | ||
| 1255 | let res = Self::complete_datapath_transfer(false).await; | 1261 | let res = self.complete_datapath_transfer(false).await; |
| 1256 | 1262 | ||
| 1257 | Self::cmd(common_cmd::stop_transmission(), false)?; // CMD12 | 1263 | self.cmd(common_cmd::stop_transmission(), false)?; // CMD12 |
| 1258 | Self::clear_interrupt_flags(); | 1264 | self.clear_interrupt_flags(); |
| 1259 | 1265 | ||
| 1260 | match res { | 1266 | match res { |
| 1261 | Ok(_) => { | 1267 | Ok(_) => { |
| 1262 | on_drop.defuse(); | 1268 | on_drop.defuse(); |
| 1263 | Self::stop_datapath(); | 1269 | self.stop_datapath(); |
| 1264 | drop(transfer); | 1270 | drop(transfer); |
| 1265 | 1271 | ||
| 1266 | // TODO: Make this configurable | 1272 | // TODO: Make this configurable |
| @@ -1306,8 +1312,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1306 | } | 1312 | } |
| 1307 | 1313 | ||
| 1308 | async fn init_internal(&mut self, freq: Hertz, mut card: SdmmcPeripheral) -> Result<(), Error> { | 1314 | async fn init_internal(&mut self, freq: Hertz, mut card: SdmmcPeripheral) -> Result<(), Error> { |
| 1309 | let regs = T::regs(); | 1315 | let regs = self.info.regs; |
| 1310 | let ker_ck = T::frequency(); | ||
| 1311 | 1316 | ||
| 1312 | let bus_width = match (self.d3.is_some(), self.d7.is_some()) { | 1317 | let bus_width = match (self.d3.is_some(), self.d7.is_some()) { |
| 1313 | (true, true) => { | 1318 | (true, true) => { |
| @@ -1322,11 +1327,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1322 | 1327 | ||
| 1323 | // While the SD/SDIO card or eMMC is in identification mode, | 1328 | // While the SD/SDIO card or eMMC is in identification mode, |
| 1324 | // the SDMMC_CK frequency must be no more than 400 kHz. | 1329 | // the SDMMC_CK frequency must be no more than 400 kHz. |
| 1325 | let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(ker_ck, SD_INIT_FREQ.0)); | 1330 | let (_bypass, clkdiv, init_clock) = unwrap!(clk_div(self.ker_clk, SD_INIT_FREQ.0)); |
| 1326 | self.clock = init_clock; | 1331 | self.clock = init_clock; |
| 1327 | 1332 | ||
| 1328 | // CPSMACT and DPSMACT must be 0 to set WIDBUS | 1333 | // CPSMACT and DPSMACT must be 0 to set WIDBUS |
| 1329 | Self::wait_idle(); | 1334 | self.wait_idle(); |
| 1330 | 1335 | ||
| 1331 | regs.clkcr().modify(|w| { | 1336 | regs.clkcr().modify(|w| { |
| 1332 | w.set_widbus(0); | 1337 | w.set_widbus(0); |
| @@ -1338,12 +1343,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1338 | .write(|w| w.set_datatime(self.config.data_transfer_timeout)); | 1343 | .write(|w| w.set_datatime(self.config.data_transfer_timeout)); |
| 1339 | 1344 | ||
| 1340 | regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); | 1345 | regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); |
| 1341 | Self::cmd(common_cmd::idle(), false)?; | 1346 | self.cmd(common_cmd::idle(), false)?; |
| 1342 | 1347 | ||
| 1343 | match card { | 1348 | match card { |
| 1344 | SdmmcPeripheral::SdCard(ref mut card) => { | 1349 | SdmmcPeripheral::SdCard(ref mut card) => { |
| 1345 | // Check if cards supports CMD8 (with pattern) | 1350 | // Check if cards supports CMD8 (with pattern) |
| 1346 | Self::cmd(sd_cmd::send_if_cond(1, 0xAA), false)?; | 1351 | self.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?; |
| 1347 | let cic = CIC::from(regs.respr(0).read().cardstatus()); | 1352 | let cic = CIC::from(regs.respr(0).read().cardstatus()); |
| 1348 | 1353 | ||
| 1349 | if cic.pattern() != 0xAA { | 1354 | if cic.pattern() != 0xAA { |
| @@ -1356,12 +1361,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1356 | 1361 | ||
| 1357 | let ocr = loop { | 1362 | let ocr = loop { |
| 1358 | // Signal that next command is a app command | 1363 | // Signal that next command is a app command |
| 1359 | Self::cmd(common_cmd::app_cmd(0), false)?; // CMD55 | 1364 | self.cmd(common_cmd::app_cmd(0), false)?; // CMD55 |
| 1360 | 1365 | ||
| 1361 | // 3.2-3.3V | 1366 | // 3.2-3.3V |
| 1362 | let voltage_window = 1 << 5; | 1367 | let voltage_window = 1 << 5; |
| 1363 | // Initialize card | 1368 | // Initialize card |
| 1364 | match Self::cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false) { | 1369 | match self.cmd(sd_cmd::sd_send_op_cond(true, false, true, voltage_window), false) { |
| 1365 | // ACMD41 | 1370 | // ACMD41 |
| 1366 | Ok(_) => (), | 1371 | Ok(_) => (), |
| 1367 | Err(Error::Crc) => (), | 1372 | Err(Error::Crc) => (), |
| @@ -1388,7 +1393,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1388 | let access_mode = 0b10 << 29; | 1393 | let access_mode = 0b10 << 29; |
| 1389 | let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15; | 1394 | let op_cond = high_voltage | access_mode | 0b1_1111_1111 << 15; |
| 1390 | // Initialize card | 1395 | // Initialize card |
| 1391 | match Self::cmd(emmc_cmd::send_op_cond(op_cond), false) { | 1396 | match self.cmd(emmc_cmd::send_op_cond(op_cond), false) { |
| 1392 | Ok(_) => (), | 1397 | Ok(_) => (), |
| 1393 | Err(Error::Crc) => (), | 1398 | Err(Error::Crc) => (), |
| 1394 | Err(err) => return Err(err), | 1399 | Err(err) => return Err(err), |
| @@ -1410,7 +1415,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1410 | } | 1415 | } |
| 1411 | } | 1416 | } |
| 1412 | 1417 | ||
| 1413 | Self::cmd(common_cmd::all_send_cid(), false)?; // CMD2 | 1418 | self.cmd(common_cmd::all_send_cid(), false)?; // CMD2 |
| 1414 | let cid0 = regs.respr(0).read().cardstatus() as u128; | 1419 | let cid0 = regs.respr(0).read().cardstatus() as u128; |
| 1415 | let cid1 = regs.respr(1).read().cardstatus() as u128; | 1420 | let cid1 = regs.respr(1).read().cardstatus() as u128; |
| 1416 | let cid2 = regs.respr(2).read().cardstatus() as u128; | 1421 | let cid2 = regs.respr(2).read().cardstatus() as u128; |
| @@ -1421,7 +1426,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1421 | SdmmcPeripheral::SdCard(ref mut card) => { | 1426 | SdmmcPeripheral::SdCard(ref mut card) => { |
| 1422 | card.cid = cid.into(); | 1427 | card.cid = cid.into(); |
| 1423 | 1428 | ||
| 1424 | Self::cmd(sd_cmd::send_relative_address(), false)?; | 1429 | self.cmd(sd_cmd::send_relative_address(), false)?; |
| 1425 | let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus()); | 1430 | let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus()); |
| 1426 | card.rca = rca.address(); | 1431 | card.rca = rca.address(); |
| 1427 | } | 1432 | } |
| @@ -1429,11 +1434,11 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1429 | emmc.cid = cid.into(); | 1434 | emmc.cid = cid.into(); |
| 1430 | 1435 | ||
| 1431 | emmc.rca = 1u16.into(); | 1436 | emmc.rca = 1u16.into(); |
| 1432 | Self::cmd(emmc_cmd::assign_relative_address(emmc.rca), false)?; | 1437 | self.cmd(emmc_cmd::assign_relative_address(emmc.rca), false)?; |
| 1433 | } | 1438 | } |
| 1434 | } | 1439 | } |
| 1435 | 1440 | ||
| 1436 | Self::cmd(common_cmd::send_csd(card.get_address()), false)?; | 1441 | self.cmd(common_cmd::send_csd(card.get_address()), false)?; |
| 1437 | let csd0 = regs.respr(0).read().cardstatus() as u128; | 1442 | let csd0 = regs.respr(0).read().cardstatus() as u128; |
| 1438 | let csd1 = regs.respr(1).read().cardstatus() as u128; | 1443 | let csd1 = regs.respr(1).read().cardstatus() as u128; |
| 1439 | let csd2 = regs.respr(2).read().cardstatus() as u128; | 1444 | let csd2 = regs.respr(2).read().cardstatus() as u128; |
| @@ -1475,12 +1480,12 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1475 | BusWidth::Four if card.scr.bus_width_four() => 2, | 1480 | BusWidth::Four if card.scr.bus_width_four() => 2, |
| 1476 | _ => 0, | 1481 | _ => 0, |
| 1477 | }; | 1482 | }; |
| 1478 | Self::cmd(common_cmd::app_cmd(card.rca), false)?; | 1483 | self.cmd(common_cmd::app_cmd(card.rca), false)?; |
| 1479 | Self::cmd(sd_cmd::cmd6(acmd_arg), false)?; | 1484 | self.cmd(sd_cmd::cmd6(acmd_arg), false)?; |
| 1480 | } | 1485 | } |
| 1481 | SdmmcPeripheral::Emmc(_) => { | 1486 | SdmmcPeripheral::Emmc(_) => { |
| 1482 | // Write bus width to ExtCSD byte 183 | 1487 | // Write bus width to ExtCSD byte 183 |
| 1483 | Self::cmd( | 1488 | self.cmd( |
| 1484 | emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus), | 1489 | emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus), |
| 1485 | false, | 1490 | false, |
| 1486 | )?; | 1491 | )?; |
| @@ -1497,7 +1502,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1497 | } | 1502 | } |
| 1498 | 1503 | ||
| 1499 | // CPSMACT and DPSMACT must be 0 to set WIDBUS | 1504 | // CPSMACT and DPSMACT must be 0 to set WIDBUS |
| 1500 | Self::wait_idle(); | 1505 | self.wait_idle(); |
| 1501 | 1506 | ||
| 1502 | regs.clkcr().modify(|w| w.set_widbus(widbus)); | 1507 | regs.clkcr().modify(|w| w.set_widbus(widbus)); |
| 1503 | 1508 | ||
| @@ -1546,7 +1551,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1546 | /// | 1551 | /// |
| 1547 | /// SD only. | 1552 | /// SD only. |
| 1548 | pub async fn init_sd_card(&mut self, freq: Hertz) -> Result<(), Error> { | 1553 | pub async fn init_sd_card(&mut self, freq: Hertz) -> Result<(), Error> { |
| 1549 | let _scoped_block_stop = T::RCC_INFO.block_stop(); | 1554 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1550 | 1555 | ||
| 1551 | self.init_internal(freq, SdmmcPeripheral::SdCard(Card::default())).await | 1556 | self.init_internal(freq, SdmmcPeripheral::SdCard(Card::default())).await |
| 1552 | } | 1557 | } |
| @@ -1579,9 +1584,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1579 | }; | 1584 | }; |
| 1580 | 1585 | ||
| 1581 | // Arm `OnDrop` after the buffer, so it will be dropped first | 1586 | // Arm `OnDrop` after the buffer, so it will be dropped first |
| 1582 | let on_drop = OnDrop::new(|| Self::on_drop()); | 1587 | let on_drop = OnDrop::new(|| self.on_drop()); |
| 1583 | 1588 | ||
| 1584 | let transfer = Self::prepare_datapath_read( | 1589 | let transfer = self.prepare_datapath_read( |
| 1585 | &self.config, | 1590 | &self.config, |
| 1586 | #[cfg(sdmmc_v1)] | 1591 | #[cfg(sdmmc_v1)] |
| 1587 | &mut self.dma, | 1592 | &mut self.dma, |
| @@ -1589,10 +1594,10 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1589 | 64, | 1594 | 64, |
| 1590 | 6, | 1595 | 6, |
| 1591 | ); | 1596 | ); |
| 1592 | InterruptHandler::<T>::enable_interrupts(); | 1597 | self.enable_interrupts(); |
| 1593 | Self::cmd(sd_cmd::cmd6(set_function), true)?; // CMD6 | 1598 | self.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6 |
| 1594 | 1599 | ||
| 1595 | let res = Self::complete_datapath_transfer(true).await; | 1600 | let res = self.complete_datapath_transfer(true).await; |
| 1596 | 1601 | ||
| 1597 | // Host is allowed to use the new functions at least 8 | 1602 | // Host is allowed to use the new functions at least 8 |
| 1598 | // clocks after the end of the switch command | 1603 | // clocks after the end of the switch command |
| @@ -1605,7 +1610,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1605 | match res { | 1610 | match res { |
| 1606 | Ok(_) => { | 1611 | Ok(_) => { |
| 1607 | on_drop.defuse(); | 1612 | on_drop.defuse(); |
| 1608 | Self::stop_datapath(); | 1613 | self.stop_datapath(); |
| 1609 | drop(transfer); | 1614 | drop(transfer); |
| 1610 | 1615 | ||
| 1611 | // Function Selection of Function Group 1 | 1616 | // Function Selection of Function Group 1 |
| @@ -1629,8 +1634,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1629 | /// SD only. | 1634 | /// SD only. |
| 1630 | async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> { | 1635 | async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> { |
| 1631 | // Read the 64-bit SCR register | 1636 | // Read the 64-bit SCR register |
| 1632 | Self::cmd(common_cmd::set_block_length(8), false)?; // CMD16 | 1637 | self.cmd(common_cmd::set_block_length(8), false)?; // CMD16 |
| 1633 | Self::cmd(common_cmd::app_cmd(card.rca), false)?; | 1638 | self.cmd(common_cmd::app_cmd(card.rca), false)?; |
| 1634 | 1639 | ||
| 1635 | let cmd_block = match self.cmd_block.as_deref_mut() { | 1640 | let cmd_block = match self.cmd_block.as_deref_mut() { |
| 1636 | Some(x) => x, | 1641 | Some(x) => x, |
| @@ -1639,9 +1644,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1639 | let scr = &mut cmd_block.0[..2]; | 1644 | let scr = &mut cmd_block.0[..2]; |
| 1640 | 1645 | ||
| 1641 | // Arm `OnDrop` after the buffer, so it will be dropped first | 1646 | // Arm `OnDrop` after the buffer, so it will be dropped first |
| 1642 | let on_drop = OnDrop::new(|| Self::on_drop()); | 1647 | let on_drop = OnDrop::new(|| self.on_drop()); |
| 1643 | 1648 | ||
| 1644 | let transfer = Self::prepare_datapath_read( | 1649 | let transfer = self.prepare_datapath_read( |
| 1645 | &self.config, | 1650 | &self.config, |
| 1646 | #[cfg(sdmmc_v1)] | 1651 | #[cfg(sdmmc_v1)] |
| 1647 | &mut self.dma, | 1652 | &mut self.dma, |
| @@ -1649,14 +1654,14 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1649 | 8, | 1654 | 8, |
| 1650 | 3, | 1655 | 3, |
| 1651 | ); | 1656 | ); |
| 1652 | InterruptHandler::<T>::enable_interrupts(); | 1657 | self.enable_interrupts(); |
| 1653 | Self::cmd(sd_cmd::send_scr(), true)?; | 1658 | self.cmd(sd_cmd::send_scr(), true)?; |
| 1654 | 1659 | ||
| 1655 | let res = Self::complete_datapath_transfer(true).await; | 1660 | let res = self.complete_datapath_transfer(true).await; |
| 1656 | 1661 | ||
| 1657 | if res.is_ok() { | 1662 | if res.is_ok() { |
| 1658 | on_drop.defuse(); | 1663 | on_drop.defuse(); |
| 1659 | Self::stop_datapath(); | 1664 | self.stop_datapath(); |
| 1660 | drop(transfer); | 1665 | drop(transfer); |
| 1661 | 1666 | ||
| 1662 | unsafe { | 1667 | unsafe { |
| @@ -1679,15 +1684,15 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1679 | None => &mut CmdBlock::new(), | 1684 | None => &mut CmdBlock::new(), |
| 1680 | }; | 1685 | }; |
| 1681 | 1686 | ||
| 1682 | Self::cmd(common_cmd::set_block_length(64), false)?; // CMD16 | 1687 | self.cmd(common_cmd::set_block_length(64), false)?; // CMD16 |
| 1683 | Self::cmd(common_cmd::app_cmd(rca), false)?; // APP | 1688 | self.cmd(common_cmd::app_cmd(rca), false)?; // APP |
| 1684 | 1689 | ||
| 1685 | let status = cmd_block; | 1690 | let status = cmd_block; |
| 1686 | 1691 | ||
| 1687 | // Arm `OnDrop` after the buffer, so it will be dropped first | 1692 | // Arm `OnDrop` after the buffer, so it will be dropped first |
| 1688 | let on_drop = OnDrop::new(|| Self::on_drop()); | 1693 | let on_drop = OnDrop::new(|| self.on_drop()); |
| 1689 | 1694 | ||
| 1690 | let transfer = Self::prepare_datapath_read( | 1695 | let transfer = self.prepare_datapath_read( |
| 1691 | &self.config, | 1696 | &self.config, |
| 1692 | #[cfg(sdmmc_v1)] | 1697 | #[cfg(sdmmc_v1)] |
| 1693 | &mut self.dma, | 1698 | &mut self.dma, |
| @@ -1695,14 +1700,14 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1695 | 64, | 1700 | 64, |
| 1696 | 6, | 1701 | 6, |
| 1697 | ); | 1702 | ); |
| 1698 | InterruptHandler::<T>::enable_interrupts(); | 1703 | self.enable_interrupts(); |
| 1699 | Self::cmd(sd_cmd::sd_status(), true)?; | 1704 | self.cmd(sd_cmd::sd_status(), true)?; |
| 1700 | 1705 | ||
| 1701 | let res = Self::complete_datapath_transfer(true).await; | 1706 | let res = self.complete_datapath_transfer(true).await; |
| 1702 | 1707 | ||
| 1703 | if res.is_ok() { | 1708 | if res.is_ok() { |
| 1704 | on_drop.defuse(); | 1709 | on_drop.defuse(); |
| 1705 | Self::stop_datapath(); | 1710 | self.stop_datapath(); |
| 1706 | drop(transfer); | 1711 | drop(transfer); |
| 1707 | 1712 | ||
| 1708 | for byte in status.iter_mut() { | 1713 | for byte in status.iter_mut() { |
| @@ -1717,7 +1722,7 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1717 | /// | 1722 | /// |
| 1718 | /// eMMC only. | 1723 | /// eMMC only. |
| 1719 | pub async fn init_emmc(&mut self, freq: Hertz) -> Result<(), Error> { | 1724 | pub async fn init_emmc(&mut self, freq: Hertz) -> Result<(), Error> { |
| 1720 | let _scoped_block_stop = T::RCC_INFO.block_stop(); | 1725 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1721 | 1726 | ||
| 1722 | self.init_internal(freq, SdmmcPeripheral::Emmc(Emmc::default())).await | 1727 | self.init_internal(freq, SdmmcPeripheral::Emmc(Emmc::default())).await |
| 1723 | } | 1728 | } |
| @@ -1726,7 +1731,8 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1726 | /// | 1731 | /// |
| 1727 | /// eMMC only. | 1732 | /// eMMC only. |
| 1728 | async fn read_ext_csd(&mut self) -> Result<(), Error> { | 1733 | async fn read_ext_csd(&mut self) -> Result<(), Error> { |
| 1729 | let card = self.card.as_mut().ok_or(Error::NoCard)?.get_emmc(); | 1734 | let mut card = self.card.take().ok_or(Error::NoCard)?; |
| 1735 | let emmc = card.get_emmc(); | ||
| 1730 | 1736 | ||
| 1731 | // Note: cmd_block can't be used because ExtCSD is too long to fit. | 1737 | // Note: cmd_block can't be used because ExtCSD is too long to fit. |
| 1732 | let mut data_block = DataBlock([0u8; 512]); | 1738 | let mut data_block = DataBlock([0u8; 512]); |
| @@ -1734,12 +1740,9 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1734 | // NOTE(unsafe) DataBlock uses align 4 | 1740 | // NOTE(unsafe) DataBlock uses align 4 |
| 1735 | let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) }; | 1741 | let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) }; |
| 1736 | 1742 | ||
| 1737 | Self::cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16 | 1743 | self.cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16 |
| 1738 | 1744 | ||
| 1739 | // Arm `OnDrop` after the buffer, so it will be dropped first | 1745 | let transfer = self.prepare_datapath_read( |
| 1740 | let on_drop = OnDrop::new(|| Self::on_drop()); | ||
| 1741 | |||
| 1742 | let transfer = Self::prepare_datapath_read( | ||
| 1743 | &self.config, | 1746 | &self.config, |
| 1744 | #[cfg(sdmmc_v1)] | 1747 | #[cfg(sdmmc_v1)] |
| 1745 | &mut self.dma, | 1748 | &mut self.dma, |
| @@ -1747,26 +1750,30 @@ impl<'d, T: Instance> Sdmmc<'d, T> { | |||
| 1747 | 512, | 1750 | 512, |
| 1748 | 9, | 1751 | 9, |
| 1749 | ); | 1752 | ); |
| 1750 | InterruptHandler::<T>::enable_interrupts(); | 1753 | self.enable_interrupts(); |
| 1751 | Self::cmd(emmc_cmd::send_ext_csd(), true)?; | 1754 | self.cmd(emmc_cmd::send_ext_csd(), true)?; |
| 1752 | 1755 | ||
| 1753 | let res = Self::complete_datapath_transfer(true).await; | 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; | ||
| 1754 | 1760 | ||
| 1755 | if res.is_ok() { | 1761 | if res.is_ok() { |
| 1756 | on_drop.defuse(); | 1762 | on_drop.defuse(); |
| 1757 | Self::stop_datapath(); | 1763 | self.stop_datapath(); |
| 1758 | drop(transfer); | 1764 | drop(transfer); |
| 1759 | 1765 | ||
| 1760 | card.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into(); | 1766 | emmc.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into(); |
| 1761 | } | 1767 | } |
| 1768 | |||
| 1762 | res | 1769 | res |
| 1763 | } | 1770 | } |
| 1764 | } | 1771 | } |
| 1765 | 1772 | ||
| 1766 | impl<'d, T: Instance> Drop for Sdmmc<'d, T> { | 1773 | impl<'d> Drop for Sdmmc<'d> { |
| 1767 | fn drop(&mut self) { | 1774 | fn drop(&mut self) { |
| 1768 | T::Interrupt::disable(); | 1775 | // T::Interrupt::disable(); |
| 1769 | Self::on_drop(); | 1776 | self.on_drop(); |
| 1770 | 1777 | ||
| 1771 | critical_section::with(|_| { | 1778 | critical_section::with(|_| { |
| 1772 | self.clk.set_as_disconnected(); | 1779 | self.clk.set_as_disconnected(); |
| @@ -1799,9 +1806,28 @@ impl<'d, T: Instance> Drop for Sdmmc<'d, T> { | |||
| 1799 | 1806 | ||
| 1800 | ////////////////////////////////////////////////////// | 1807 | ////////////////////////////////////////////////////// |
| 1801 | 1808 | ||
| 1809 | type Regs = RegBlock; | ||
| 1810 | |||
| 1811 | struct Info { | ||
| 1812 | regs: Regs, | ||
| 1813 | rcc: RccInfo, | ||
| 1814 | } | ||
| 1815 | |||
| 1816 | struct State { | ||
| 1817 | waker: AtomicWaker, | ||
| 1818 | } | ||
| 1819 | |||
| 1820 | impl State { | ||
| 1821 | const fn new() -> Self { | ||
| 1822 | Self { | ||
| 1823 | waker: AtomicWaker::new(), | ||
| 1824 | } | ||
| 1825 | } | ||
| 1826 | } | ||
| 1827 | |||
| 1802 | trait SealedInstance { | 1828 | trait SealedInstance { |
| 1803 | fn regs() -> RegBlock; | 1829 | fn info() -> &'static Info; |
| 1804 | fn state() -> &'static AtomicWaker; | 1830 | fn state() -> &'static State; |
| 1805 | } | 1831 | } |
| 1806 | 1832 | ||
| 1807 | /// SDMMC instance trait. | 1833 | /// SDMMC instance trait. |
| @@ -1828,13 +1854,17 @@ dma_trait!(SdmmcDma, Instance); | |||
| 1828 | foreach_peripheral!( | 1854 | foreach_peripheral!( |
| 1829 | (sdmmc, $inst:ident) => { | 1855 | (sdmmc, $inst:ident) => { |
| 1830 | impl SealedInstance for peripherals::$inst { | 1856 | impl SealedInstance for peripherals::$inst { |
| 1831 | fn regs() -> RegBlock { | 1857 | fn info() -> &'static Info { |
| 1832 | crate::pac::$inst | 1858 | static INFO: Info = Info { |
| 1859 | regs: unsafe { Regs::from_ptr(crate::pac::$inst.as_ptr()) }, | ||
| 1860 | rcc: crate::peripherals::$inst::RCC_INFO, | ||
| 1861 | }; | ||
| 1862 | &INFO | ||
| 1833 | } | 1863 | } |
| 1834 | 1864 | ||
| 1835 | fn state() -> &'static ::embassy_sync::waitqueue::AtomicWaker { | 1865 | fn state() -> &'static State { |
| 1836 | static WAKER: ::embassy_sync::waitqueue::AtomicWaker = ::embassy_sync::waitqueue::AtomicWaker::new(); | 1866 | static STATE: State = State::new(); |
| 1837 | &WAKER | 1867 | &STATE |
| 1838 | } | 1868 | } |
| 1839 | } | 1869 | } |
| 1840 | 1870 | ||
| @@ -1844,7 +1874,7 @@ foreach_peripheral!( | |||
| 1844 | }; | 1874 | }; |
| 1845 | ); | 1875 | ); |
| 1846 | 1876 | ||
| 1847 | impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> { | 1877 | impl<'d> block_device_driver::BlockDevice<512> for Sdmmc<'d> { |
| 1848 | type Error = Error; | 1878 | type Error = Error; |
| 1849 | type Align = aligned::A4; | 1879 | type Align = aligned::A4; |
| 1850 | 1880 | ||
| @@ -1853,7 +1883,7 @@ impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> { | |||
| 1853 | block_address: u32, | 1883 | block_address: u32, |
| 1854 | buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>], | 1884 | buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>], |
| 1855 | ) -> Result<(), Self::Error> { | 1885 | ) -> Result<(), Self::Error> { |
| 1856 | let _scoped_block_stop = T::RCC_INFO.block_stop(); | 1886 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1857 | // TODO: I think block_address needs to be adjusted by the partition start offset | 1887 | // TODO: I think block_address needs to be adjusted by the partition start offset |
| 1858 | if buf.len() == 1 { | 1888 | if buf.len() == 1 { |
| 1859 | let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut crate::sdmmc::DataBlock) }; | 1889 | let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut crate::sdmmc::DataBlock) }; |
| @@ -1871,7 +1901,7 @@ impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> { | |||
| 1871 | block_address: u32, | 1901 | block_address: u32, |
| 1872 | buf: &[aligned::Aligned<Self::Align, [u8; 512]>], | 1902 | buf: &[aligned::Aligned<Self::Align, [u8; 512]>], |
| 1873 | ) -> Result<(), Self::Error> { | 1903 | ) -> Result<(), Self::Error> { |
| 1874 | let _scoped_block_stop = T::RCC_INFO.block_stop(); | 1904 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1875 | // TODO: I think block_address needs to be adjusted by the partition start offset | 1905 | // TODO: I think block_address needs to be adjusted by the partition start offset |
| 1876 | if buf.len() == 1 { | 1906 | if buf.len() == 1 { |
| 1877 | let block = unsafe { &*(&buf[0] as *const _ as *const crate::sdmmc::DataBlock) }; | 1907 | let block = unsafe { &*(&buf[0] as *const _ as *const crate::sdmmc::DataBlock) }; |
