diff options
| author | xoviat <[email protected]> | 2025-12-09 11:35:37 -0600 |
|---|---|---|
| committer | xoviat <[email protected]> | 2025-12-09 11:35:37 -0600 |
| commit | 142c237b781daf0f5bc2ac6e165d14454b87544c (patch) | |
| tree | 6f5c1c51d5f5f6b1a06486a18bf81988b1bd7e13 /embassy-stm32 | |
| parent | 7087ad7d45396e139fcbd710084db0d9dac7ecb8 (diff) | |
sdmmc: use storage devices with reference
Diffstat (limited to 'embassy-stm32')
| -rw-r--r-- | embassy-stm32/src/sdmmc/mod.rs | 718 | ||||
| -rw-r--r-- | embassy-stm32/src/time.rs | 2 |
2 files changed, 403 insertions, 317 deletions
diff --git a/embassy-stm32/src/sdmmc/mod.rs b/embassy-stm32/src/sdmmc/mod.rs index 74a6f13fa..f862d73b1 100644 --- a/embassy-stm32/src/sdmmc/mod.rs +++ b/embassy-stm32/src/sdmmc/mod.rs | |||
| @@ -9,7 +9,6 @@ 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; | ||
| 13 | use embassy_sync::waitqueue::AtomicWaker; | 12 | use embassy_sync::waitqueue::AtomicWaker; |
| 14 | use sdio_host::common_cmd::{self, Resp, ResponseLen}; | 13 | use sdio_host::common_cmd::{self, Resp, ResponseLen}; |
| 15 | use sdio_host::emmc::{EMMC, ExtCSD}; | 14 | use sdio_host::emmc::{EMMC, ExtCSD}; |
| @@ -165,6 +164,55 @@ pub enum Error { | |||
| 165 | StBitErr, | 164 | StBitErr, |
| 166 | } | 165 | } |
| 167 | 166 | ||
| 167 | pub trait Addressable: Sized { | ||
| 168 | type Ext; | ||
| 169 | |||
| 170 | /// Get this peripheral's address on the SDMMC bus | ||
| 171 | fn get_address(&self) -> u16; | ||
| 172 | |||
| 173 | /// Is this a standard or high capacity peripheral? | ||
| 174 | fn get_capacity(&self) -> CardCapacity; | ||
| 175 | |||
| 176 | /// Size in bytes | ||
| 177 | fn size(&self) -> u64; | ||
| 178 | |||
| 179 | async fn write_block<'a>( | ||
| 180 | &mut self, | ||
| 181 | sdmmc: &mut Sdmmc<'a>, | ||
| 182 | block_idx: u32, | ||
| 183 | buffer: &DataBlock, | ||
| 184 | ) -> Result<(), Error> { | ||
| 185 | sdmmc.write_block(self, block_idx, buffer).await | ||
| 186 | } | ||
| 187 | |||
| 188 | async fn write_blocks<'a>( | ||
| 189 | &mut self, | ||
| 190 | sdmmc: &mut Sdmmc<'a>, | ||
| 191 | block_idx: u32, | ||
| 192 | blocks: &[DataBlock], | ||
| 193 | ) -> Result<(), Error> { | ||
| 194 | sdmmc.write_blocks(self, block_idx, blocks).await | ||
| 195 | } | ||
| 196 | |||
| 197 | async fn read_block<'a>( | ||
| 198 | &mut self, | ||
| 199 | sdmmc: &mut Sdmmc<'a>, | ||
| 200 | block_idx: u32, | ||
| 201 | buffer: &mut DataBlock, | ||
| 202 | ) -> Result<(), Error> { | ||
| 203 | sdmmc.read_block(self, block_idx, buffer).await | ||
| 204 | } | ||
| 205 | |||
| 206 | async fn read_blocks<'a>( | ||
| 207 | &mut self, | ||
| 208 | sdmmc: &mut Sdmmc<'a>, | ||
| 209 | block_idx: u32, | ||
| 210 | blocks: &mut [DataBlock], | ||
| 211 | ) -> Result<(), Error> { | ||
| 212 | sdmmc.read_blocks(self, block_idx, blocks).await | ||
| 213 | } | ||
| 214 | } | ||
| 215 | |||
| 168 | #[derive(Clone, Copy, Debug, Default)] | 216 | #[derive(Clone, Copy, Debug, Default)] |
| 169 | /// SD Card | 217 | /// SD Card |
| 170 | pub struct Card { | 218 | pub struct Card { |
| @@ -184,6 +232,178 @@ pub struct Card { | |||
| 184 | pub status: SDStatus, | 232 | pub status: SDStatus, |
| 185 | } | 233 | } |
| 186 | 234 | ||
| 235 | impl Card { | ||
| 236 | /// Switch mode using CMD6. | ||
| 237 | /// | ||
| 238 | /// Attempt to set a new signalling mode. The selected | ||
| 239 | /// signalling mode is returned. Expects the current clock | ||
| 240 | /// frequency to be > 12.5MHz. | ||
| 241 | /// | ||
| 242 | /// SD only. | ||
| 243 | pub async fn switch_signalling_mode<'a>( | ||
| 244 | &mut self, | ||
| 245 | sdmmc: &mut Sdmmc<'a>, | ||
| 246 | cmd_block: &mut CmdBlock, | ||
| 247 | signalling: Signalling, | ||
| 248 | ) -> Result<Signalling, Error> { | ||
| 249 | // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not | ||
| 250 | // necessary" | ||
| 251 | |||
| 252 | let set_function = 0x8000_0000 | ||
| 253 | | match signalling { | ||
| 254 | // See PLSS v7_10 Table 4-11 | ||
| 255 | Signalling::DDR50 => 0xFF_FF04, | ||
| 256 | Signalling::SDR104 => 0xFF_1F03, | ||
| 257 | Signalling::SDR50 => 0xFF_1F02, | ||
| 258 | Signalling::SDR25 => 0xFF_FF01, | ||
| 259 | Signalling::SDR12 => 0xFF_FF00, | ||
| 260 | }; | ||
| 261 | |||
| 262 | // Arm `OnDrop` after the buffer, so it will be dropped first | ||
| 263 | let on_drop = OnDrop::new(|| sdmmc.on_drop()); | ||
| 264 | |||
| 265 | let transfer = sdmmc.prepare_datapath_read( | ||
| 266 | &sdmmc.config, | ||
| 267 | #[cfg(sdmmc_v1)] | ||
| 268 | &mut self.dma, | ||
| 269 | cmd_block.as_mut(), | ||
| 270 | 64, | ||
| 271 | 6, | ||
| 272 | ); | ||
| 273 | sdmmc.enable_interrupts(); | ||
| 274 | sdmmc.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6 | ||
| 275 | |||
| 276 | let res = sdmmc.complete_datapath_transfer(true).await; | ||
| 277 | |||
| 278 | // Host is allowed to use the new functions at least 8 | ||
| 279 | // clocks after the end of the switch command | ||
| 280 | // transaction. We know the current clock period is < 80ns, | ||
| 281 | // so a total delay of 640ns is required here | ||
| 282 | for _ in 0..300 { | ||
| 283 | cortex_m::asm::nop(); | ||
| 284 | } | ||
| 285 | |||
| 286 | match res { | ||
| 287 | Ok(_) => { | ||
| 288 | on_drop.defuse(); | ||
| 289 | sdmmc.stop_datapath(); | ||
| 290 | drop(transfer); | ||
| 291 | |||
| 292 | // Function Selection of Function Group 1 | ||
| 293 | let selection = (u32::from_be(cmd_block[4]) >> 24) & 0xF; | ||
| 294 | |||
| 295 | match selection { | ||
| 296 | 0 => Ok(Signalling::SDR12), | ||
| 297 | 1 => Ok(Signalling::SDR25), | ||
| 298 | 2 => Ok(Signalling::SDR50), | ||
| 299 | 3 => Ok(Signalling::SDR104), | ||
| 300 | 4 => Ok(Signalling::DDR50), | ||
| 301 | _ => Err(Error::UnsupportedCardType), | ||
| 302 | } | ||
| 303 | } | ||
| 304 | Err(e) => Err(e), | ||
| 305 | } | ||
| 306 | } | ||
| 307 | |||
| 308 | /// Reads the SCR register. | ||
| 309 | /// | ||
| 310 | /// SD only. | ||
| 311 | pub async fn get_scr<'a>(&mut self, sdmmc: &mut Sdmmc<'a>, cmd_block: &mut CmdBlock) -> Result<(), Error> { | ||
| 312 | // Read the 64-bit SCR register | ||
| 313 | sdmmc.cmd(common_cmd::set_block_length(8), false)?; // CMD16 | ||
| 314 | sdmmc.cmd(common_cmd::app_cmd(self.rca), false)?; | ||
| 315 | |||
| 316 | let scr = &mut cmd_block.0[..2]; | ||
| 317 | |||
| 318 | // Arm `OnDrop` after the buffer, so it will be dropped first | ||
| 319 | let on_drop = OnDrop::new(|| sdmmc.on_drop()); | ||
| 320 | |||
| 321 | let transfer = sdmmc.prepare_datapath_read( | ||
| 322 | &sdmmc.config, | ||
| 323 | #[cfg(sdmmc_v1)] | ||
| 324 | &mut self.dma, | ||
| 325 | scr, | ||
| 326 | 8, | ||
| 327 | 3, | ||
| 328 | ); | ||
| 329 | sdmmc.enable_interrupts(); | ||
| 330 | sdmmc.cmd(sd_cmd::send_scr(), true)?; | ||
| 331 | |||
| 332 | let res = sdmmc.complete_datapath_transfer(true).await; | ||
| 333 | |||
| 334 | if res.is_ok() { | ||
| 335 | on_drop.defuse(); | ||
| 336 | sdmmc.stop_datapath(); | ||
| 337 | drop(transfer); | ||
| 338 | |||
| 339 | unsafe { | ||
| 340 | let scr_bytes = &*(&scr as *const _ as *const [u8; 8]); | ||
| 341 | self.scr = SCR(u64::from_be_bytes(*scr_bytes)); | ||
| 342 | } | ||
| 343 | } | ||
| 344 | res | ||
| 345 | } | ||
| 346 | |||
| 347 | /// Reads the SD Status (ACMD13) | ||
| 348 | /// | ||
| 349 | /// SD only. | ||
| 350 | pub async fn read_sd_status<'a>(&mut self, sdmmc: &mut Sdmmc<'a>, cmd_block: &mut CmdBlock) -> Result<(), Error> { | ||
| 351 | let rca = self.rca; | ||
| 352 | |||
| 353 | sdmmc.cmd(common_cmd::set_block_length(64), false)?; // CMD16 | ||
| 354 | sdmmc.cmd(common_cmd::app_cmd(rca), false)?; // APP | ||
| 355 | |||
| 356 | let status = cmd_block; | ||
| 357 | |||
| 358 | // Arm `OnDrop` after the buffer, so it will be dropped first | ||
| 359 | let on_drop = OnDrop::new(|| sdmmc.on_drop()); | ||
| 360 | |||
| 361 | let transfer = sdmmc.prepare_datapath_read( | ||
| 362 | &sdmmc.config, | ||
| 363 | #[cfg(sdmmc_v1)] | ||
| 364 | &mut self.dma, | ||
| 365 | status.as_mut(), | ||
| 366 | 64, | ||
| 367 | 6, | ||
| 368 | ); | ||
| 369 | sdmmc.enable_interrupts(); | ||
| 370 | sdmmc.cmd(sd_cmd::sd_status(), true)?; | ||
| 371 | |||
| 372 | let res = sdmmc.complete_datapath_transfer(true).await; | ||
| 373 | |||
| 374 | if res.is_ok() { | ||
| 375 | on_drop.defuse(); | ||
| 376 | sdmmc.stop_datapath(); | ||
| 377 | drop(transfer); | ||
| 378 | |||
| 379 | for byte in status.iter_mut() { | ||
| 380 | *byte = u32::from_be(*byte); | ||
| 381 | } | ||
| 382 | self.status = status.0.into(); | ||
| 383 | } | ||
| 384 | res | ||
| 385 | } | ||
| 386 | } | ||
| 387 | |||
| 388 | impl Addressable for Card { | ||
| 389 | type Ext = SD; | ||
| 390 | |||
| 391 | /// Get this peripheral's address on the SDMMC bus | ||
| 392 | fn get_address(&self) -> u16 { | ||
| 393 | self.rca | ||
| 394 | } | ||
| 395 | |||
| 396 | /// Is this a standard or high capacity peripheral? | ||
| 397 | fn get_capacity(&self) -> CardCapacity { | ||
| 398 | self.card_type | ||
| 399 | } | ||
| 400 | |||
| 401 | /// Size in bytes | ||
| 402 | fn size(&self) -> u64 { | ||
| 403 | u64::from(self.csd.block_count()) * 512 | ||
| 404 | } | ||
| 405 | } | ||
| 406 | |||
| 187 | #[derive(Clone, Copy, Debug, Default)] | 407 | #[derive(Clone, Copy, Debug, Default)] |
| 188 | /// eMMC storage | 408 | /// eMMC storage |
| 189 | pub struct Emmc { | 409 | pub struct Emmc { |
| @@ -201,6 +421,66 @@ pub struct Emmc { | |||
| 201 | pub ext_csd: ExtCSD, | 421 | pub ext_csd: ExtCSD, |
| 202 | } | 422 | } |
| 203 | 423 | ||
| 424 | impl Emmc { | ||
| 425 | /// Gets the EXT_CSD register. | ||
| 426 | /// | ||
| 427 | /// eMMC only. | ||
| 428 | async fn read_ext_csd<'a>(&mut self, sdmmc: &mut Sdmmc<'a>) -> Result<(), Error> { | ||
| 429 | // Note: cmd_block can't be used because ExtCSD is too long to fit. | ||
| 430 | let mut data_block = DataBlock([0u8; 512]); | ||
| 431 | |||
| 432 | // NOTE(unsafe) DataBlock uses align 4 | ||
| 433 | let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) }; | ||
| 434 | |||
| 435 | sdmmc.cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16 | ||
| 436 | |||
| 437 | let transfer = sdmmc.prepare_datapath_read( | ||
| 438 | &sdmmc.config, | ||
| 439 | #[cfg(sdmmc_v1)] | ||
| 440 | &mut self.dma, | ||
| 441 | buffer, | ||
| 442 | 512, | ||
| 443 | 9, | ||
| 444 | ); | ||
| 445 | sdmmc.enable_interrupts(); | ||
| 446 | sdmmc.cmd(emmc_cmd::send_ext_csd(), true)?; | ||
| 447 | |||
| 448 | // Arm `OnDrop` after the buffer, so it will be dropped first | ||
| 449 | let on_drop = OnDrop::new(|| sdmmc.on_drop()); | ||
| 450 | |||
| 451 | let res = sdmmc.complete_datapath_transfer(true).await; | ||
| 452 | |||
| 453 | if res.is_ok() { | ||
| 454 | on_drop.defuse(); | ||
| 455 | sdmmc.stop_datapath(); | ||
| 456 | drop(transfer); | ||
| 457 | |||
| 458 | self.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into(); | ||
| 459 | } | ||
| 460 | |||
| 461 | res | ||
| 462 | } | ||
| 463 | } | ||
| 464 | |||
| 465 | impl Addressable for Emmc { | ||
| 466 | type Ext = EMMC; | ||
| 467 | |||
| 468 | /// Get this peripheral's address on the SDMMC bus | ||
| 469 | fn get_address(&self) -> u16 { | ||
| 470 | self.rca | ||
| 471 | } | ||
| 472 | |||
| 473 | /// Is this a standard or high capacity peripheral? | ||
| 474 | fn get_capacity(&self) -> CardCapacity { | ||
| 475 | self.capacity | ||
| 476 | } | ||
| 477 | |||
| 478 | /// Size in bytes | ||
| 479 | fn size(&self) -> u64 { | ||
| 480 | u64::from(self.ext_csd.sector_count()) * 512 | ||
| 481 | } | ||
| 482 | } | ||
| 483 | |||
| 204 | #[repr(u8)] | 484 | #[repr(u8)] |
| 205 | enum PowerCtrl { | 485 | enum PowerCtrl { |
| 206 | Off = 0b00, | 486 | Off = 0b00, |
| @@ -386,12 +666,6 @@ pub struct Sdmmc<'d> { | |||
| 386 | clock: Hertz, | 666 | clock: Hertz, |
| 387 | /// Current signalling scheme to card | 667 | /// Current signalling scheme to card |
| 388 | signalling: Signalling, | 668 | signalling: Signalling, |
| 389 | /// Card | ||
| 390 | card: Option<SdmmcPeripheral>, | ||
| 391 | |||
| 392 | /// An optional buffer to be used for commands | ||
| 393 | /// This should be used if there are special memory location requirements for dma | ||
| 394 | cmd_block: Option<&'d mut CmdBlock>, | ||
| 395 | } | 669 | } |
| 396 | 670 | ||
| 397 | const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh); | 671 | const CLK_AF: AfType = AfType::output(OutputType::PushPull, Speed::VeryHigh); |
| @@ -725,8 +999,6 @@ impl<'d> Sdmmc<'d> { | |||
| 725 | config, | 999 | config, |
| 726 | clock: SD_INIT_FREQ, | 1000 | clock: SD_INIT_FREQ, |
| 727 | signalling: Default::default(), | 1001 | signalling: Default::default(), |
| 728 | card: None, | ||
| 729 | cmd_block: None, | ||
| 730 | } | 1002 | } |
| 731 | } | 1003 | } |
| 732 | 1004 | ||
| @@ -889,9 +1161,9 @@ impl<'d> Sdmmc<'d> { | |||
| 889 | } | 1161 | } |
| 890 | 1162 | ||
| 891 | /// Query the card status (CMD13, returns R1) | 1163 | /// Query the card status (CMD13, returns R1) |
| 892 | fn read_status<Ext>(&self, card: &SdmmcPeripheral) -> Result<CardStatus<Ext>, Error> | 1164 | fn read_status<A: Addressable>(&self, card: &A) -> Result<CardStatus<A::Ext>, Error> |
| 893 | where | 1165 | where |
| 894 | CardStatus<Ext>: From<u32>, | 1166 | CardStatus<A::Ext>: From<u32>, |
| 895 | { | 1167 | { |
| 896 | let regs = self.info.regs; | 1168 | let regs = self.info.regs; |
| 897 | let rca = card.get_address(); | 1169 | let rca = card.get_address(); |
| @@ -1080,9 +1352,14 @@ impl<'d> Sdmmc<'d> { | |||
| 1080 | 1352 | ||
| 1081 | /// Read a data block. | 1353 | /// Read a data block. |
| 1082 | #[inline] | 1354 | #[inline] |
| 1083 | pub async fn read_block(&mut self, block_idx: u32, buffer: &mut DataBlock) -> Result<(), Error> { | 1355 | pub async fn read_block( |
| 1356 | &mut self, | ||
| 1357 | card: &mut impl Addressable, | ||
| 1358 | block_idx: u32, | ||
| 1359 | buffer: &mut DataBlock, | ||
| 1360 | ) -> Result<(), Error> { | ||
| 1084 | let _scoped_block_stop = self.info.rcc.block_stop(); | 1361 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1085 | let card_capacity = self.card()?.get_capacity(); | 1362 | let card_capacity = card.get_capacity(); |
| 1086 | 1363 | ||
| 1087 | // NOTE(unsafe) DataBlock uses align 4 | 1364 | // NOTE(unsafe) DataBlock uses align 4 |
| 1088 | let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) }; | 1365 | let buffer = unsafe { &mut *((&mut buffer.0) as *mut [u8; 512] as *mut [u32; 128]) }; |
| @@ -1120,9 +1397,14 @@ impl<'d> Sdmmc<'d> { | |||
| 1120 | 1397 | ||
| 1121 | /// Read multiple data blocks. | 1398 | /// Read multiple data blocks. |
| 1122 | #[inline] | 1399 | #[inline] |
| 1123 | pub async fn read_blocks(&mut self, block_idx: u32, blocks: &mut [DataBlock]) -> Result<(), Error> { | 1400 | pub async fn read_blocks( |
| 1401 | &mut self, | ||
| 1402 | card: &mut impl Addressable, | ||
| 1403 | block_idx: u32, | ||
| 1404 | blocks: &mut [DataBlock], | ||
| 1405 | ) -> Result<(), Error> { | ||
| 1124 | let _scoped_block_stop = self.info.rcc.block_stop(); | 1406 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1125 | let card_capacity = self.card()?.get_capacity(); | 1407 | let card_capacity = card.get_capacity(); |
| 1126 | 1408 | ||
| 1127 | // NOTE(unsafe) reinterpret buffer as &mut [u32] | 1409 | // NOTE(unsafe) reinterpret buffer as &mut [u32] |
| 1128 | let buffer = unsafe { | 1410 | let buffer = unsafe { |
| @@ -1167,9 +1449,16 @@ impl<'d> Sdmmc<'d> { | |||
| 1167 | } | 1449 | } |
| 1168 | 1450 | ||
| 1169 | /// Write a data block. | 1451 | /// Write a data block. |
| 1170 | pub async fn write_block(&mut self, block_idx: u32, buffer: &DataBlock) -> Result<(), Error> { | 1452 | pub async fn write_block<A: Addressable>( |
| 1453 | &mut self, | ||
| 1454 | card: &mut A, | ||
| 1455 | block_idx: u32, | ||
| 1456 | buffer: &DataBlock, | ||
| 1457 | ) -> Result<(), Error> | ||
| 1458 | where | ||
| 1459 | CardStatus<A::Ext>: From<u32>, | ||
| 1460 | { | ||
| 1171 | let _scoped_block_stop = self.info.rcc.block_stop(); | 1461 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1172 | let card = self.card.as_mut().ok_or(Error::NoCard)?; | ||
| 1173 | 1462 | ||
| 1174 | // NOTE(unsafe) DataBlock uses align 4 | 1463 | // NOTE(unsafe) DataBlock uses align 4 |
| 1175 | let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) }; | 1464 | let buffer = unsafe { &*((&buffer.0) as *const [u8; 512] as *const [u32; 128]) }; |
| @@ -1205,13 +1494,8 @@ impl<'d> Sdmmc<'d> { | |||
| 1205 | // TODO: Make this configurable | 1494 | // TODO: Make this configurable |
| 1206 | let mut timeout: u32 = 0x00FF_FFFF; | 1495 | let mut timeout: u32 = 0x00FF_FFFF; |
| 1207 | 1496 | ||
| 1208 | let card = self.card.as_ref().unwrap(); | ||
| 1209 | while timeout > 0 { | 1497 | while timeout > 0 { |
| 1210 | let ready_for_data = match card { | 1498 | let ready_for_data = self.read_status(card)?.ready_for_data(); |
| 1211 | SdmmcPeripheral::Emmc(_) => self.read_status::<EMMC>(card)?.ready_for_data(), | ||
| 1212 | SdmmcPeripheral::SdCard(_) => self.read_status::<SD>(card)?.ready_for_data(), | ||
| 1213 | }; | ||
| 1214 | |||
| 1215 | if ready_for_data { | 1499 | if ready_for_data { |
| 1216 | return Ok(()); | 1500 | return Ok(()); |
| 1217 | } | 1501 | } |
| @@ -1224,9 +1508,16 @@ impl<'d> Sdmmc<'d> { | |||
| 1224 | } | 1508 | } |
| 1225 | 1509 | ||
| 1226 | /// Write multiple data blocks. | 1510 | /// Write multiple data blocks. |
| 1227 | pub async fn write_blocks(&mut self, block_idx: u32, blocks: &[DataBlock]) -> Result<(), Error> { | 1511 | pub async fn write_blocks<A: Addressable>( |
| 1512 | &mut self, | ||
| 1513 | card: &mut A, | ||
| 1514 | block_idx: u32, | ||
| 1515 | blocks: &[DataBlock], | ||
| 1516 | ) -> Result<(), Error> | ||
| 1517 | where | ||
| 1518 | CardStatus<A::Ext>: From<u32>, | ||
| 1519 | { | ||
| 1228 | let _scoped_block_stop = self.info.rcc.block_stop(); | 1520 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1229 | let card = self.card.as_mut().ok_or(Error::NoCard)?; | ||
| 1230 | 1521 | ||
| 1231 | // NOTE(unsafe) reinterpret buffer as &[u32] | 1522 | // NOTE(unsafe) reinterpret buffer as &[u32] |
| 1232 | let buffer = unsafe { | 1523 | let buffer = unsafe { |
| @@ -1272,12 +1563,11 @@ impl<'d> Sdmmc<'d> { | |||
| 1272 | // TODO: Make this configurable | 1563 | // TODO: Make this configurable |
| 1273 | let mut timeout: u32 = 0x00FF_FFFF; | 1564 | let mut timeout: u32 = 0x00FF_FFFF; |
| 1274 | 1565 | ||
| 1275 | // Try to read card status (ACMD13) | ||
| 1276 | while timeout > 0 { | 1566 | while timeout > 0 { |
| 1277 | match self.read_sd_status().await { | 1567 | let ready_for_data = self.read_status(card)?.ready_for_data(); |
| 1278 | Ok(_) => return Ok(()), | 1568 | |
| 1279 | Err(Error::Timeout) => (), // Try again | 1569 | if ready_for_data { |
| 1280 | Err(e) => return Err(e), | 1570 | return Ok(()); |
| 1281 | } | 1571 | } |
| 1282 | timeout -= 1; | 1572 | timeout -= 1; |
| 1283 | } | 1573 | } |
| @@ -1287,31 +1577,17 @@ impl<'d> Sdmmc<'d> { | |||
| 1287 | } | 1577 | } |
| 1288 | } | 1578 | } |
| 1289 | 1579 | ||
| 1290 | /// Get a reference to the initialized card | ||
| 1291 | /// | ||
| 1292 | /// # Errors | ||
| 1293 | /// | ||
| 1294 | /// Returns Error::NoCard if [`init_sd_card`](#method.init_sd_card) or | ||
| 1295 | /// [`init_emmc`](#method.init_emmc) has not previously succeeded | ||
| 1296 | #[inline] | ||
| 1297 | pub fn card(&self) -> Result<&SdmmcPeripheral, Error> { | ||
| 1298 | self.card.as_ref().ok_or(Error::NoCard) | ||
| 1299 | } | ||
| 1300 | |||
| 1301 | /// Get the current SDMMC bus clock | 1580 | /// Get the current SDMMC bus clock |
| 1302 | pub fn clock(&self) -> Hertz { | 1581 | pub fn clock(&self) -> Hertz { |
| 1303 | self.clock | 1582 | self.clock |
| 1304 | } | 1583 | } |
| 1305 | 1584 | ||
| 1306 | /// Set a specific cmd buffer rather than using the default stack allocated one. | 1585 | async fn init_internal( |
| 1307 | /// This is required if stack RAM cannot be used with DMA and usually manifests | 1586 | &mut self, |
| 1308 | /// itself as an indefinite wait on a dma transfer because the dma peripheral | 1587 | cmd_block: &mut CmdBlock, |
| 1309 | /// cannot access the memory. | 1588 | freq: Hertz, |
| 1310 | pub fn set_cmd_block(&mut self, cmd_block: &'d mut CmdBlock) { | 1589 | card: &mut SdmmcPeripheral, |
| 1311 | self.cmd_block = Some(cmd_block) | 1590 | ) -> Result<(), Error> { |
| 1312 | } | ||
| 1313 | |||
| 1314 | async fn init_internal(&mut self, freq: Hertz, mut card: SdmmcPeripheral) -> Result<(), Error> { | ||
| 1315 | let regs = self.info.regs; | 1591 | let regs = self.info.regs; |
| 1316 | 1592 | ||
| 1317 | let bus_width = match (self.d3.is_some(), self.d7.is_some()) { | 1593 | let bus_width = match (self.d3.is_some(), self.d7.is_some()) { |
| @@ -1346,7 +1622,7 @@ impl<'d> Sdmmc<'d> { | |||
| 1346 | self.cmd(common_cmd::idle(), false)?; | 1622 | self.cmd(common_cmd::idle(), false)?; |
| 1347 | 1623 | ||
| 1348 | match card { | 1624 | match card { |
| 1349 | SdmmcPeripheral::SdCard(ref mut card) => { | 1625 | SdmmcPeripheral::SdCard(card) => { |
| 1350 | // Check if cards supports CMD8 (with pattern) | 1626 | // Check if cards supports CMD8 (with pattern) |
| 1351 | self.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?; | 1627 | self.cmd(sd_cmd::send_if_cond(1, 0xAA), false)?; |
| 1352 | let cic = CIC::from(regs.respr(0).read().cardstatus()); | 1628 | let cic = CIC::from(regs.respr(0).read().cardstatus()); |
| @@ -1387,7 +1663,7 @@ impl<'d> Sdmmc<'d> { | |||
| 1387 | } | 1663 | } |
| 1388 | card.ocr = ocr; | 1664 | card.ocr = ocr; |
| 1389 | } | 1665 | } |
| 1390 | SdmmcPeripheral::Emmc(ref mut emmc) => { | 1666 | SdmmcPeripheral::Emmc(emmc) => { |
| 1391 | let ocr = loop { | 1667 | let ocr = loop { |
| 1392 | let high_voltage = 0b0 << 7; | 1668 | let high_voltage = 0b0 << 7; |
| 1393 | let access_mode = 0b10 << 29; | 1669 | let access_mode = 0b10 << 29; |
| @@ -1423,14 +1699,14 @@ impl<'d> Sdmmc<'d> { | |||
| 1423 | let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); | 1699 | let cid = (cid0 << 96) | (cid1 << 64) | (cid2 << 32) | (cid3); |
| 1424 | 1700 | ||
| 1425 | match card { | 1701 | match card { |
| 1426 | SdmmcPeripheral::SdCard(ref mut card) => { | 1702 | SdmmcPeripheral::SdCard(card) => { |
| 1427 | card.cid = cid.into(); | 1703 | card.cid = cid.into(); |
| 1428 | 1704 | ||
| 1429 | self.cmd(sd_cmd::send_relative_address(), false)?; | 1705 | self.cmd(sd_cmd::send_relative_address(), false)?; |
| 1430 | let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus()); | 1706 | let rca = RCA::<SD>::from(regs.respr(0).read().cardstatus()); |
| 1431 | card.rca = rca.address(); | 1707 | card.rca = rca.address(); |
| 1432 | } | 1708 | } |
| 1433 | SdmmcPeripheral::Emmc(ref mut emmc) => { | 1709 | SdmmcPeripheral::Emmc(emmc) => { |
| 1434 | emmc.cid = cid.into(); | 1710 | emmc.cid = cid.into(); |
| 1435 | 1711 | ||
| 1436 | emmc.rca = 1u16.into(); | 1712 | emmc.rca = 1u16.into(); |
| @@ -1448,10 +1724,10 @@ impl<'d> Sdmmc<'d> { | |||
| 1448 | self.select_card(Some(card.get_address()))?; | 1724 | self.select_card(Some(card.get_address()))?; |
| 1449 | 1725 | ||
| 1450 | let bus_width = match card { | 1726 | let bus_width = match card { |
| 1451 | SdmmcPeripheral::SdCard(ref mut card) => { | 1727 | SdmmcPeripheral::SdCard(card) => { |
| 1452 | card.csd = csd.into(); | 1728 | card.csd = csd.into(); |
| 1453 | 1729 | ||
| 1454 | self.get_scr(card).await?; | 1730 | card.get_scr(self, cmd_block).await?; |
| 1455 | 1731 | ||
| 1456 | if !card.scr.bus_width_four() { | 1732 | if !card.scr.bus_width_four() { |
| 1457 | BusWidth::One | 1733 | BusWidth::One |
| @@ -1459,7 +1735,7 @@ impl<'d> Sdmmc<'d> { | |||
| 1459 | BusWidth::Four | 1735 | BusWidth::Four |
| 1460 | } | 1736 | } |
| 1461 | } | 1737 | } |
| 1462 | SdmmcPeripheral::Emmc(ref mut emmc) => { | 1738 | SdmmcPeripheral::Emmc(emmc) => { |
| 1463 | emmc.csd = csd.into(); | 1739 | emmc.csd = csd.into(); |
| 1464 | 1740 | ||
| 1465 | bus_width | 1741 | bus_width |
| @@ -1475,7 +1751,7 @@ impl<'d> Sdmmc<'d> { | |||
| 1475 | }; | 1751 | }; |
| 1476 | 1752 | ||
| 1477 | match card { | 1753 | match card { |
| 1478 | SdmmcPeripheral::SdCard(ref mut card) => { | 1754 | SdmmcPeripheral::SdCard(card) => { |
| 1479 | let acmd_arg = match bus_width { | 1755 | let acmd_arg = match bus_width { |
| 1480 | BusWidth::Four if card.scr.bus_width_four() => 2, | 1756 | BusWidth::Four if card.scr.bus_width_four() => 2, |
| 1481 | _ => 0, | 1757 | _ => 0, |
| @@ -1483,7 +1759,7 @@ impl<'d> Sdmmc<'d> { | |||
| 1483 | self.cmd(common_cmd::app_cmd(card.rca), false)?; | 1759 | self.cmd(common_cmd::app_cmd(card.rca), false)?; |
| 1484 | self.cmd(sd_cmd::cmd6(acmd_arg), false)?; | 1760 | self.cmd(sd_cmd::cmd6(acmd_arg), false)?; |
| 1485 | } | 1761 | } |
| 1486 | SdmmcPeripheral::Emmc(_) => { | 1762 | SdmmcPeripheral::Emmc(emmc) => { |
| 1487 | // Write bus width to ExtCSD byte 183 | 1763 | // Write bus width to ExtCSD byte 183 |
| 1488 | self.cmd( | 1764 | self.cmd( |
| 1489 | emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus), | 1765 | emmc_cmd::modify_ext_csd(emmc_cmd::AccessMode::WriteByte, 183, widbus), |
| @@ -1492,7 +1768,7 @@ impl<'d> Sdmmc<'d> { | |||
| 1492 | 1768 | ||
| 1493 | // Wait for ready after R1b response | 1769 | // Wait for ready after R1b response |
| 1494 | loop { | 1770 | loop { |
| 1495 | let status = self.read_status::<EMMC>(&card)?; | 1771 | let status = self.read_status(emmc)?; |
| 1496 | 1772 | ||
| 1497 | if status.ready_for_data() { | 1773 | if status.ready_for_data() { |
| 1498 | break; | 1774 | break; |
| @@ -1515,32 +1791,30 @@ impl<'d> Sdmmc<'d> { | |||
| 1515 | self.clkcr_set_clkdiv(25_000_000, bus_width)?; | 1791 | self.clkcr_set_clkdiv(25_000_000, bus_width)?; |
| 1516 | } | 1792 | } |
| 1517 | 1793 | ||
| 1518 | self.card = Some(card); | ||
| 1519 | |||
| 1520 | match card { | 1794 | match card { |
| 1521 | SdmmcPeripheral::SdCard(_) => { | 1795 | SdmmcPeripheral::SdCard(card) => { |
| 1522 | // Read status | 1796 | // Read status |
| 1523 | self.read_sd_status().await?; | 1797 | card.read_sd_status(self, cmd_block).await?; |
| 1524 | 1798 | ||
| 1525 | if freq.0 > 25_000_000 { | 1799 | if freq.0 > 25_000_000 { |
| 1526 | // Switch to SDR25 | 1800 | // Switch to SDR25 |
| 1527 | self.signalling = self.switch_signalling_mode(Signalling::SDR25).await?; | 1801 | self.signalling = card.switch_signalling_mode(self, cmd_block, Signalling::SDR25).await?; |
| 1528 | 1802 | ||
| 1529 | if self.signalling == Signalling::SDR25 { | 1803 | if self.signalling == Signalling::SDR25 { |
| 1530 | // Set final clock frequency | 1804 | // Set final clock frequency |
| 1531 | self.clkcr_set_clkdiv(freq.0, bus_width)?; | 1805 | self.clkcr_set_clkdiv(freq.0, bus_width)?; |
| 1532 | 1806 | ||
| 1533 | if self.read_status::<SD>(self.card.as_ref().unwrap())?.state() != CurrentState::Transfer { | 1807 | if self.read_status(card)?.state() != CurrentState::Transfer { |
| 1534 | return Err(Error::SignalingSwitchFailed); | 1808 | return Err(Error::SignalingSwitchFailed); |
| 1535 | } | 1809 | } |
| 1536 | } | 1810 | } |
| 1537 | } | 1811 | } |
| 1538 | 1812 | ||
| 1539 | // Read status after signalling change | 1813 | // Read status after signalling change |
| 1540 | self.read_sd_status().await?; | 1814 | card.read_sd_status(self, cmd_block).await?; |
| 1541 | } | 1815 | } |
| 1542 | SdmmcPeripheral::Emmc(_) => { | 1816 | SdmmcPeripheral::Emmc(emmc) => { |
| 1543 | self.read_ext_csd().await?; | 1817 | emmc.read_ext_csd(self).await?; |
| 1544 | } | 1818 | } |
| 1545 | } | 1819 | } |
| 1546 | 1820 | ||
| @@ -1550,223 +1824,35 @@ impl<'d> Sdmmc<'d> { | |||
| 1550 | /// Initializes card (if present) and sets the bus at the specified frequency. | 1824 | /// Initializes card (if present) and sets the bus at the specified frequency. |
| 1551 | /// | 1825 | /// |
| 1552 | /// SD only. | 1826 | /// SD only. |
| 1553 | pub async fn init_sd_card(&mut self, freq: Hertz) -> Result<(), Error> { | 1827 | pub async fn init_sd_card(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Card, Error> { |
| 1554 | let _scoped_block_stop = self.info.rcc.block_stop(); | 1828 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1555 | 1829 | ||
| 1556 | self.init_internal(freq, SdmmcPeripheral::SdCard(Card::default())).await | 1830 | let mut card = SdmmcPeripheral::SdCard(Card::default()); |
| 1557 | } | 1831 | self.init_internal(cmd_block, freq, &mut card).await?; |
| 1558 | |||
| 1559 | /// Switch mode using CMD6. | ||
| 1560 | /// | ||
| 1561 | /// Attempt to set a new signalling mode. The selected | ||
| 1562 | /// signalling mode is returned. Expects the current clock | ||
| 1563 | /// frequency to be > 12.5MHz. | ||
| 1564 | /// | ||
| 1565 | /// SD only. | ||
| 1566 | async fn switch_signalling_mode(&mut self, signalling: Signalling) -> Result<Signalling, Error> { | ||
| 1567 | let _ = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card(); | ||
| 1568 | // NB PLSS v7_10 4.3.10.4: "the use of SET_BLK_LEN command is not | ||
| 1569 | // necessary" | ||
| 1570 | |||
| 1571 | let set_function = 0x8000_0000 | ||
| 1572 | | match signalling { | ||
| 1573 | // See PLSS v7_10 Table 4-11 | ||
| 1574 | Signalling::DDR50 => 0xFF_FF04, | ||
| 1575 | Signalling::SDR104 => 0xFF_1F03, | ||
| 1576 | Signalling::SDR50 => 0xFF_1F02, | ||
| 1577 | Signalling::SDR25 => 0xFF_FF01, | ||
| 1578 | Signalling::SDR12 => 0xFF_FF00, | ||
| 1579 | }; | ||
| 1580 | |||
| 1581 | let status = match self.cmd_block.as_deref_mut() { | ||
| 1582 | Some(x) => x, | ||
| 1583 | None => &mut CmdBlock::new(), | ||
| 1584 | }; | ||
| 1585 | |||
| 1586 | // Arm `OnDrop` after the buffer, so it will be dropped first | ||
| 1587 | let on_drop = OnDrop::new(|| self.on_drop()); | ||
| 1588 | |||
| 1589 | let transfer = self.prepare_datapath_read( | ||
| 1590 | &self.config, | ||
| 1591 | #[cfg(sdmmc_v1)] | ||
| 1592 | &mut self.dma, | ||
| 1593 | status.as_mut(), | ||
| 1594 | 64, | ||
| 1595 | 6, | ||
| 1596 | ); | ||
| 1597 | self.enable_interrupts(); | ||
| 1598 | self.cmd(sd_cmd::cmd6(set_function), true)?; // CMD6 | ||
| 1599 | |||
| 1600 | let res = self.complete_datapath_transfer(true).await; | ||
| 1601 | |||
| 1602 | // Host is allowed to use the new functions at least 8 | ||
| 1603 | // clocks after the end of the switch command | ||
| 1604 | // transaction. We know the current clock period is < 80ns, | ||
| 1605 | // so a total delay of 640ns is required here | ||
| 1606 | for _ in 0..300 { | ||
| 1607 | cortex_m::asm::nop(); | ||
| 1608 | } | ||
| 1609 | |||
| 1610 | match res { | ||
| 1611 | Ok(_) => { | ||
| 1612 | on_drop.defuse(); | ||
| 1613 | self.stop_datapath(); | ||
| 1614 | drop(transfer); | ||
| 1615 | |||
| 1616 | // Function Selection of Function Group 1 | ||
| 1617 | let selection = (u32::from_be(status[4]) >> 24) & 0xF; | ||
| 1618 | |||
| 1619 | match selection { | ||
| 1620 | 0 => Ok(Signalling::SDR12), | ||
| 1621 | 1 => Ok(Signalling::SDR25), | ||
| 1622 | 2 => Ok(Signalling::SDR50), | ||
| 1623 | 3 => Ok(Signalling::SDR104), | ||
| 1624 | 4 => Ok(Signalling::DDR50), | ||
| 1625 | _ => Err(Error::UnsupportedCardType), | ||
| 1626 | } | ||
| 1627 | } | ||
| 1628 | Err(e) => Err(e), | ||
| 1629 | } | ||
| 1630 | } | ||
| 1631 | |||
| 1632 | /// Reads the SCR register. | ||
| 1633 | /// | ||
| 1634 | /// SD only. | ||
| 1635 | async fn get_scr(&mut self, card: &mut Card) -> Result<(), Error> { | ||
| 1636 | // Read the 64-bit SCR register | ||
| 1637 | self.cmd(common_cmd::set_block_length(8), false)?; // CMD16 | ||
| 1638 | self.cmd(common_cmd::app_cmd(card.rca), false)?; | ||
| 1639 | |||
| 1640 | let cmd_block = match self.cmd_block.as_deref_mut() { | ||
| 1641 | Some(x) => x, | ||
| 1642 | None => &mut CmdBlock::new(), | ||
| 1643 | }; | ||
| 1644 | let scr = &mut cmd_block.0[..2]; | ||
| 1645 | |||
| 1646 | // Arm `OnDrop` after the buffer, so it will be dropped first | ||
| 1647 | let on_drop = OnDrop::new(|| self.on_drop()); | ||
| 1648 | |||
| 1649 | let transfer = self.prepare_datapath_read( | ||
| 1650 | &self.config, | ||
| 1651 | #[cfg(sdmmc_v1)] | ||
| 1652 | &mut self.dma, | ||
| 1653 | scr, | ||
| 1654 | 8, | ||
| 1655 | 3, | ||
| 1656 | ); | ||
| 1657 | self.enable_interrupts(); | ||
| 1658 | self.cmd(sd_cmd::send_scr(), true)?; | ||
| 1659 | 1832 | ||
| 1660 | let res = self.complete_datapath_transfer(true).await; | 1833 | let card = match card { |
| 1661 | 1834 | SdmmcPeripheral::SdCard(card) => card, | |
| 1662 | if res.is_ok() { | 1835 | _ => unreachable!(), |
| 1663 | on_drop.defuse(); | ||
| 1664 | self.stop_datapath(); | ||
| 1665 | drop(transfer); | ||
| 1666 | |||
| 1667 | unsafe { | ||
| 1668 | let scr_bytes = &*(&scr as *const _ as *const [u8; 8]); | ||
| 1669 | card.scr = SCR(u64::from_be_bytes(*scr_bytes)); | ||
| 1670 | } | ||
| 1671 | } | ||
| 1672 | res | ||
| 1673 | } | ||
| 1674 | |||
| 1675 | /// Reads the SD Status (ACMD13) | ||
| 1676 | /// | ||
| 1677 | /// SD only. | ||
| 1678 | async fn read_sd_status(&mut self) -> Result<(), Error> { | ||
| 1679 | let card = self.card.as_mut().ok_or(Error::NoCard)?.get_sd_card(); | ||
| 1680 | let rca = card.rca; | ||
| 1681 | |||
| 1682 | let cmd_block = match self.cmd_block.as_deref_mut() { | ||
| 1683 | Some(x) => x, | ||
| 1684 | None => &mut CmdBlock::new(), | ||
| 1685 | }; | 1836 | }; |
| 1686 | 1837 | ||
| 1687 | self.cmd(common_cmd::set_block_length(64), false)?; // CMD16 | 1838 | Ok(card) |
| 1688 | self.cmd(common_cmd::app_cmd(rca), false)?; // APP | ||
| 1689 | |||
| 1690 | let status = cmd_block; | ||
| 1691 | |||
| 1692 | // Arm `OnDrop` after the buffer, so it will be dropped first | ||
| 1693 | let on_drop = OnDrop::new(|| self.on_drop()); | ||
| 1694 | |||
| 1695 | let transfer = self.prepare_datapath_read( | ||
| 1696 | &self.config, | ||
| 1697 | #[cfg(sdmmc_v1)] | ||
| 1698 | &mut self.dma, | ||
| 1699 | status.as_mut(), | ||
| 1700 | 64, | ||
| 1701 | 6, | ||
| 1702 | ); | ||
| 1703 | self.enable_interrupts(); | ||
| 1704 | self.cmd(sd_cmd::sd_status(), true)?; | ||
| 1705 | |||
| 1706 | let res = self.complete_datapath_transfer(true).await; | ||
| 1707 | |||
| 1708 | if res.is_ok() { | ||
| 1709 | on_drop.defuse(); | ||
| 1710 | self.stop_datapath(); | ||
| 1711 | drop(transfer); | ||
| 1712 | |||
| 1713 | for byte in status.iter_mut() { | ||
| 1714 | *byte = u32::from_be(*byte); | ||
| 1715 | } | ||
| 1716 | card.status = status.0.into(); | ||
| 1717 | } | ||
| 1718 | res | ||
| 1719 | } | 1839 | } |
| 1720 | 1840 | ||
| 1721 | /// Initializes eMMC and sets the bus at the specified frequency. | 1841 | /// Initializes eMMC and sets the bus at the specified frequency. |
| 1722 | /// | 1842 | /// |
| 1723 | /// eMMC only. | 1843 | /// eMMC only. |
| 1724 | pub async fn init_emmc(&mut self, freq: Hertz) -> Result<(), Error> { | 1844 | pub async fn init_emmc(&mut self, cmd_block: &mut CmdBlock, freq: Hertz) -> Result<Emmc, Error> { |
| 1725 | let _scoped_block_stop = self.info.rcc.block_stop(); | 1845 | let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1726 | 1846 | ||
| 1727 | self.init_internal(freq, SdmmcPeripheral::Emmc(Emmc::default())).await | 1847 | let mut card = SdmmcPeripheral::Emmc(Emmc::default()); |
| 1728 | } | 1848 | self.init_internal(cmd_block, freq, &mut card).await?; |
| 1729 | |||
| 1730 | /// Gets the EXT_CSD register. | ||
| 1731 | /// | ||
| 1732 | /// eMMC only. | ||
| 1733 | async fn read_ext_csd(&mut self) -> Result<(), Error> { | ||
| 1734 | let mut card = self.card.take().ok_or(Error::NoCard)?; | ||
| 1735 | let emmc = card.get_emmc(); | ||
| 1736 | |||
| 1737 | // Note: cmd_block can't be used because ExtCSD is too long to fit. | ||
| 1738 | let mut data_block = DataBlock([0u8; 512]); | ||
| 1739 | |||
| 1740 | // NOTE(unsafe) DataBlock uses align 4 | ||
| 1741 | let buffer = unsafe { &mut *((&mut data_block.0) as *mut [u8; 512] as *mut [u32; 128]) }; | ||
| 1742 | |||
| 1743 | self.cmd(common_cmd::set_block_length(512), false).unwrap(); // CMD16 | ||
| 1744 | |||
| 1745 | let transfer = self.prepare_datapath_read( | ||
| 1746 | &self.config, | ||
| 1747 | #[cfg(sdmmc_v1)] | ||
| 1748 | &mut self.dma, | ||
| 1749 | buffer, | ||
| 1750 | 512, | ||
| 1751 | 9, | ||
| 1752 | ); | ||
| 1753 | self.enable_interrupts(); | ||
| 1754 | self.cmd(emmc_cmd::send_ext_csd(), true)?; | ||
| 1755 | |||
| 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; | ||
| 1760 | |||
| 1761 | if res.is_ok() { | ||
| 1762 | on_drop.defuse(); | ||
| 1763 | self.stop_datapath(); | ||
| 1764 | drop(transfer); | ||
| 1765 | 1849 | ||
| 1766 | emmc.ext_csd = unsafe { core::mem::transmute::<_, [u32; 128]>(data_block.0) }.into(); | 1850 | let card = match card { |
| 1767 | } | 1851 | SdmmcPeripheral::Emmc(card) => card, |
| 1852 | _ => unreachable!(), | ||
| 1853 | }; | ||
| 1768 | 1854 | ||
| 1769 | res | 1855 | Ok(card) |
| 1770 | } | 1856 | } |
| 1771 | } | 1857 | } |
| 1772 | 1858 | ||
| @@ -1874,47 +1960,47 @@ foreach_peripheral!( | |||
| 1874 | }; | 1960 | }; |
| 1875 | ); | 1961 | ); |
| 1876 | 1962 | ||
| 1877 | impl<'d> block_device_driver::BlockDevice<512> for Sdmmc<'d> { | 1963 | // impl<'d, A: Addressable> block_device_driver::BlockDevice<512> for Sdmmc<'d>, A { |
| 1878 | type Error = Error; | 1964 | // type Error = Error; |
| 1879 | type Align = aligned::A4; | 1965 | // type Align = aligned::A4; |
| 1880 | 1966 | // | |
| 1881 | async fn read( | 1967 | // async fn read( |
| 1882 | &mut self, | 1968 | // &mut self, |
| 1883 | block_address: u32, | 1969 | // block_address: u32, |
| 1884 | buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>], | 1970 | // buf: &mut [aligned::Aligned<Self::Align, [u8; 512]>], |
| 1885 | ) -> Result<(), Self::Error> { | 1971 | // ) -> Result<(), Self::Error> { |
| 1886 | let _scoped_block_stop = self.info.rcc.block_stop(); | 1972 | // let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1887 | // TODO: I think block_address needs to be adjusted by the partition start offset | 1973 | // // TODO: I think block_address needs to be adjusted by the partition start offset |
| 1888 | if buf.len() == 1 { | 1974 | // if buf.len() == 1 { |
| 1889 | let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut crate::sdmmc::DataBlock) }; | 1975 | // let block = unsafe { &mut *(&mut buf[0] as *mut _ as *mut crate::sdmmc::DataBlock) }; |
| 1890 | self.read_block(block_address, block).await?; | 1976 | // self.read_block(block_address, block).await?; |
| 1891 | } else { | 1977 | // } else { |
| 1892 | let blocks: &mut [DataBlock] = | 1978 | // let blocks: &mut [DataBlock] = |
| 1893 | unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) }; | 1979 | // unsafe { core::slice::from_raw_parts_mut(buf.as_mut_ptr() as *mut DataBlock, buf.len()) }; |
| 1894 | self.read_blocks(block_address, blocks).await?; | 1980 | // self.read_blocks(block_address, blocks).await?; |
| 1895 | } | 1981 | // } |
| 1896 | Ok(()) | 1982 | // Ok(()) |
| 1897 | } | 1983 | // } |
| 1898 | 1984 | // | |
| 1899 | async fn write( | 1985 | // async fn write( |
| 1900 | &mut self, | 1986 | // &mut self, |
| 1901 | block_address: u32, | 1987 | // block_address: u32, |
| 1902 | buf: &[aligned::Aligned<Self::Align, [u8; 512]>], | 1988 | // buf: &[aligned::Aligned<Self::Align, [u8; 512]>], |
| 1903 | ) -> Result<(), Self::Error> { | 1989 | // ) -> Result<(), Self::Error> { |
| 1904 | let _scoped_block_stop = self.info.rcc.block_stop(); | 1990 | // let _scoped_block_stop = self.info.rcc.block_stop(); |
| 1905 | // TODO: I think block_address needs to be adjusted by the partition start offset | 1991 | // // TODO: I think block_address needs to be adjusted by the partition start offset |
| 1906 | if buf.len() == 1 { | 1992 | // if buf.len() == 1 { |
| 1907 | let block = unsafe { &*(&buf[0] as *const _ as *const crate::sdmmc::DataBlock) }; | 1993 | // let block = unsafe { &*(&buf[0] as *const _ as *const crate::sdmmc::DataBlock) }; |
| 1908 | self.write_block(block_address, block).await?; | 1994 | // self.write_block(block_address, block).await?; |
| 1909 | } else { | 1995 | // } else { |
| 1910 | let blocks: &[DataBlock] = | 1996 | // let blocks: &[DataBlock] = |
| 1911 | unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) }; | 1997 | // unsafe { core::slice::from_raw_parts(buf.as_ptr() as *const DataBlock, buf.len()) }; |
| 1912 | self.write_blocks(block_address, blocks).await?; | 1998 | // self.write_blocks(block_address, blocks).await?; |
| 1913 | } | 1999 | // } |
| 1914 | Ok(()) | 2000 | // Ok(()) |
| 1915 | } | 2001 | // } |
| 1916 | 2002 | // | |
| 1917 | async fn size(&mut self) -> Result<u64, Self::Error> { | 2003 | // async fn size(&mut self) -> Result<u64, Self::Error> { |
| 1918 | Ok(self.card()?.size()) | 2004 | // Ok(self.card()?.size()) |
| 1919 | } | 2005 | // } |
| 1920 | } | 2006 | // } |
diff --git a/embassy-stm32/src/time.rs b/embassy-stm32/src/time.rs index 532877f70..88a28ee3d 100644 --- a/embassy-stm32/src/time.rs +++ b/embassy-stm32/src/time.rs | |||
| @@ -4,7 +4,7 @@ use core::fmt::Display; | |||
| 4 | use core::ops::{Div, Mul}; | 4 | use core::ops::{Div, Mul}; |
| 5 | 5 | ||
| 6 | /// Hertz | 6 | /// Hertz |
| 7 | #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug)] | 7 | #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug, Default)] |
| 8 | pub struct Hertz(pub u32); | 8 | pub struct Hertz(pub u32); |
| 9 | 9 | ||
| 10 | impl Display for Hertz { | 10 | impl Display for Hertz { |
