aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorchemicstry <[email protected]>2022-03-16 20:20:39 +0200
committerchemicstry <[email protected]>2022-03-16 20:20:39 +0200
commit8a8e5c4b736adf1d83f6849d7f86c26dabf73675 (patch)
treea8439e348929415c0e767c4669713906aab24cc4
parent48fc48ea7d0d73c7071e0f353c52eda10ad5a1b4 (diff)
Fix SDMMC v2 and add H7 example
-rw-r--r--embassy-stm32/src/sdmmc/mod.rs94
-rw-r--r--examples/stm32f4/src/bin/sdmmc.rs23
-rw-r--r--examples/stm32h7/src/bin/sdmmc.rs42
m---------stm32-data0
4 files changed, 119 insertions, 40 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs
index 18e53ce10..60060c79e 100644
--- a/embassy-stm32/src/sdmmc/mod.rs
+++ b/embassy-stm32/src/sdmmc/mod.rs
@@ -12,7 +12,7 @@ use embassy_hal_common::unborrow;
12use futures::future::poll_fn; 12use futures::future::poll_fn;
13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR}; 13use sdio_host::{BusWidth, CardCapacity, CardStatus, CurrentState, SDStatus, CID, CSD, OCR, SCR};
14 14
15use crate::dma::{NoDma, TransferOptions}; 15use crate::dma::NoDma;
16use crate::gpio::sealed::AFType; 16use crate::gpio::sealed::AFType;
17use crate::gpio::{Pull, Speed}; 17use crate::gpio::{Pull, Speed};
18use crate::interrupt::Interrupt; 18use crate::interrupt::Interrupt;
@@ -191,26 +191,23 @@ pub struct Sdmmc<'d, T: Instance, P: Pins<T>, Dma = NoDma> {
191 card: Option<Card>, 191 card: Option<Card>,
192} 192}
193 193
194#[cfg(sdmmc_v1)]
194impl<'d, T: Instance, P: Pins<T>, Dma: SdioDma<T>> Sdmmc<'d, T, P, Dma> { 195impl<'d, T: Instance, P: Pins<T>, Dma: SdioDma<T>> Sdmmc<'d, T, P, Dma> {
195 /// # Safety 196 pub fn new(
196 ///
197 /// Futures that borrow this type can't be leaked
198 #[inline(always)]
199 pub unsafe fn new(
200 _peripheral: impl Unborrow<Target = T> + 'd, 197 _peripheral: impl Unborrow<Target = T> + 'd,
201 pins: impl Unborrow<Target = P> + 'd, 198 pins: impl Unborrow<Target = P> + 'd,
202 irq: impl Unborrow<Target = T::Interrupt> + 'd, 199 irq: impl Unborrow<Target = T::Interrupt> + 'd,
203 config: Config, 200 config: Config,
204 dma: Dma, 201 dma: impl Unborrow<Target = Dma> + 'd,
205 ) -> Self { 202 ) -> Self {
206 unborrow!(irq, pins); 203 unborrow!(irq, pins, dma);
207 pins.configure(); 204 pins.configure();
208 205
209 T::enable(); 206 T::enable();
210 T::reset(); 207 T::reset();
211 208
212 let inner = T::inner(); 209 let inner = T::inner();
213 let clock = inner.new_inner(T::frequency()); 210 let clock = unsafe { inner.new_inner(T::frequency()) };
214 211
215 irq.set_handler(Self::on_interrupt); 212 irq.set_handler(Self::on_interrupt);
216 irq.unpend(); 213 irq.unpend();
@@ -227,7 +224,45 @@ impl<'d, T: Instance, P: Pins<T>, Dma: SdioDma<T>> Sdmmc<'d, T, P, Dma> {
227 card: None, 224 card: None,
228 } 225 }
229 } 226 }
227}
228
229#[cfg(sdmmc_v2)]
230impl<'d, T: Instance, P: Pins<T>> Sdmmc<'d, T, P, NoDma> {
231 pub fn new(
232 _peripheral: impl Unborrow<Target = T> + 'd,
233 pins: impl Unborrow<Target = P> + 'd,
234 irq: impl Unborrow<Target = T::Interrupt> + 'd,
235 config: Config,
236 ) -> Self {
237 unborrow!(irq, pins);
238 pins.configure();
239
240 T::enable();
241 T::reset();
242
243 info!("Freq: {}", T::frequency().0);
244
245 let inner = T::inner();
246 let clock = unsafe { inner.new_inner(T::frequency()) };
247
248 irq.set_handler(Self::on_interrupt);
249 irq.unpend();
250 irq.enable();
251
252 Self {
253 sdmmc: PhantomData,
254 pins,
255 irq,
256 config,
257 dma: NoDma,
258 clock,
259 signalling: Default::default(),
260 card: None,
261 }
262 }
263}
230 264
265impl<'d, T: Instance, P: Pins<T>, Dma: SdioDma<T>> Sdmmc<'d, T, P, Dma> {
231 #[inline(always)] 266 #[inline(always)]
232 pub async fn init_card(&mut self, freq: impl Into<Hertz>) -> Result<(), Error> { 267 pub async fn init_card(&mut self, freq: impl Into<Hertz>) -> Result<(), Error> {
233 let inner = T::inner(); 268 let inner = T::inner();
@@ -687,7 +722,7 @@ impl SdmmcInner {
687 length_bytes: u32, 722 length_bytes: u32,
688 block_size: u8, 723 block_size: u8,
689 data_transfer_timeout: u32, 724 data_transfer_timeout: u32,
690 dma: &mut Dma, 725 #[allow(unused_variables)] dma: &mut Dma,
691 ) { 726 ) {
692 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 727 assert!(block_size <= 14, "Block size up to 2^14 bytes");
693 let regs = self.0; 728 let regs = self.0;
@@ -705,13 +740,13 @@ impl SdmmcInner {
705 cfg_if::cfg_if! { 740 cfg_if::cfg_if! {
706 if #[cfg(sdmmc_v1)] { 741 if #[cfg(sdmmc_v1)] {
707 let request = dma.request(); 742 let request = dma.request();
708 dma.start_read(request, regs.fifor().ptr() as *const u32, buffer, TransferOptions { 743 dma.start_read(request, regs.fifor().ptr() as *const u32, buffer, crate::dma::TransferOptions {
709 pburst: crate::dma::Burst::Incr4, 744 pburst: crate::dma::Burst::Incr4,
710 flow_ctrl: crate::dma::FlowControl::Peripheral, 745 flow_ctrl: crate::dma::FlowControl::Peripheral,
711 ..Default::default() 746 ..Default::default()
712 }); 747 });
713 } else if #[cfg(sdmmc_v2)] { 748 } else if #[cfg(sdmmc_v2)] {
714 regs.idmabase0r().write(|w| w.set_idmabase0(buffer_addr)); 749 regs.idmabase0r().write(|w| w.set_idmabase0(buffer as *mut u32 as u32));
715 regs.idmactrlr().modify(|w| w.set_idmaen(true)); 750 regs.idmactrlr().modify(|w| w.set_idmaen(true));
716 } 751 }
717 } 752 }
@@ -736,7 +771,7 @@ impl SdmmcInner {
736 length_bytes: u32, 771 length_bytes: u32,
737 block_size: u8, 772 block_size: u8,
738 data_transfer_timeout: u32, 773 data_transfer_timeout: u32,
739 dma: &mut Dma, 774 #[allow(unused_variables)] dma: &mut Dma,
740 ) { 775 ) {
741 assert!(block_size <= 14, "Block size up to 2^14 bytes"); 776 assert!(block_size <= 14, "Block size up to 2^14 bytes");
742 let regs = self.0; 777 let regs = self.0;
@@ -754,13 +789,13 @@ impl SdmmcInner {
754 cfg_if::cfg_if! { 789 cfg_if::cfg_if! {
755 if #[cfg(sdmmc_v1)] { 790 if #[cfg(sdmmc_v1)] {
756 let request = dma.request(); 791 let request = dma.request();
757 dma.start_write(request, buffer, regs.fifor().ptr() as *mut u32, TransferOptions { 792 dma.start_write(request, buffer, regs.fifor().ptr() as *mut u32, crate::dma::TransferOptions {
758 pburst: crate::dma::Burst::Incr4, 793 pburst: crate::dma::Burst::Incr4,
759 flow_ctrl: crate::dma::FlowControl::Peripheral, 794 flow_ctrl: crate::dma::FlowControl::Peripheral,
760 ..Default::default() 795 ..Default::default()
761 }); 796 });
762 } else if #[cfg(sdmmc_v2)] { 797 } else if #[cfg(sdmmc_v2)] {
763 regs.idmabase0r().write(|w| w.set_idmabase0(buffer_addr)); 798 regs.idmabase0r().write(|w| w.set_idmabase0(buffer as *const u32 as u32));
764 regs.idmactrlr().modify(|w| w.set_idmaen(true)); 799 regs.idmactrlr().modify(|w| w.set_idmaen(true));
765 } 800 }
766 } 801 }
@@ -1104,7 +1139,7 @@ impl SdmmcInner {
1104 while self.cmd_active() {} 1139 while self.cmd_active() {}
1105 1140
1106 // Command arg 1141 // Command arg
1107 regs.argr().write(|w| w.set_cmdargr(cmd.arg)); 1142 regs.argr().write(|w| w.set_cmdarg(cmd.arg));
1108 1143
1109 // Command index and start CP State Machine 1144 // Command index and start CP State Machine
1110 regs.cmdr().write(|w| { 1145 regs.cmdr().write(|w| {
@@ -1113,14 +1148,13 @@ impl SdmmcInner {
1113 w.set_cmdindex(cmd.cmd); 1148 w.set_cmdindex(cmd.cmd);
1114 w.set_cpsmen(true); 1149 w.set_cpsmen(true);
1115 1150
1116 cfg_if::cfg_if! { 1151 #[cfg(sdmmc_v2)]
1117 if #[cfg(sdmmc_v2)] { 1152 {
1118 // Special mode in CP State Machine 1153 // Special mode in CP State Machine
1119 // CMD12: Stop Transmission 1154 // CMD12: Stop Transmission
1120 let cpsm_stop_transmission = cmd.cmd == 12; 1155 let cpsm_stop_transmission = cmd.cmd == 12;
1121 w.set_cmdstop(cpsm_stop_transmission); 1156 w.set_cmdstop(cpsm_stop_transmission);
1122 w.set_cmdtrans(data); 1157 w.set_cmdtrans(data);
1123 }
1124 } 1158 }
1125 }); 1159 });
1126 1160
@@ -1160,7 +1194,7 @@ impl SdmmcInner {
1160 while self.cmd_active() {} 1194 while self.cmd_active() {}
1161 1195
1162 // Command arg 1196 // Command arg
1163 regs.argr().write(|w| w.set_cmdargr(0)); 1197 regs.argr().write(|w| w.set_cmdarg(0));
1164 1198
1165 // Command index and start CP State Machine 1199 // Command index and start CP State Machine
1166 regs.cmdr().write(|w| { 1200 regs.cmdr().write(|w| {
@@ -1300,7 +1334,15 @@ pin_trait!(D5Pin, Instance);
1300pin_trait!(D6Pin, Instance); 1334pin_trait!(D6Pin, Instance);
1301pin_trait!(D7Pin, Instance); 1335pin_trait!(D7Pin, Instance);
1302 1336
1303dma_trait!(SdioDma, Instance); 1337cfg_if::cfg_if! {
1338 if #[cfg(sdmmc_v1)] {
1339 dma_trait!(SdioDma, Instance);
1340 } else if #[cfg(sdmmc_v2)] {
1341 // SDMMCv2 uses internal DMA
1342 pub trait SdioDma<T: Instance> {}
1343 impl<T: Instance> SdioDma<T> for NoDma {}
1344 }
1345}
1304 1346
1305pub trait Pins<T: Instance>: sealed::Pins<T> + 'static { 1347pub trait Pins<T: Instance>: sealed::Pins<T> + 'static {
1306 const BUSWIDTH: BusWidth; 1348 const BUSWIDTH: BusWidth;
diff --git a/examples/stm32f4/src/bin/sdmmc.rs b/examples/stm32f4/src/bin/sdmmc.rs
index 46ac44500..301d7dda0 100644
--- a/examples/stm32f4/src/bin/sdmmc.rs
+++ b/examples/stm32f4/src/bin/sdmmc.rs
@@ -13,28 +13,23 @@ use example_common::*;
13 13
14fn config() -> Config { 14fn config() -> Config {
15 let mut config = Config::default(); 15 let mut config = Config::default();
16 config.rcc.hse = Some(8.mhz().into()); 16 config.rcc.sys_ck = Some(48.mhz().into());
17 config.rcc.hclk = Some(48.mhz().into());
18 config.rcc.pclk2 = Some(48.mhz().into());
19 config.rcc.pll48 = true;
20 config 17 config
21} 18}
22 19
23#[embassy::main(config = "config()")] 20#[embassy::main(config = "config()")]
24async fn main(_spawner: Spawner, p: Peripherals) -> ! { 21async fn main(_spawner: Spawner, p: Peripherals) -> ! {
25 info!("Hello World, dude!"); 22 info!("Hello World!");
26 23
27 let irq = interrupt::take!(SDIO); 24 let irq = interrupt::take!(SDIO);
28 25
29 let mut sdmmc = unsafe { 26 let mut sdmmc = Sdmmc::new(
30 Sdmmc::new( 27 p.SDIO,
31 p.SDIO, 28 (p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11),
32 (p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11), 29 irq,
33 irq, 30 Default::default(),
34 Default::default(), 31 p.DMA2_CH3,
35 p.DMA2_CH3, 32 );
36 )
37 };
38 33
39 info!("Configured clock: {}", sdmmc.clock.0); 34 info!("Configured clock: {}", sdmmc.clock.0);
40 35
diff --git a/examples/stm32h7/src/bin/sdmmc.rs b/examples/stm32h7/src/bin/sdmmc.rs
new file mode 100644
index 000000000..255c5568f
--- /dev/null
+++ b/examples/stm32h7/src/bin/sdmmc.rs
@@ -0,0 +1,42 @@
1#![no_std]
2#![no_main]
3#![feature(type_alias_impl_trait)]
4
5#[path = "../example_common.rs"]
6mod example_common;
7
8use embassy::executor::Spawner;
9use embassy_stm32::sdmmc::Sdmmc;
10use embassy_stm32::time::U32Ext;
11use embassy_stm32::{interrupt, Config, Peripherals};
12use example_common::*;
13
14fn config() -> Config {
15 let mut config = Config::default();
16 config.rcc.sys_ck = Some(200.mhz().into());
17 config
18}
19
20#[embassy::main(config = "config()")]
21async fn main(_spawner: Spawner, p: Peripherals) -> ! {
22 info!("Hello World!");
23
24 let irq = interrupt::take!(SDMMC1);
25
26 let mut sdmmc = Sdmmc::new(
27 p.SDMMC1,
28 (p.PC12, p.PD2, p.PC8, p.PC9, p.PC10, p.PC11),
29 irq,
30 Default::default(),
31 );
32
33 info!("Configured clock: {}", sdmmc.clock.0);
34
35 unwrap!(sdmmc.init_card(25.mhz()).await);
36
37 let card = unwrap!(sdmmc.card());
38
39 info!("Card: {:#?}", Debug2Format(card));
40
41 loop {}
42}
diff --git a/stm32-data b/stm32-data
Subproject 2b8eb83c7aa01200f8215248793da2489209116 Subproject 938770167164faa46970af4f6096ec7c8b19591