Skip to content

Fixes response and data block for CMD17 and CMD18 #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: bisync
Choose a base branch
from

Conversation

marcfir
Copy link

@marcfir marcfir commented May 13, 2025

Without the fix, I get a DeviceError(ReadError) because CMD17 does not detect a start block

// http://elm-chan.org/docs/mmc/mmc_e.html
const MAX_WAIT_BYTES: usize = 8;
const TRANSFER_BYTES: usize = COMMAND_BYTES + MAX_WAIT_BYTES + COMMAND_RESPONSE_BYTES;

let mut buf = [0xFF; TRANSFER_BYTES];
let mut buf: [u8; 19] = [0xFF; TRANSFER_BYTES];
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Magic number

(Some(res), _) => Ok(res),
(None, CMD17 | CMD18) => {
for _retry in 0..8 - 2 {
let ret = self.read_byte().await?;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be possible to do another multi-byte read here instead of reading one at a time?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

According to the specification, the timing of a read operation is

| cmd | Ncr | resp | Nac | data blk |

where (unless otherwise specified, the unit is 8 clock cycles)

  • Ncr = 1..8
  • Nac = 1..100ms (see 4.6.2.1)

In the case of a fast response, we therefore have

| cmd | 0xFF | R1 | 0xFF | Start |

For the slow case

| cmd | 8 * 0xFF | R1 | n * 0xFF | Start |  // where n is the equivalent of 100ms 

If we read more bytes, the start may be included. We could optimize by reading two bytes at a time because Nac is at least one.
In my tests, the SDHC responded quickly, so it's not a problem.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that the single byte reads can reintroduce the problem I fixed in #1. If the task gets stalled between sending the command and reading the respons then the card can run into some sort of timeout and the whole command can fail. I'm a little shirt on time right now so I don't know if that's a problem with this specific command but it would be a good edge case to check.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ran some timeout tests (see here: https://github.com/marcfir/sd_timout_test/blob/b3a18608a5a11f2832cabde6d4463c661d276789/src/bin/main.rs#L68-L86), and everything looks fine.
I used an ESP32S3 and two different SDHC microSD cards.
I could not reproduce your problem with CMD13 in the write function, too.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I previously created this reproducer for the write error problem. The key is that there are multiple tasks that compete for bus access.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested your reproducer and was able to reproduce the errors.
Using your commit, 835b2e4, removed the errors.

I extended your example to read a large file in the same loop. I did not encounter any errors.
So, where is the ReadError that I encountered previously?

I experimented with the SPI frequency, and at 400 kHz, I received a DeviceError(ReadError) for open_volume.
At this point, I switched to my PR, and the DeviceError(ReadError) disappeared for 400 kHz as well as 25 MHz.
Using a logic analyzer, I analyzed the CMD17 with SPI at 10 MHz, and I saw only one 0xFF between CMD17 and R1, which indicates that the R1 comes within https://github.com/marcfir/embedded-sdmmc-rs/blob/1add59b16a9af841794cdfedfc98333cf1f8174e/src/inner/sdcard/mod.rs#L548. I added a log to https://github.com/marcfir/embedded-sdmmc-rs/blob/1add59b16a9af841794cdfedfc98333cf1f8174e/src/inner/sdcard/mod.rs#L569, but it never fired, even when I used 25 MHz.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants