diff options
| -rw-r--r-- | embassy-stm32/Cargo.toml | 3 | ||||
| -rw-r--r-- | embassy-stm32/src/sdmmc_v2.rs | 303 |
2 files changed, 218 insertions, 88 deletions
diff --git a/embassy-stm32/Cargo.toml b/embassy-stm32/Cargo.toml index 4735a34f0..bd06abee1 100644 --- a/embassy-stm32/Cargo.toml +++ b/embassy-stm32/Cargo.toml | |||
| @@ -24,12 +24,13 @@ embedded-sdmmc = { git = "https://github.com/thalesfragoso/embedded-sdmmc-rs", b | |||
| 24 | regex = "1.4.6" | 24 | regex = "1.4.6" |
| 25 | 25 | ||
| 26 | [features] | 26 | [features] |
| 27 | default = ["stm32h750vb", "defmt-debug", "defmt"] | 27 | default = ["stm32h750vb", "defmt-debug", "defmt", "sdmmc-rs"] |
| 28 | defmt-trace = [ ] | 28 | defmt-trace = [ ] |
| 29 | defmt-debug = [ ] | 29 | defmt-debug = [ ] |
| 30 | defmt-info = [ ] | 30 | defmt-info = [ ] |
| 31 | defmt-warn = [ ] | 31 | defmt-warn = [ ] |
| 32 | defmt-error = [ ] | 32 | defmt-error = [ ] |
| 33 | sdmmc-rs = ["embedded-sdmmc"] | ||
| 33 | 34 | ||
| 34 | # BEGIN GENERATED FEATURES | 35 | # BEGIN GENERATED FEATURES |
| 35 | stm32f401cb = [ "_dma", "_dma_v2", "_exti", "_exti_v1", "_gpio", "_gpio_v2", "_spi", "_spi_v1", "_stm32f4", "_syscfg", "_syscfg_f4", "_usart", "_usart_v1",] | 36 | stm32f401cb = [ "_dma", "_dma_v2", "_exti", "_exti_v1", "_gpio", "_gpio_v2", "_spi", "_spi_v1", "_stm32f4", "_syscfg", "_syscfg_f4", "_usart", "_usart_v1",] |
diff --git a/embassy-stm32/src/sdmmc_v2.rs b/embassy-stm32/src/sdmmc_v2.rs index ba849008d..215a2a6a2 100644 --- a/embassy-stm32/src/sdmmc_v2.rs +++ b/embassy-stm32/src/sdmmc_v2.rs | |||
| @@ -5,7 +5,6 @@ use core::task::Poll; | |||
| 5 | use embassy::interrupt::InterruptExt; | 5 | use embassy::interrupt::InterruptExt; |
| 6 | use embassy::util::{AtomicWaker, OnDrop, Unborrow}; | 6 | use embassy::util::{AtomicWaker, OnDrop, Unborrow}; |
| 7 | use embassy_extras::unborrow; | 7 | use embassy_extras::unborrow; |
| 8 | use embedded_sdmmc::{Block, BlockCount, BlockDevice, BlockIdx}; | ||
| 9 | use futures::future::poll_fn; | 8 | use futures::future::poll_fn; |
| 10 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; | 9 | use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; |
| 11 | 10 | ||
| @@ -151,6 +150,8 @@ pub struct Sdmmc<'d, T: Instance, P: Pins<T>> { | |||
| 151 | signalling: Signalling, | 150 | signalling: Signalling, |
| 152 | /// Card | 151 | /// Card |
| 153 | card: Option<Card>, | 152 | card: Option<Card>, |
| 153 | /// The timeout to be set for data transfers, in card bus clock periods | ||
| 154 | data_transfer_timeout: u32, | ||
| 154 | } | 155 | } |
| 155 | 156 | ||
| 156 | impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P> { | 157 | impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P> { |
| @@ -164,6 +165,7 @@ impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P> { | |||
| 164 | irq: impl Unborrow<Target = T::Interrupt>, | 165 | irq: impl Unborrow<Target = T::Interrupt>, |
| 165 | hclk: Hertz, | 166 | hclk: Hertz, |
| 166 | kernel_clk: Hertz, | 167 | kernel_clk: Hertz, |
| 168 | data_transfer_timeout: u32, | ||
| 167 | ) -> Self { | 169 | ) -> Self { |
| 168 | unborrow!(irq, pins); | 170 | unborrow!(irq, pins); |
| 169 | pins.configure(); | 171 | pins.configure(); |
| @@ -184,6 +186,7 @@ impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P> { | |||
| 184 | clock, | 186 | clock, |
| 185 | signalling: Default::default(), | 187 | signalling: Default::default(), |
| 186 | card: None, | 188 | card: None, |
| 189 | data_transfer_timeout, | ||
| 187 | } | 190 | } |
| 188 | } | 191 | } |
| 189 | 192 | ||
| @@ -202,6 +205,7 @@ impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P> { | |||
| 202 | self.ker_ck, | 205 | self.ker_ck, |
| 203 | &mut self.clock, | 206 | &mut self.clock, |
| 204 | T::state(), | 207 | T::state(), |
| 208 | self.data_transfer_timeout, | ||
| 205 | ) | 209 | ) |
| 206 | .await | 210 | .await |
| 207 | } | 211 | } |
| @@ -218,7 +222,15 @@ impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P> { | |||
| 218 | 222 | ||
| 219 | // NOTE(unsafe) DataBlock uses align 4 | 223 | // NOTE(unsafe) DataBlock uses align 4 |
| 220 | let buf = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) }; | 224 | let buf = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) }; |
| 221 | inner.read_block(block_idx, buf, card_capacity, state).await | 225 | inner |
| 226 | .read_block( | ||
| 227 | block_idx, | ||
| 228 | buf, | ||
| 229 | card_capacity, | ||
| 230 | state, | ||
| 231 | self.data_transfer_timeout, | ||
| 232 | ) | ||
| 233 | .await | ||
| 222 | } | 234 | } |
| 223 | 235 | ||
| 224 | pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { | 236 | pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { |
| @@ -228,7 +240,9 @@ impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P> { | |||
| 228 | 240 | ||
| 229 | // NOTE(unsafe) DataBlock uses align 4 | 241 | // NOTE(unsafe) DataBlock uses align 4 |
| 230 | let buf = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) }; | 242 | let buf = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) }; |
| 231 | inner.write_block(block_idx, buf, card, state).await | 243 | inner |
| 244 | .write_block(block_idx, buf, card, state, self.data_transfer_timeout) | ||
| 245 | .await | ||
| 232 | } | 246 | } |
| 233 | 247 | ||
| 234 | /// Get a reference to the initialized card | 248 | /// Get a reference to the initialized card |
| @@ -302,6 +316,7 @@ impl SdmmcInner { | |||
| 302 | ker_ck: Hertz, | 316 | ker_ck: Hertz, |
| 303 | clock: &mut Hertz, | 317 | clock: &mut Hertz, |
| 304 | waker_reg: &AtomicWaker, | 318 | waker_reg: &AtomicWaker, |
| 319 | data_transfer_timeout: u32, | ||
| 305 | ) -> Result<(), Error> { | 320 | ) -> Result<(), Error> { |
| 306 | let regs = self.0; | 321 | let regs = self.0; |
| 307 | 322 | ||
| @@ -371,7 +386,8 @@ impl SdmmcInner { | |||
| 371 | card.csd = csd.into(); | 386 | card.csd = csd.into(); |
| 372 | 387 | ||
| 373 | self.select_card(Some(&card))?; | 388 | self.select_card(Some(&card))?; |
| 374 | self.get_scr(&mut card, waker_reg).await?; | 389 | self.get_scr(&mut card, waker_reg, data_transfer_timeout) |
| 390 | .await?; | ||
| 375 | 391 | ||
| 376 | // Set bus width | 392 | // Set bus width |
| 377 | let (width, acmd_arg) = match bus_width { | 393 | let (width, acmd_arg) = match bus_width { |
| @@ -404,12 +420,13 @@ impl SdmmcInner { | |||
| 404 | } | 420 | } |
| 405 | 421 | ||
| 406 | // Read status | 422 | // Read status |
| 407 | self.read_sd_status(&mut card, waker_reg).await?; | 423 | self.read_sd_status(&mut card, waker_reg, data_transfer_timeout) |
| 424 | .await?; | ||
| 408 | 425 | ||
| 409 | if freq.0 > 25_000_000 { | 426 | if freq.0 > 25_000_000 { |
| 410 | // Switch to SDR25 | 427 | // Switch to SDR25 |
| 411 | *signalling = self | 428 | *signalling = self |
| 412 | .switch_signalling_mode(Signalling::SDR25, waker_reg) | 429 | .switch_signalling_mode(Signalling::SDR25, waker_reg, data_transfer_timeout) |
| 413 | .await?; | 430 | .await?; |
| 414 | 431 | ||
| 415 | if *signalling == Signalling::SDR25 { | 432 | if *signalling == Signalling::SDR25 { |
| @@ -422,7 +439,8 @@ impl SdmmcInner { | |||
| 422 | } | 439 | } |
| 423 | } | 440 | } |
| 424 | // Read status after signalling change | 441 | // Read status after signalling change |
| 425 | self.read_sd_status(&mut card, waker_reg).await?; | 442 | self.read_sd_status(&mut card, waker_reg, data_transfer_timeout) |
| 443 | .await?; | ||
| 426 | old_card.replace(card); | 444 | old_card.replace(card); |
| 427 | } | 445 | } |
| 428 | 446 | ||
| @@ -435,6 +453,7 @@ impl SdmmcInner { | |||
| 435 | buffer: &mut [u32; 128], | 453 | buffer: &mut [u32; 128], |
| 436 | capacity: CardCapacity, | 454 | capacity: CardCapacity, |
| 437 | waker_reg: &AtomicWaker, | 455 | waker_reg: &AtomicWaker, |
| 456 | data_transfer_timeout: u32, | ||
| 438 | ) -> Result<(), Error> { | 457 | ) -> Result<(), Error> { |
| 439 | // Always read 1 block of 512 bytes | 458 | // Always read 1 block of 512 bytes |
| 440 | // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes | 459 | // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes |
| @@ -449,7 +468,13 @@ impl SdmmcInner { | |||
| 449 | 468 | ||
| 450 | let buf_addr = buffer as *mut [u32; 128] as u32; | 469 | let buf_addr = buffer as *mut [u32; 128] as u32; |
| 451 | unsafe { | 470 | unsafe { |
| 452 | self.prepare_datapath_transfer(buf_addr, 512, 9, Dir::CardToHost); | 471 | self.prepare_datapath_transfer( |
| 472 | buf_addr, | ||
| 473 | 512, | ||
| 474 | 9, | ||
| 475 | Dir::CardToHost, | ||
| 476 | data_transfer_timeout, | ||
| 477 | ); | ||
| 453 | self.data_interrupts(true); | 478 | self.data_interrupts(true); |
| 454 | } | 479 | } |
| 455 | self.cmd(Cmd::read_single_block(address), true)?; | 480 | self.cmd(Cmd::read_single_block(address), true)?; |
| @@ -485,6 +510,7 @@ impl SdmmcInner { | |||
| 485 | buffer: &[u32; 128], | 510 | buffer: &[u32; 128], |
| 486 | card: &mut Card, | 511 | card: &mut Card, |
| 487 | waker_reg: &AtomicWaker, | 512 | waker_reg: &AtomicWaker, |
| 513 | data_transfer_timeout: u32, | ||
| 488 | ) -> Result<(), Error> { | 514 | ) -> Result<(), Error> { |
| 489 | // Always read 1 block of 512 bytes | 515 | // Always read 1 block of 512 bytes |
| 490 | // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes | 516 | // SDSC cards are byte addressed hence the blockaddress is in multiples of 512 bytes |
| @@ -499,7 +525,13 @@ impl SdmmcInner { | |||
| 499 | 525 | ||
| 500 | let buf_addr = buffer as *const [u32; 128] as u32; | 526 | let buf_addr = buffer as *const [u32; 128] as u32; |
| 501 | unsafe { | 527 | unsafe { |
| 502 | self.prepare_datapath_transfer(buf_addr, 512, 9, Dir::HostToCard); | 528 | self.prepare_datapath_transfer( |
| 529 | buf_addr, | ||
| 530 | 512, | ||
| 531 | 9, | ||
| 532 | Dir::HostToCard, | ||
| 533 | data_transfer_timeout, | ||
| 534 | ); | ||
| 503 | self.data_interrupts(true); | 535 | self.data_interrupts(true); |
| 504 | } | 536 | } |
| 505 | self.cmd(Cmd::write_single_block(address), true)?; | 537 | self.cmd(Cmd::write_single_block(address), true)?; |
| @@ -527,16 +559,18 @@ impl SdmmcInner { | |||
| 527 | regs.idmactrlr().modify(|w| w.set_idmaen(false)); | 559 | regs.idmactrlr().modify(|w| w.set_idmaen(false)); |
| 528 | } | 560 | } |
| 529 | // TODO: Make this configurable | 561 | // TODO: Make this configurable |
| 530 | let mut timeout: u32 = 0xFFFF_FFFF; | 562 | let mut timeout: u32 = 0x00FF_FFFF; |
| 531 | 563 | ||
| 532 | // Try to read card status (ACMD13) | 564 | // Try to read card status (ACMD13) |
| 533 | while timeout > 0 { | 565 | while timeout > 0 { |
| 534 | match self.read_sd_status(card, waker_reg).await { | 566 | match self |
| 567 | .read_sd_status(card, waker_reg, data_transfer_timeout) | ||
| 568 | .await | ||
| 569 | { | ||
| 535 | Ok(_) => return Ok(()), | 570 | Ok(_) => return Ok(()), |
| 536 | Err(Error::Timeout) => (), // Try again | 571 | Err(Error::Timeout) => (), // Try again |
| 537 | Err(e) => return Err(e), | 572 | Err(e) => return Err(e), |
| 538 | } | 573 | } |
| 539 | |||
| 540 | timeout -= 1; | 574 | timeout -= 1; |
| 541 | } | 575 | } |
| 542 | Err(Error::SoftwareTimeout) | 576 | Err(Error::SoftwareTimeout) |
| @@ -573,6 +607,7 @@ impl SdmmcInner { | |||
| 573 | length_bytes: u32, | 607 | length_bytes: u32, |
| 574 | block_size: u8, | 608 | block_size: u8, |
| 575 | direction: Dir, | 609 | direction: Dir, |
| 610 | data_transfer_timeout: u32, | ||
| 576 | ) { | 611 | ) { |
| 577 | self::assert!(block_size <= 14, "Block size up to 2^14 bytes"); | 612 | self::assert!(block_size <= 14, "Block size up to 2^14 bytes"); |
| 578 | let regs = self.0; | 613 | let regs = self.0; |
| @@ -588,8 +623,8 @@ impl SdmmcInner { | |||
| 588 | 623 | ||
| 589 | // NOTE(unsafe) We have exclusive access to the regisers | 624 | // NOTE(unsafe) We have exclusive access to the regisers |
| 590 | 625 | ||
| 591 | // TODO: Make this configurable | 626 | regs.dtimer() |
| 592 | regs.dtimer().write(|w| w.set_datatime(5_000_000)); | 627 | .write(|w| w.set_datatime(data_transfer_timeout)); |
| 593 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); | 628 | regs.dlenr().write(|w| w.set_datalength(length_bytes)); |
| 594 | 629 | ||
| 595 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer_addr)); | 630 | regs.idmabase0r().write(|w| w.set_idmabase0(buffer_addr)); |
| @@ -637,6 +672,7 @@ impl SdmmcInner { | |||
| 637 | &self, | 672 | &self, |
| 638 | signalling: Signalling, | 673 | signalling: Signalling, |
| 639 | waker_reg: &AtomicWaker, | 674 | waker_reg: &AtomicWaker, |
| 675 | data_transfer_timeout: u32, | ||
| 640 | ) -> Result<Signalling, Error> { | 676 | ) -> Result<Signalling, Error> { |
| 641 | // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not | 677 | // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not |
| 642 | // necessary" | 678 | // necessary" |
| @@ -659,7 +695,13 @@ impl SdmmcInner { | |||
| 659 | let on_drop = OnDrop::new(|| unsafe { self.on_drop() }); | 695 | let on_drop = OnDrop::new(|| unsafe { self.on_drop() }); |
| 660 | 696 | ||
| 661 | unsafe { | 697 | unsafe { |
| 662 | self.prepare_datapath_transfer(status_addr, 64, 6, Dir::CardToHost); | 698 | self.prepare_datapath_transfer( |
| 699 | status_addr, | ||
| 700 | 64, | ||
| 701 | 6, | ||
| 702 | Dir::CardToHost, | ||
| 703 | data_transfer_timeout, | ||
| 704 | ); | ||
| 663 | self.data_interrupts(true); | 705 | self.data_interrupts(true); |
| 664 | } | 706 | } |
| 665 | self.cmd(Cmd::cmd6(set_function), true)?; // CMD6 | 707 | self.cmd(Cmd::cmd6(set_function), true)?; // CMD6 |
| @@ -724,7 +766,12 @@ impl SdmmcInner { | |||
| 724 | } | 766 | } |
| 725 | 767 | ||
| 726 | /// Reads the SD Status (ACMD13) | 768 | /// Reads the SD Status (ACMD13) |
| 727 | async fn read_sd_status(&self, card: &mut Card, waker_reg: &AtomicWaker) -> Result<(), Error> { | 769 | async fn read_sd_status( |
| 770 | &self, | ||
| 771 | card: &mut Card, | ||
| 772 | waker_reg: &AtomicWaker, | ||
| 773 | data_transfer_timeout: u32, | ||
| 774 | ) -> Result<(), Error> { | ||
| 728 | let rca = card.rca; | 775 | let rca = card.rca; |
| 729 | self.cmd(Cmd::set_block_length(64), false)?; // CMD16 | 776 | self.cmd(Cmd::set_block_length(64), false)?; // CMD16 |
| 730 | self.cmd(Cmd::app_cmd(rca << 16), false)?; // APP | 777 | self.cmd(Cmd::app_cmd(rca << 16), false)?; // APP |
| @@ -737,7 +784,13 @@ impl SdmmcInner { | |||
| 737 | let on_drop = OnDrop::new(|| unsafe { self.on_drop() }); | 784 | let on_drop = OnDrop::new(|| unsafe { self.on_drop() }); |
| 738 | 785 | ||
| 739 | unsafe { | 786 | unsafe { |
| 740 | self.prepare_datapath_transfer(status_addr, 64, 6, Dir::CardToHost); | 787 | self.prepare_datapath_transfer( |
| 788 | status_addr, | ||
| 789 | 64, | ||
| 790 | 6, | ||
| 791 | Dir::CardToHost, | ||
| 792 | data_transfer_timeout, | ||
| 793 | ); | ||
| 741 | self.data_interrupts(true); | 794 | self.data_interrupts(true); |
| 742 | } | 795 | } |
| 743 | self.cmd(Cmd::card_status(0), true)?; | 796 | self.cmd(Cmd::card_status(0), true)?; |
| @@ -832,7 +885,12 @@ impl SdmmcInner { | |||
| 832 | } | 885 | } |
| 833 | } | 886 | } |
| 834 | 887 | ||
| 835 | async fn get_scr(&self, card: &mut Card, waker_reg: &AtomicWaker) -> Result<(), Error> { | 888 | async fn get_scr( |
| 889 | &self, | ||
| 890 | card: &mut Card, | ||
| 891 | waker_reg: &AtomicWaker, | ||
| 892 | data_transfer_timeout: u32, | ||
| 893 | ) -> Result<(), Error> { | ||
| 836 | // Read the the 64-bit SCR register | 894 | // Read the the 64-bit SCR register |
| 837 | self.cmd(Cmd::set_block_length(8), false)?; // CMD16 | 895 | self.cmd(Cmd::set_block_length(8), false)?; // CMD16 |
| 838 | self.cmd(Cmd::app_cmd(card.rca << 16), false)?; | 896 | self.cmd(Cmd::app_cmd(card.rca << 16), false)?; |
| @@ -845,7 +903,7 @@ impl SdmmcInner { | |||
| 845 | let on_drop = OnDrop::new(move || unsafe { self.on_drop() }); | 903 | let on_drop = OnDrop::new(move || unsafe { self.on_drop() }); |
| 846 | 904 | ||
| 847 | unsafe { | 905 | unsafe { |
| 848 | self.prepare_datapath_transfer(scr_addr, 8, 3, Dir::CardToHost); | 906 | self.prepare_datapath_transfer(scr_addr, 8, 3, Dir::CardToHost, data_transfer_timeout); |
| 849 | self.data_interrupts(true); | 907 | self.data_interrupts(true); |
| 850 | } | 908 | } |
| 851 | self.cmd(Cmd::cmd51(), true)?; | 909 | self.cmd(Cmd::cmd51(), true)?; |
| @@ -905,36 +963,26 @@ impl SdmmcInner { | |||
| 905 | w.set_cmdtrans(data); | 963 | w.set_cmdtrans(data); |
| 906 | }); | 964 | }); |
| 907 | 965 | ||
| 908 | // TODO: Check if this timeout is necessary | ||
| 909 | let mut timeout: u32 = 0xFFFF_FFFF; | ||
| 910 | |||
| 911 | let mut status; | 966 | let mut status; |
| 912 | if cmd.resp == Response::None { | 967 | if cmd.resp == Response::None { |
| 913 | // Wait for CMDSENT or a timeout | 968 | // Wait for CMDSENT or a timeout |
| 914 | while { | 969 | while { |
| 915 | status = regs.star().read(); | 970 | status = regs.star().read(); |
| 916 | !(status.ctimeout() || status.cmdsent()) && timeout > 0 | 971 | !(status.ctimeout() || status.cmdsent()) |
| 917 | } { | 972 | } {} |
| 918 | timeout -= 1; | ||
| 919 | } | ||
| 920 | } else { | 973 | } else { |
| 921 | // Wait for CMDREND or CCRCFAIL or a timeout | 974 | // Wait for CMDREND or CCRCFAIL or a timeout |
| 922 | while { | 975 | while { |
| 923 | status = regs.star().read(); | 976 | status = regs.star().read(); |
| 924 | !(status.ctimeout() || status.cmdrend() || status.ccrcfail()) && timeout > 0 | 977 | !(status.ctimeout() || status.cmdrend() || status.ccrcfail()) |
| 925 | } { | 978 | } {} |
| 926 | timeout -= 1; | ||
| 927 | } | ||
| 928 | } | 979 | } |
| 929 | 980 | ||
| 930 | if status.ctimeout() { | 981 | if status.ctimeout() { |
| 931 | return Err(Error::Timeout); | 982 | return Err(Error::Timeout); |
| 932 | } else if timeout == 0 { | ||
| 933 | return Err(Error::SoftwareTimeout); | ||
| 934 | } else if status.ccrcfail() { | 983 | } else if status.ccrcfail() { |
| 935 | return Err(Error::Crc); | 984 | return Err(Error::Crc); |
| 936 | } | 985 | } |
| 937 | |||
| 938 | Ok(()) | 986 | Ok(()) |
| 939 | } | 987 | } |
| 940 | } | 988 | } |
| @@ -1321,11 +1369,76 @@ where | |||
| 1321 | const BUSWIDTH: BusWidth = BusWidth::One; | 1369 | const BUSWIDTH: BusWidth = BusWidth::One; |
| 1322 | 1370 | ||
| 1323 | fn configure(&mut self) { | 1371 | fn configure(&mut self) { |
| 1324 | self::todo!() | 1372 | let (clk_pin, cmd_pin, d0_pin) = self; |
| 1373 | |||
| 1374 | cortex_m::interrupt::free(|_| unsafe { | ||
| 1375 | // clk | ||
| 1376 | let block = clk_pin.block(); | ||
| 1377 | let n = clk_pin.pin() as usize; | ||
| 1378 | let afr_num = CLK::AF_NUM; | ||
| 1379 | configure_pin(block, n, afr_num, false); | ||
| 1380 | |||
| 1381 | // cmd | ||
| 1382 | let block = cmd_pin.block(); | ||
| 1383 | let n = cmd_pin.pin() as usize; | ||
| 1384 | let afr_num = CMD::AF_NUM; | ||
| 1385 | configure_pin(block, n, afr_num, true); | ||
| 1386 | |||
| 1387 | // d0 | ||
| 1388 | let block = d0_pin.block(); | ||
| 1389 | let n = d0_pin.pin() as usize; | ||
| 1390 | let afr_num = D0::AF_NUM; | ||
| 1391 | configure_pin(block, n, afr_num, true); | ||
| 1392 | }); | ||
| 1325 | } | 1393 | } |
| 1326 | 1394 | ||
| 1327 | fn deconfigure(&mut self) { | 1395 | fn deconfigure(&mut self) { |
| 1328 | self::todo!() | 1396 | use pac::gpio::vals::{Moder, Ospeedr, Pupdr}; |
| 1397 | |||
| 1398 | let (clk_pin, cmd_pin, d0_pin) = self; | ||
| 1399 | |||
| 1400 | cortex_m::interrupt::free(|_| unsafe { | ||
| 1401 | // clk | ||
| 1402 | let n = clk_pin.pin().into(); | ||
| 1403 | clk_pin | ||
| 1404 | .block() | ||
| 1405 | .moder() | ||
| 1406 | .modify(|w| w.set_moder(n, Moder::ANALOG)); | ||
| 1407 | clk_pin | ||
| 1408 | .block() | ||
| 1409 | .ospeedr() | ||
| 1410 | .modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED)); | ||
| 1411 | |||
| 1412 | // cmd | ||
| 1413 | let n = cmd_pin.pin().into(); | ||
| 1414 | cmd_pin | ||
| 1415 | .block() | ||
| 1416 | .moder() | ||
| 1417 | .modify(|w| w.set_moder(n, Moder::ANALOG)); | ||
| 1418 | cmd_pin | ||
| 1419 | .block() | ||
| 1420 | .ospeedr() | ||
| 1421 | .modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED)); | ||
| 1422 | cmd_pin | ||
| 1423 | .block() | ||
| 1424 | .pupdr() | ||
| 1425 | .modify(|w| w.set_pupdr(n, Pupdr::FLOATING)); | ||
| 1426 | |||
| 1427 | // d0 | ||
| 1428 | let n = d0_pin.pin().into(); | ||
| 1429 | d0_pin | ||
| 1430 | .block() | ||
| 1431 | .moder() | ||
| 1432 | .modify(|w| w.set_moder(n, Moder::ANALOG)); | ||
| 1433 | d0_pin | ||
| 1434 | .block() | ||
| 1435 | .ospeedr() | ||
| 1436 | .modify(|w| w.set_ospeedr(n, Ospeedr::LOWSPEED)); | ||
| 1437 | d0_pin | ||
| 1438 | .block() | ||
| 1439 | .pupdr() | ||
| 1440 | .modify(|w| w.set_pupdr(n, Pupdr::FLOATING)); | ||
| 1441 | }); | ||
| 1329 | } | 1442 | } |
| 1330 | } | 1443 | } |
| 1331 | 1444 | ||
| @@ -1359,63 +1472,79 @@ macro_rules! impl_sdmmc_pin { | |||
| 1359 | }; | 1472 | }; |
| 1360 | } | 1473 | } |
| 1361 | 1474 | ||
| 1362 | impl<'d, T: Instance, P: Pins<T>> BlockDevice for Sdmmc<'d, T, P> { | 1475 | #[cfg(feature = "sdmmc-rs")] |
| 1363 | type Error = Error; | 1476 | mod sdmmc_rs { |
| 1364 | #[rustfmt::skip] | 1477 | use super::*; |
| 1365 | type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a; | 1478 | use embedded_sdmmc::{Block, BlockCount, BlockDevice, BlockIdx}; |
| 1366 | #[rustfmt::skip] | 1479 | |
| 1367 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a; | 1480 | impl<'d, T: Instance, P: Pins<T>> BlockDevice for Sdmmc<'d, T, P> { |
| 1368 | 1481 | type Error = Error; | |
| 1369 | fn read<'a>( | 1482 | #[rustfmt::skip] |
| 1370 | &'a mut self, | 1483 | type ReadFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a; |
| 1371 | blocks: &'a mut [Block], | 1484 | #[rustfmt::skip] |
| 1372 | start_block_idx: BlockIdx, | 1485 | type WriteFuture<'a> where Self: 'a = impl Future<Output = Result<(), Self::Error>> + 'a; |
| 1373 | _reason: &str, | 1486 | |
| 1374 | ) -> Self::ReadFuture<'a> { | 1487 | fn read<'a>( |
| 1375 | async move { | 1488 | &'a mut self, |
| 1376 | let card_capacity = self.card()?.card_type; | 1489 | blocks: &'a mut [Block], |
| 1377 | let inner = T::inner(); | 1490 | start_block_idx: BlockIdx, |
| 1378 | let state = T::state(); | 1491 | _reason: &str, |
| 1379 | let mut address = start_block_idx.0; | 1492 | ) -> Self::ReadFuture<'a> { |
| 1380 | 1493 | async move { | |
| 1381 | for block in blocks.iter_mut() { | 1494 | let card_capacity = self.card()?.card_type; |
| 1382 | let block: &mut [u8; 512] = &mut block.contents; | 1495 | let inner = T::inner(); |
| 1383 | 1496 | let state = T::state(); | |
| 1384 | // NOTE(unsafe) Block uses align(4) | 1497 | let mut address = start_block_idx.0; |
| 1385 | let buf = unsafe { &mut *(block as *mut [u8; 512] as *mut [u32; 128]) }; | 1498 | |
| 1386 | inner.read_block(address, buf, card_capacity, state).await?; | 1499 | for block in blocks.iter_mut() { |
| 1387 | address += 1; | 1500 | let block: &mut [u8; 512] = &mut block.contents; |
| 1501 | |||
| 1502 | // NOTE(unsafe) Block uses align(4) | ||
| 1503 | let buf = unsafe { &mut *(block as *mut [u8; 512] as *mut [u32; 128]) }; | ||
| 1504 | inner | ||
| 1505 | .read_block( | ||
| 1506 | address, | ||
| 1507 | buf, | ||
| 1508 | card_capacity, | ||
| 1509 | state, | ||
| 1510 | self.data_transfer_timeout, | ||
| 1511 | ) | ||
| 1512 | .await?; | ||
| 1513 | address += 1; | ||
| 1514 | } | ||
| 1515 | Ok(()) | ||
| 1388 | } | 1516 | } |
| 1389 | Ok(()) | ||
| 1390 | } | 1517 | } |
| 1391 | } | ||
| 1392 | 1518 | ||
| 1393 | fn write<'a>( | 1519 | fn write<'a>( |
| 1394 | &'a mut self, | 1520 | &'a mut self, |
| 1395 | blocks: &'a [Block], | 1521 | blocks: &'a [Block], |
| 1396 | start_block_idx: BlockIdx, | 1522 | start_block_idx: BlockIdx, |
| 1397 | ) -> Self::WriteFuture<'a> { | 1523 | ) -> Self::WriteFuture<'a> { |
| 1398 | async move { | 1524 | async move { |
| 1399 | let card = self.card.as_mut().ok_or(Error::NoCard)?; | 1525 | let card = self.card.as_mut().ok_or(Error::NoCard)?; |
| 1400 | let inner = T::inner(); | 1526 | let inner = T::inner(); |
| 1401 | let state = T::state(); | 1527 | let state = T::state(); |
| 1402 | let mut address = start_block_idx.0; | 1528 | let mut address = start_block_idx.0; |
| 1403 | 1529 | ||
| 1404 | for block in blocks.iter() { | 1530 | for block in blocks.iter() { |
| 1405 | let block: &[u8; 512] = &block.contents; | 1531 | let block: &[u8; 512] = &block.contents; |
| 1406 | 1532 | ||
| 1407 | // NOTE(unsafe) DataBlock uses align 4 | 1533 | // NOTE(unsafe) DataBlock uses align 4 |
| 1408 | let buf = unsafe { &*(block as *const [u8; 512] as *const [u32; 128]) }; | 1534 | let buf = unsafe { &*(block as *const [u8; 512] as *const [u32; 128]) }; |
| 1409 | inner.write_block(address, buf, card, state).await?; | 1535 | inner |
| 1410 | address += 1; | 1536 | .write_block(address, buf, card, state, self.data_transfer_timeout) |
| 1537 | .await?; | ||
| 1538 | address += 1; | ||
| 1539 | } | ||
| 1540 | Ok(()) | ||
| 1411 | } | 1541 | } |
| 1412 | Ok(()) | ||
| 1413 | } | 1542 | } |
| 1414 | } | ||
| 1415 | 1543 | ||
| 1416 | fn num_blocks(&self) -> Result<BlockCount, Self::Error> { | 1544 | fn num_blocks(&self) -> Result<BlockCount, Self::Error> { |
| 1417 | let card = self.card()?; | 1545 | let card = self.card()?; |
| 1418 | let count = card.csd.block_count(); | 1546 | let count = card.csd.block_count(); |
| 1419 | Ok(BlockCount(count)) | 1547 | Ok(BlockCount(count)) |
| 1548 | } | ||
| 1420 | } | 1549 | } |
| 1421 | } | 1550 | } |
