Skip to content

Commit 8fc205e

Browse files
committed
Write commands and read response in single transfer
1 parent 5f270ac commit 8fc205e

File tree

1 file changed

+41
-44
lines changed

1 file changed

+41
-44
lines changed

src/inner/sdcard/mod.rs

Lines changed: 41 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -254,10 +254,8 @@ where
254254
self.write_data(DATA_START_BLOCK, &blocks[0].contents)
255255
.await?;
256256
self.wait_not_busy(Delay::new_write()).await?;
257-
if self.card_command(CMD13, 0).await? != 0x00 {
258-
return Err(Error::WriteError);
259-
}
260-
if self.read_byte().await? != 0x00 {
257+
let response = self.card_command(CMD13, 0).await?;
258+
if response[0] != 0x00 || response[1] != 0x00 {
261259
return Err(Error::WriteError);
262260
}
263261
} else {
@@ -317,15 +315,17 @@ where
317315
match self.card_type {
318316
Some(CardType::SD1) => {
319317
let mut csd = CsdV1::new();
320-
if self.card_command(CMD9, 0).await? != 0 {
318+
let cmd_response = self.card_command(CMD9, 0).await?;
319+
if cmd_response[0] != 0 {
321320
return Err(Error::RegisterReadError);
322321
}
323322
self.read_data(&mut csd.data).await?;
324323
Ok(Csd::V1(csd))
325324
}
326325
Some(CardType::SD2 | CardType::SDHC) => {
327326
let mut csd = CsdV2::new();
328-
if self.card_command(CMD9, 0).await? != 0 {
327+
let cmd_response = self.card_command(CMD9, 0).await?;
328+
if cmd_response[0] != 0 {
329329
return Err(Error::RegisterReadError);
330330
}
331331
self.read_data(&mut csd.data).await?;
@@ -429,12 +429,12 @@ where
429429
Err(e) => {
430430
return Err(e);
431431
}
432-
Ok(R1_IDLE_STATE) => {
432+
Ok([R1_IDLE_STATE, ..]) => {
433433
break;
434434
}
435435
Ok(_r) => {
436436
// Try again
437-
warn!("Got response: {:x}, trying again..", _r);
437+
warn!("Got response: {:x}, trying again..", _r[0]);
438438
}
439439
}
440440

@@ -444,19 +444,18 @@ where
444444
debug!("Enable CRC: {}", self.options.use_crc);
445445
// "The SPI interface is initialized in the CRC OFF mode in default"
446446
// -- SD Part 1 Physical Layer Specification v9.00, Section 7.2.2 Bus Transfer Protection
447-
if self.options.use_crc && self.card_command(CMD59, 1).await? != R1_IDLE_STATE {
447+
if self.options.use_crc && self.card_command(CMD59, 1).await?[0] != R1_IDLE_STATE {
448448
return Err(Error::CantEnableCRC);
449449
}
450450
// Check card version
451451
let mut delay = Delay::new_command();
452452
let arg = loop {
453-
if self.card_command(CMD8, 0x1AA).await? == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE) {
453+
let cmd_response = self.card_command(CMD8, 0x1AA).await?;
454+
if cmd_response[0] == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE) {
454455
card_type = CardType::SD1;
455456
break 0;
456457
}
457-
let mut buffer = [0xFF; 4];
458-
self.transfer_bytes(&mut buffer).await?;
459-
let status = buffer[3];
458+
let status = cmd_response[4];
460459
if status == 0xAA {
461460
card_type = CardType::SD2;
462461
break 0x4000_0000;
@@ -474,12 +473,11 @@ where
474473
}
475474

476475
if card_type == CardType::SD2 {
477-
if self.card_command(CMD58, 0).await? != 0 {
476+
let cmd_response = self.card_command(CMD58, 0).await?;
477+
if cmd_response[0] != 0 {
478478
return Err(Error::Cmd58Error);
479479
}
480-
let mut buffer = [0xFF; 4];
481-
self.transfer_bytes(&mut buffer).await?;
482-
if (buffer[0] & 0xC0) == 0xC0 {
480+
if (cmd_response[1] & 0xC0) == 0xC0 {
483481
card_type = CardType::SDHC;
484482
}
485483
// Ignore the other three bytes
@@ -496,42 +494,41 @@ where
496494
/// Perform an application-specific command.
497495
async fn card_acmd(&mut self, command: u8, arg: u32) -> Result<u8, Error> {
498496
self.card_command(CMD55, 0).await?;
499-
self.card_command(command, arg).await
497+
self.card_command(command, arg).await.map(|r| r[0])
500498
}
501499

502500
/// Perform a command.
503-
async fn card_command(&mut self, command: u8, arg: u32) -> Result<u8, Error> {
501+
async fn card_command(&mut self, command: u8, arg: u32) -> Result<[u8; 5], Error> {
504502
if command != CMD0 && command != CMD12 {
505503
self.wait_not_busy(Delay::new_command()).await?;
506504
}
507505

508-
let mut buf = [
509-
0x40 | command,
510-
(arg >> 24) as u8,
511-
(arg >> 16) as u8,
512-
(arg >> 8) as u8,
513-
arg as u8,
514-
0,
515-
];
506+
// Write the command and read the response in a single SPI transfer.
507+
const COMMAND_BYTES: usize = 6;
508+
const MAX_WAIT_BYTES: usize = 8;
509+
const RESPONSE_BYTES: usize = 5;
510+
const TRANSFER_BYTES: usize = COMMAND_BYTES + MAX_WAIT_BYTES + RESPONSE_BYTES;
511+
512+
let mut buf = [0xFF; TRANSFER_BYTES];
513+
buf[0] = 0x40 | command;
514+
buf[1] = (arg >> 24) as u8;
515+
buf[2] = (arg >> 16) as u8;
516+
buf[3] = (arg >> 8) as u8;
517+
buf[4] = arg as u8;
516518
buf[5] = crc7(&buf[0..5]);
517519

518-
self.write_bytes(&buf).await?;
519-
520-
// skip stuff byte for stop read
521-
if command == CMD12 {
522-
let _result = self.read_byte().await?;
523-
}
524-
525-
let mut delay = Delay::new_command();
526-
loop {
527-
let result = self.read_byte().await?;
528-
if (result & 0x80) == ERROR_OK {
529-
return Ok(result);
530-
}
531-
delay
532-
.delay(&mut self.delayer, Error::TimeoutCommand(command))
533-
.await?;
534-
}
520+
self.transfer_bytes(&mut buf).await?;
521+
522+
buf.iter()
523+
.skip(COMMAND_BYTES)
524+
.position(|&b| (b & 0x80) == ERROR_OK)
525+
.and_then(|pos| {
526+
let start = pos + COMMAND_BYTES;
527+
let end = start + RESPONSE_BYTES;
528+
buf.get(start..end)
529+
})
530+
.and_then(|bytes| bytes.try_into().ok())
531+
.ok_or(Error::TimeoutCommand(command))
535532
}
536533

537534
/// Receive a byte from the SPI bus by clocking out an 0xFF byte.

0 commit comments

Comments
 (0)