diff options
| -rw-r--r-- | embassy-stm32/src/macros.rs | 12 | ||||
| -rw-r--r-- | embassy-stm32/src/sdmmc/mod.rs | 104 |
2 files changed, 66 insertions, 50 deletions
diff --git a/embassy-stm32/src/macros.rs b/embassy-stm32/src/macros.rs index ae53deb08..000773e2d 100644 --- a/embassy-stm32/src/macros.rs +++ b/embassy-stm32/src/macros.rs | |||
| @@ -85,6 +85,18 @@ macro_rules! dma_trait_impl { | |||
| 85 | }; | 85 | }; |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | #[allow(unused)] | ||
| 89 | macro_rules! new_dma_nonopt { | ||
| 90 | ($name:ident) => {{ | ||
| 91 | let dma = $name.into_ref(); | ||
| 92 | let request = dma.request(); | ||
| 93 | crate::dma::ChannelAndRequest { | ||
| 94 | channel: dma.map_into(), | ||
| 95 | request, | ||
| 96 | } | ||
| 97 | }}; | ||
| 98 | } | ||
| 99 | |||
| 88 | macro_rules! new_dma { | 100 | macro_rules! new_dma { |
| 89 | ($name:ident) => {{ | 101 | ($name:ident) => {{ |
| 90 | let dma = $name.into_ref(); | 102 | let dma = $name.into_ref(); |
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 8af2f8381..d8671caf7 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -12,7 +12,8 @@ use embassy_hal_internal::{into_ref, PeripheralRef}; | |||
| 12 | use embassy_sync::waitqueue::AtomicWaker; | 12 | use embassy_sync::waitqueue::AtomicWaker; |
| 13 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; | 13 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; |
| 14 | 14 | ||
| 15 | use crate::dma::NoDma; | 15 | #[cfg(sdmmc_v1)] |
| 16 | use crate::dma::ChannelAndRequest; | ||
| 16 | #[cfg(gpio_v2)] | 17 | #[cfg(gpio_v2)] |
| 17 | use crate::gpio::Pull; | 18 | use crate::gpio::Pull; |
| 18 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; | 19 | use crate::gpio::{AfType, AnyPin, OutputType, SealedPin, Speed}; |
| @@ -301,10 +302,10 @@ impl Default for Config { | |||
| 301 | } | 302 | } |
| 302 | 303 | ||
| 303 | /// Sdmmc device | 304 | /// Sdmmc device |
| 304 | pub struct Sdmmc<'d, T: Instance, Dma: SdmmcDma<T> = NoDma> { | 305 | pub struct Sdmmc<'d, T: Instance> { |
| 305 | _peri: PeripheralRef<'d, T>, | 306 | _peri: PeripheralRef<'d, T>, |
| 306 | #[allow(unused)] | 307 | #[cfg(sdmmc_v1)] |
| 307 | dma: PeripheralRef<'d, Dma>, | 308 | dma: ChannelAndRequest<'d>, |
| 308 | 309 | ||
| 309 | clk: PeripheralRef<'d, AnyPin>, | 310 | clk: PeripheralRef<'d, AnyPin>, |
| 310 | cmd: PeripheralRef<'d, AnyPin>, | 311 | cmd: PeripheralRef<'d, AnyPin>, |
| @@ -334,18 +335,18 @@ const CMD_AF: AfType = AfType::output_pull(OutputType::PushPull, Speed::VeryHigh | |||
| 334 | const DATA_AF: AfType = CMD_AF; | 335 | const DATA_AF: AfType = CMD_AF; |
| 335 | 336 | ||
| 336 | #[cfg(sdmmc_v1)] | 337 | #[cfg(sdmmc_v1)] |
| 337 | impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | 338 | impl<'d, T: Instance> Sdmmc<'d, T> { |
| 338 | /// Create a new SDMMC driver, with 1 data lane. | 339 | /// Create a new SDMMC driver, with 1 data lane. |
| 339 | pub fn new_1bit( | 340 | pub fn new_1bit( |
| 340 | sdmmc: impl Peripheral<P = T> + 'd, | 341 | sdmmc: impl Peripheral<P = T> + 'd, |
| 341 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 342 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 342 | dma: impl Peripheral<P = Dma> + 'd, | 343 | dma: impl Peripheral<P = impl SdmmcDma<T>> + 'd, |
| 343 | clk: impl Peripheral<P = impl CkPin<T>> + 'd, | 344 | clk: impl Peripheral<P = impl CkPin<T>> + 'd, |
| 344 | cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, | 345 | cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, |
| 345 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, | 346 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, |
| 346 | config: Config, | 347 | config: Config, |
| 347 | ) -> Self { | 348 | ) -> Self { |
| 348 | into_ref!(clk, cmd, d0); | 349 | into_ref!(dma, clk, cmd, d0); |
| 349 | 350 | ||
| 350 | critical_section::with(|_| { | 351 | critical_section::with(|_| { |
| 351 | clk.set_as_af(clk.af_num(), CLK_AF); | 352 | clk.set_as_af(clk.af_num(), CLK_AF); |
| @@ -355,7 +356,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 355 | 356 | ||
| 356 | Self::new_inner( | 357 | Self::new_inner( |
| 357 | sdmmc, | 358 | sdmmc, |
| 358 | dma, | 359 | new_dma_nonopt!(dma), |
| 359 | clk.map_into(), | 360 | clk.map_into(), |
| 360 | cmd.map_into(), | 361 | cmd.map_into(), |
| 361 | d0.map_into(), | 362 | d0.map_into(), |
| @@ -370,7 +371,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 370 | pub fn new_4bit( | 371 | pub fn new_4bit( |
| 371 | sdmmc: impl Peripheral<P = T> + 'd, | 372 | sdmmc: impl Peripheral<P = T> + 'd, |
| 372 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, | 373 | _irq: impl interrupt::typelevel::Binding<T::Interrupt, InterruptHandler<T>> + 'd, |
| 373 | dma: impl Peripheral<P = Dma> + 'd, | 374 | dma: impl Peripheral<P = impl SdmmcDma<T>> + 'd, |
| 374 | clk: impl Peripheral<P = impl CkPin<T>> + 'd, | 375 | clk: impl Peripheral<P = impl CkPin<T>> + 'd, |
| 375 | cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, | 376 | cmd: impl Peripheral<P = impl CmdPin<T>> + 'd, |
| 376 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, | 377 | d0: impl Peripheral<P = impl D0Pin<T>> + 'd, |
| @@ -392,7 +393,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 392 | 393 | ||
| 393 | Self::new_inner( | 394 | Self::new_inner( |
| 394 | sdmmc, | 395 | sdmmc, |
| 395 | dma, | 396 | new_dma_nonopt!(dma), |
| 396 | clk.map_into(), | 397 | clk.map_into(), |
| 397 | cmd.map_into(), | 398 | cmd.map_into(), |
| 398 | d0.map_into(), | 399 | d0.map_into(), |
| @@ -405,7 +406,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T>> Sdmmc<'d, T, Dma> { | |||
| 405 | } | 406 | } |
| 406 | 407 | ||
| 407 | #[cfg(sdmmc_v2)] | 408 | #[cfg(sdmmc_v2)] |
| 408 | impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | 409 | impl<'d, T: Instance> Sdmmc<'d, T> { |
| 409 | /// Create a new SDMMC driver, with 1 data lane. | 410 | /// Create a new SDMMC driver, with 1 data lane. |
| 410 | pub fn new_1bit( | 411 | pub fn new_1bit( |
| 411 | sdmmc: impl Peripheral<P = T> + 'd, | 412 | sdmmc: impl Peripheral<P = T> + 'd, |
| @@ -425,7 +426,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||
| 425 | 426 | ||
| 426 | Self::new_inner( | 427 | Self::new_inner( |
| 427 | sdmmc, | 428 | sdmmc, |
| 428 | NoDma.into_ref(), | ||
| 429 | clk.map_into(), | 429 | clk.map_into(), |
| 430 | cmd.map_into(), | 430 | cmd.map_into(), |
| 431 | d0.map_into(), | 431 | d0.map_into(), |
| @@ -461,7 +461,6 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||
| 461 | 461 | ||
| 462 | Self::new_inner( | 462 | Self::new_inner( |
| 463 | sdmmc, | 463 | sdmmc, |
| 464 | NoDma.into_ref(), | ||
| 465 | clk.map_into(), | 464 | clk.map_into(), |
| 466 | cmd.map_into(), | 465 | cmd.map_into(), |
| 467 | d0.map_into(), | 466 | d0.map_into(), |
| @@ -473,10 +472,10 @@ impl<'d, T: Instance> Sdmmc<'d, T, NoDma> { | |||
| 473 | } | 472 | } |
| 474 | } | 473 | } |
| 475 | 474 | ||
| 476 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | 475 | impl<'d, T: Instance> Sdmmc<'d, T> { |
| 477 | fn new_inner( | 476 | fn new_inner( |
| 478 | sdmmc: impl Peripheral<P = T> + 'd, | 477 | sdmmc: impl Peripheral<P = T> + 'd, |
| 479 | dma: impl Peripheral<P = Dma> + 'd, | 478 | #[cfg(sdmmc_v1)] dma: ChannelAndRequest<'d>, |
| 480 | clk: PeripheralRef<'d, AnyPin>, | 479 | clk: PeripheralRef<'d, AnyPin>, |
| 481 | cmd: PeripheralRef<'d, AnyPin>, | 480 | cmd: PeripheralRef<'d, AnyPin>, |
| 482 | d0: PeripheralRef<'d, AnyPin>, | 481 | d0: PeripheralRef<'d, AnyPin>, |
| @@ -485,7 +484,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 485 | d3: Option<PeripheralRef<'d, AnyPin>>, | 484 | d3: Option<PeripheralRef<'d, AnyPin>>, |
| 486 | config: Config, | 485 | config: Config, |
| 487 | ) -> Self { | 486 | ) -> Self { |
| 488 | into_ref!(sdmmc, dma); | 487 | into_ref!(sdmmc); |
| 489 | 488 | ||
| 490 | rcc::enable_and_reset::<T>(); | 489 | rcc::enable_and_reset::<T>(); |
| 491 | 490 | ||
| @@ -514,6 +513,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 514 | 513 | ||
| 515 | Self { | 514 | Self { |
| 516 | _peri: sdmmc, | 515 | _peri: sdmmc, |
| 516 | #[cfg(sdmmc_v1)] | ||
| 517 | dma, | 517 | dma, |
| 518 | 518 | ||
| 519 | clk, | 519 | clk, |
| @@ -567,7 +567,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 567 | #[allow(unused_variables)] | 567 | #[allow(unused_variables)] |
| 568 | fn prepare_datapath_read<'a>( | 568 | fn prepare_datapath_read<'a>( |
| 569 | config: &Config, | 569 | config: &Config, |
| 570 | dma: &'a mut PeripheralRef<'d, Dma>, | 570 | #[cfg(sdmmc_v1)] dma: &'a mut ChannelAndRequest<'d>, |
| 571 | buffer: &'a mut [u32], | 571 | buffer: &'a mut [u32], |
| 572 | length_bytes: u32, | 572 | length_bytes: u32, |
| 573 | block_size: u8, | 573 | block_size: u8, |
| @@ -583,16 +583,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 583 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); | 583 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); |
| 584 | 584 | ||
| 585 | #[cfg(sdmmc_v1)] | 585 | #[cfg(sdmmc_v1)] |
| 586 | let transfer = unsafe { | 586 | let transfer = unsafe { dma.read(regs.fifor().as_ptr() as *mut u32, buffer, DMA_TRANSFER_OPTIONS) }; |
| 587 | let request = dma.request(); | ||
| 588 | Transfer::new_read( | ||
| 589 | dma, | ||
| 590 | request, | ||
| 591 | regs.fifor().as_ptr() as *mut u32, | ||
| 592 | buffer, | ||
| 593 | DMA_TRANSFER_OPTIONS, | ||
| 594 | ) | ||
| 595 | }; | ||
| 596 | #[cfg(sdmmc_v2)] | 587 | #[cfg(sdmmc_v2)] |
| 597 | let transfer = { | 588 | let transfer = { |
| 598 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); | 589 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer.as_mut_ptr() as u32)); |
| @@ -632,14 +623,8 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 632 | 623 | ||
| 633 | #[cfg(sdmmc_v1)] | 624 | #[cfg(sdmmc_v1)] |
| 634 | let transfer = unsafe { | 625 | let transfer = unsafe { |
| 635 | let request = self.dma.request(); | 626 | self.dma |
| 636 | Transfer::new_write( | 627 | .write(buffer, regs.fifor().as_ptr() as *mut u32, DMA_TRANSFER_OPTIONS) |
| 637 | &mut self.dma, | ||
| 638 | request, | ||
| 639 | buffer, | ||
| 640 | regs.fifor().as_ptr() as *mut u32, | ||
| 641 | DMA_TRANSFER_OPTIONS, | ||
| 642 | ) | ||
| 643 | }; | 628 | }; |
| 644 | #[cfg(sdmmc_v2)] | 629 | #[cfg(sdmmc_v2)] |
| 645 | let transfer = { | 630 | let transfer = { |
| @@ -735,7 +720,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 735 | let regs = T::regs(); | 720 | let regs = T::regs(); |
| 736 | let on_drop = OnDrop::new(|| Self::on_drop()); | 721 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 737 | 722 | ||
| 738 | let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); | 723 | let transfer = Self::prepare_datapath_read( |
| 724 | &self.config, | ||
| 725 | #[cfg(sdmmc_v1)] | ||
| 726 | &mut self.dma, | ||
| 727 | status.as_mut(), | ||
| 728 | 64, | ||
| 729 | 6, | ||
| 730 | ); | ||
| 739 | InterruptHandler::<T>::data_interrupts(true); | 731 | InterruptHandler::<T>::data_interrupts(true); |
| 740 | Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6 | 732 | Self::cmd(Cmd::cmd6(set_function), true)?; // CMD6 |
| 741 | 733 | ||
| @@ -821,7 +813,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 821 | let regs = T::regs(); | 813 | let regs = T::regs(); |
| 822 | let on_drop = OnDrop::new(|| Self::on_drop()); | 814 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 823 | 815 | ||
| 824 | let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, status.as_mut(), 64, 6); | 816 | let transfer = Self::prepare_datapath_read( |
| 817 | &self.config, | ||
| 818 | #[cfg(sdmmc_v1)] | ||
| 819 | &mut self.dma, | ||
| 820 | status.as_mut(), | ||
| 821 | 64, | ||
| 822 | 6, | ||
| 823 | ); | ||
| 825 | InterruptHandler::<T>::data_interrupts(true); | 824 | InterruptHandler::<T>::data_interrupts(true); |
| 826 | Self::cmd(Cmd::card_status(0), true)?; | 825 | Self::cmd(Cmd::card_status(0), true)?; |
| 827 | 826 | ||
| @@ -924,7 +923,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 924 | let regs = T::regs(); | 923 | let regs = T::regs(); |
| 925 | let on_drop = OnDrop::new(|| Self::on_drop()); | 924 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 926 | 925 | ||
| 927 | let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, scr, 8, 3); | 926 | let transfer = Self::prepare_datapath_read( |
| 927 | &self.config, | ||
| 928 | #[cfg(sdmmc_v1)] | ||
| 929 | &mut self.dma, | ||
| 930 | scr, | ||
| 931 | 8, | ||
| 932 | 3, | ||
| 933 | ); | ||
| 928 | InterruptHandler::<T>::data_interrupts(true); | 934 | InterruptHandler::<T>::data_interrupts(true); |
| 929 | Self::cmd(Cmd::cmd51(), true)?; | 935 | Self::cmd(Cmd::cmd51(), true)?; |
| 930 | 936 | ||
| @@ -1214,7 +1220,14 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1214 | let regs = T::regs(); | 1220 | let regs = T::regs(); |
| 1215 | let on_drop = OnDrop::new(|| Self::on_drop()); | 1221 | let on_drop = OnDrop::new(|| Self::on_drop()); |
| 1216 | 1222 | ||
| 1217 | let transfer = Self::prepare_datapath_read(&self.config, &mut self.dma, buffer, 512, 9); | 1223 | let transfer = Self::prepare_datapath_read( |
| 1224 | &self.config, | ||
| 1225 | #[cfg(sdmmc_v1)] | ||
| 1226 | &mut self.dma, | ||
| 1227 | buffer, | ||
| 1228 | 512, | ||
| 1229 | 9, | ||
| 1230 | ); | ||
| 1218 | InterruptHandler::<T>::data_interrupts(true); | 1231 | InterruptHandler::<T>::data_interrupts(true); |
| 1219 | Self::cmd(Cmd::read_single_block(address), true)?; | 1232 | Self::cmd(Cmd::read_single_block(address), true)?; |
| 1220 | 1233 | ||
| @@ -1347,7 +1360,7 @@ impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Sdmmc<'d, T, Dma> { | |||
| 1347 | } | 1360 | } |
| 1348 | } | 1361 | } |
| 1349 | 1362 | ||
| 1350 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> Drop for Sdmmc<'d, T, Dma> { | 1363 | impl<'d, T: Instance> Drop for Sdmmc<'d, T> { |
| 1351 | fn drop(&mut self) { | 1364 | fn drop(&mut self) { |
| 1352 | T::Interrupt::disable(); | 1365 | T::Interrupt::disable(); |
| 1353 | Self::on_drop(); | 1366 | Self::on_drop(); |
| @@ -1484,15 +1497,6 @@ pin_trait!(D7Pin, Instance); | |||
| 1484 | #[cfg(sdmmc_v1)] | 1497 | #[cfg(sdmmc_v1)] |
| 1485 | dma_trait!(SdmmcDma, Instance); | 1498 | dma_trait!(SdmmcDma, Instance); |
| 1486 | 1499 | ||
| 1487 | /// DMA instance trait. | ||
| 1488 | /// | ||
| 1489 | /// This is only implemented for `NoDma`, since SDMMCv2 has DMA built-in, instead of | ||
| 1490 | /// using ST's system-wide DMA peripheral. | ||
| 1491 | #[cfg(sdmmc_v2)] | ||
| 1492 | pub trait SdmmcDma<T: Instance> {} | ||
| 1493 | #[cfg(sdmmc_v2)] | ||
| 1494 | impl<T: Instance> SdmmcDma<T> for NoDma {} | ||
| 1495 | |||
| 1496 | foreach_peripheral!( | 1500 | foreach_peripheral!( |
| 1497 | (sdmmc, $inst:ident) => { | 1501 | (sdmmc, $inst:ident) => { |
| 1498 | impl SealedInstance for peripherals::$inst { | 1502 | impl SealedInstance for peripherals::$inst { |
| @@ -1512,7 +1516,7 @@ foreach_peripheral!( | |||
| 1512 | }; | 1516 | }; |
| 1513 | ); | 1517 | ); |
| 1514 | 1518 | ||
| 1515 | impl<'d, T: Instance, Dma: SdmmcDma<T> + 'd> block_device_driver::BlockDevice<512> for Sdmmc<'d, T, Dma> { | 1519 | impl<'d, T: Instance> block_device_driver::BlockDevice<512> for Sdmmc<'d, T> { |
| 1516 | type Error = Error; | 1520 | type Error = Error; |
| 1517 | type Align = aligned::A4; | 1521 | type Align = aligned::A4; |
| 1518 | 1522 | ||
