diff options
| author | Thales Fragoso <[email protected]> | 2021-05-09 02:19:00 -0300 |
|---|---|---|
| committer | Thales Fragoso <[email protected]> | 2021-05-14 23:40:28 -0300 |
| commit | 72fb3a75200e143dbdfc1df6aec29a99adb7491d (patch) | |
| tree | 59d9c83ae7dcb74a786a9381a92c2de3b49c980d | |
| parent | 0b607ca80a990d7d3696cf95389e35e1dc5dc761 (diff) | |
Init working :)
| -rw-r--r-- | embassy-stm32/src/sdmmc_v2.rs | 92 |
1 files changed, 80 insertions, 12 deletions
diff --git a/embassy-stm32/src/sdmmc_v2.rs b/embassy-stm32/src/sdmmc_v2.rs index b96b9154e..5ab5313e1 100644 --- a/embassy-stm32/src/sdmmc_v2.rs +++ b/embassy-stm32/src/sdmmc_v2.rs | |||
| @@ -363,7 +363,6 @@ impl<'d> Sdmmc<'d> { | |||
| 363 | // NOTE(unsafe) We have exclusive access to the peripheral | 363 | // NOTE(unsafe) We have exclusive access to the peripheral |
| 364 | unsafe { | 364 | unsafe { |
| 365 | regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); | 365 | regs.power().modify(|w| w.set_pwrctrl(PowerCtrl::On as u8)); |
| 366 | defmt::info!("pwr"); | ||
| 367 | self.cmd(Cmd::idle(), false)?; | 366 | self.cmd(Cmd::idle(), false)?; |
| 368 | 367 | ||
| 369 | // Check if cards supports CMD8 (with pattern) | 368 | // Check if cards supports CMD8 (with pattern) |
| @@ -377,8 +376,6 @@ impl<'d> Sdmmc<'d> { | |||
| 377 | return Err(Error::UnsupportedCardVersion); | 376 | return Err(Error::UnsupportedCardVersion); |
| 378 | }; | 377 | }; |
| 379 | 378 | ||
| 380 | defmt::info!("CMD8"); | ||
| 381 | |||
| 382 | let ocr = loop { | 379 | let ocr = loop { |
| 383 | // Signal that next command is a app command | 380 | // Signal that next command is a app command |
| 384 | self.cmd(Cmd::app_cmd(0), false)?; // CMD55 | 381 | self.cmd(Cmd::app_cmd(0), false)?; // CMD55 |
| @@ -408,7 +405,6 @@ impl<'d> Sdmmc<'d> { | |||
| 408 | card.card_type = CardCapacity::SDSC; | 405 | card.card_type = CardCapacity::SDSC; |
| 409 | } | 406 | } |
| 410 | card.ocr = ocr; | 407 | card.ocr = ocr; |
| 411 | defmt::info!("OCR"); | ||
| 412 | 408 | ||
| 413 | self.cmd(Cmd::all_send_cid(), false)?; // CMD2 | 409 | self.cmd(Cmd::all_send_cid(), false)?; // CMD2 |
| 414 | let cid0 = regs.respr(0).read().cardstatus1() as u128; | 410 | let cid0 = regs.respr(0).read().cardstatus1() as u128; |
| @@ -430,12 +426,8 @@ impl<'d> Sdmmc<'d> { | |||
| 430 | card.csd = csd.into(); | 426 | card.csd = csd.into(); |
| 431 | 427 | ||
| 432 | self.select_card(Some(&card))?; | 428 | self.select_card(Some(&card))?; |
| 433 | |||
| 434 | defmt::info!("select"); | ||
| 435 | self.get_scr(&mut card).await?; | 429 | self.get_scr(&mut card).await?; |
| 436 | 430 | ||
| 437 | defmt::info!("scr"); | ||
| 438 | |||
| 439 | // Set bus width | 431 | // Set bus width |
| 440 | let (width, acmd_arg) = match self.bus_width { | 432 | let (width, acmd_arg) = match self.bus_width { |
| 441 | BusWidth::Eight => unimplemented!(), | 433 | BusWidth::Eight => unimplemented!(), |
| @@ -472,7 +464,7 @@ impl<'d> Sdmmc<'d> { | |||
| 472 | 464 | ||
| 473 | if freq.0 > 25_000_000 { | 465 | if freq.0 > 25_000_000 { |
| 474 | // Switch to SDR25 | 466 | // Switch to SDR25 |
| 475 | self.signalling = self.switch_signalling_mode(Signalling::SDR25)?; | 467 | self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; |
| 476 | 468 | ||
| 477 | if self.signalling == Signalling::SDR25 { | 469 | if self.signalling == Signalling::SDR25 { |
| 478 | // Set final clock frequency | 470 | // Set final clock frequency |
| @@ -598,8 +590,84 @@ impl<'d> Sdmmc<'d> { | |||
| 598 | /// Attempt to set a new signalling mode. The selected | 590 | /// Attempt to set a new signalling mode. The selected |
| 599 | /// signalling mode is returned. Expects the current clock | 591 | /// signalling mode is returned. Expects the current clock |
| 600 | /// frequency to be > 12.5MHz. | 592 | /// frequency to be > 12.5MHz. |
| 601 | fn switch_signalling_mode(&self, signalling: Signalling) -> Result<Signalling, Error> { | 593 | async fn switch_signalling_mode( |
| 602 | self::todo!() | 594 | &mut self, |
| 595 | signalling: Signalling, | ||
| 596 | ) -> Result<Signalling, Error> { | ||
| 597 | // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not | ||
| 598 | // necessary" | ||
| 599 | |||
| 600 | let set_function = 0x8000_0000 | ||
| 601 | | match signalling { | ||
| 602 | // See PLSS v7_10 Table 4-11 | ||
| 603 | Signalling::DDR50 => 0xFF_FF04, | ||
| 604 | Signalling::SDR104 => 0xFF_1F03, | ||
| 605 | Signalling::SDR50 => 0xFF_1F02, | ||
| 606 | Signalling::SDR25 => 0xFF_FF01, | ||
| 607 | Signalling::SDR12 => 0xFF_FF00, | ||
| 608 | }; | ||
| 609 | |||
| 610 | let mut status = [0u32; 16]; | ||
| 611 | let status_addr = &mut status as *mut [u32; 16] as u32; | ||
| 612 | |||
| 613 | // Arm `OnDrop` after the buffer, so it will be dropped first | ||
| 614 | let regs = self.regs(); | ||
| 615 | let on_drop = OnDrop::new(move || unsafe { Self::on_drop(regs) }); | ||
| 616 | |||
| 617 | unsafe { | ||
| 618 | self.prepare_datapath_transfer(status_addr, 64, 6, Dir::CardToHost); | ||
| 619 | Self::data_interrupts(regs, true); | ||
| 620 | } | ||
| 621 | self.cmd(Cmd::cmd6(set_function), true)?; // CMD6 | ||
| 622 | |||
| 623 | let res = poll_fn(|cx| { | ||
| 624 | self.store_waker_and_unmask(&cx); | ||
| 625 | let status = unsafe { regs.star().read() }; | ||
| 626 | |||
| 627 | if status.dcrcfail() { | ||
| 628 | return Poll::Ready(Err(Error::Crc)); | ||
| 629 | } else if status.dtimeout() { | ||
| 630 | return Poll::Ready(Err(Error::Timeout)); | ||
| 631 | } else if status.dataend() { | ||
| 632 | return Poll::Ready(Ok(())); | ||
| 633 | } | ||
| 634 | Poll::Pending | ||
| 635 | }) | ||
| 636 | .await; | ||
| 637 | |||
| 638 | unsafe { | ||
| 639 | Self::data_interrupts(regs, false); | ||
| 640 | } | ||
| 641 | Self::clear_interrupt_flags(regs); | ||
| 642 | |||
| 643 | // Host is allowed to use the new functions at least 8 | ||
| 644 | // clocks after the end of the switch command | ||
| 645 | // transaction. We know the current clock period is < 80ns, | ||
| 646 | // so a total delay of 640ns is required here | ||
| 647 | for _ in 0..300 { | ||
| 648 | cortex_m::asm::nop(); | ||
| 649 | } | ||
| 650 | |||
| 651 | match res { | ||
| 652 | Ok(_) => { | ||
| 653 | on_drop.defuse(); | ||
| 654 | unsafe { | ||
| 655 | regs.idmactrlr().modify(|w| w.set_idmaen(false)); | ||
| 656 | } | ||
| 657 | // Function Selection of Function Group 1 | ||
| 658 | let selection = (u32::from_be(status[4]) >> 24) & 0xF; | ||
| 659 | |||
| 660 | match selection { | ||
| 661 | 0 => Ok(Signalling::SDR12), | ||
| 662 | 1 => Ok(Signalling::SDR25), | ||
| 663 | 2 => Ok(Signalling::SDR50), | ||
| 664 | 3 => Ok(Signalling::SDR104), | ||
| 665 | 4 => Ok(Signalling::DDR50), | ||
| 666 | _ => Err(Error::UnsupportedCardType), | ||
| 667 | } | ||
| 668 | } | ||
| 669 | Err(e) => Err(e), | ||
| 670 | } | ||
| 603 | } | 671 | } |
| 604 | 672 | ||
| 605 | /// Query the card status (CMD13, returns R1) | 673 | /// Query the card status (CMD13, returns R1) |
| @@ -695,6 +763,7 @@ impl<'d> Sdmmc<'d> { | |||
| 695 | w.set_dtimeoutc(true); | 763 | w.set_dtimeoutc(true); |
| 696 | w.set_txunderrc(true); | 764 | w.set_txunderrc(true); |
| 697 | w.set_rxoverrc(true); | 765 | w.set_rxoverrc(true); |
| 766 | w.set_cmdrendc(true); | ||
| 698 | w.set_cmdsentc(true); | 767 | w.set_cmdsentc(true); |
| 699 | w.set_dataendc(true); | 768 | w.set_dataendc(true); |
| 700 | w.set_dholdc(true); | 769 | w.set_dholdc(true); |
| @@ -786,7 +855,6 @@ impl<'d> Sdmmc<'d> { | |||
| 786 | unsafe { | 855 | unsafe { |
| 787 | // CP state machine must be idle | 856 | // CP state machine must be idle |
| 788 | while regs.star().read().cpsmact() {} | 857 | while regs.star().read().cpsmact() {} |
| 789 | defmt::info!("cpsma idle"); | ||
| 790 | 858 | ||
| 791 | // Command arg | 859 | // Command arg |
| 792 | regs.argr().write(|w| w.set_cmdarg(cmd.arg)); | 860 | regs.argr().write(|w| w.set_cmdarg(cmd.arg)); |
