It's an older 2013 Adata 16GB. My first uSD card. But just marking cards as incompatible is hardly a good solution. Need to resolve to a solution that makes them work. That goes for your Silicon Power card too. I presume it works with Flexspin's built-in FAT32 filesystem just fine?
Also, we're hardly experts on implementing the spec. I found many times, that experience taught me, I wasn't reading the spec correctly in the first place. EDIT: Or just didn't read it at all.
@"Stephen Moraco" said:
@evanh, ok, how can I help?
Two things, first off (1) can you please identify the failing card? There is a utility (UTILS/) that reads the controller's registers and generates a two-line card identifier (UTILS/SD_card_characterize.spin2), if you will. And then (2) also in utilities, run the audit tool (UTILS/SD_FAT32_audit.spin2). This is non-destructive and surveys the entire silesystem structure on the card, reporting all errors.
@evanh hmm... your detail is helping me understand. It's starting to look like some controllers in the past reported CMD13 poorly. We can test for this case and detune our use of CMD13. Then your card will work. Also, changing two of the audit findings from error to warning. Does all this sound like what you expect?
And thank you for all the details on what's happening. It left no question as to what's being seen and how the driver is reacting. As we learn about these edge case cards, I'm leaving detailed analysis documents in the repo for each case we find.
Until proven otherwise, I consider these cases as being buggy driver software not following the spec. I struck it a lot during the SD mode development. I'd mistime or reorder something that didn't upset most cards but there'd be one or two that threw a spaz because I did it wrong.
@evanh said:
Until proven otherwise, I consider these cases as being buggy driver software not following the spec. I struck it a lot during the SD mode development. I'd mistime or reorder something that didn't upset most cards but there'd be one or two that threw a spaz because of my error.
The challenge for me is that the data stream needs to be analyzed for cmd13 returns, as it's either bad content or mistimed (bit shifted), but how do we prove it? You have the card; I can't recreate this. Thoughts? Also, why are only the cmd13 responses affected if it's stream alignment? Your testing has proven that the data path for sector content is fine (CRC-protected reads/writes and is working). There are my other commands using the same SPI code, but only cmd13 is having sync problems? We've got more to learn here.
I'm releasing a modified driver shortly. Can you test it against this card, please? v1.2.1. With the release, you'll have the full cmd13 analysis in the repo for review.
Yup, you deal with the cards you've got. I'll see what I can do at this end. I have the gear, I just have to get motivated.
Actually, this is where splitting the SD driver from the FS handler would be helpful. Create a clear divide between what is filesystem management and what is device management.
The sequences in Flexspin's original sdmm.c driver is rather small. Admittedly, it also doesn't provide any card details but the support for generic command/response is all there and can be used to make large reports or pass back the card data, via an ioctl() say.
Also be able to easily swap in alternative drivers to compare. I did a lot more comparing once Eric had made a runtime plug-in interface for Flexspin's drivers.
Interesting reading about CMD13 not always supported by cards. So maybe not a driver bug then. I wonder if that might sometimes apply to SD mode too. CMD13 is not something I used for that driver either.
Um, Stephen, where did you read about buggy CMD13 in cards? That better not have been AI hallucinations? I've just added it to the sdmm.c SPI mode driver from Flexspin and it's now happily producing valid CMD13 zero responses at end of every group of blocks read from all my SD cards.
send_cmd() has an intriguing check in it though. It seems to skip over any reply bytes that have bit7 set. Not something I'd paid any attention to until now:
...
/* Receive command response */
if (cmd == CMD12) rcvr_mmc(buf+6, 1); /* Skip a stuff byte when stop reading */
n = 10; /* Wait for a valid response in timeout of 10 attempts */
do
rcvr_mmc(buf+6, 1);
while ((buf[6] & 0x80) && --n);
return buf[6]; /* Return with the response value */
@evanh, yes, there are posts on the interwebs across various embedded forums and even microchip forums indicating cmd13 problems. We all know the quality of the information depends on the reporting user's experience level, but the reports are out there. I'm still reviewing the details you provided. Thank you.
While chasing the SP Elite problems to their root cause (my other card), I learned that our driver was not logging traffic, which was very telling. The newer Elite card was sending the next sector start while we were commanding it to stop sectors, causing full-duplex traffic. This prevented the driver from having definitive proof of the correct behavior and caused stuff to be in our RX pipeline. The spec is very clear about how to reset and continue in this case. Which we now do, and this newly working card is now one of our top performers.
Given this new diagnostic thinking, I'm building a temporary early release, v1.2.9 (I'm about to release v1.3.0 after adding deeper regression testing). I'm adding full-duplex logging to the cmd13 handling to see if there is any further indication in the traffic pattern. I'll add a test/diagnostic source file to this distribution that you should be able to compile and run, then send me the logs. Since this is an older card, it is more of a long shot and may or may not provide new info to guide us, but it's worth looking at everything we can.
FYI- This is now documented for this driver. The finding for this Elite card: multi-sector reads are supported in two ways: feed forward: send cmd23, number of sectors, then cmd18 reads the sectors, or terminate when complete: without using cmd23, use cmd18 to read the sectors, then send cmd12 to end the transfer. The Elite Card and the Lexar 64GB card both show cmd23 as supported in the register values, but in actual use, both devices, in SPI mode, fail the command as not supported, so the driver falls back to read and then terminates after the desired sector count is received.
So it seems we have different behavior in SPI mode vs. SD mode. And we get to learn the boundaries experientially...
If you were using my tools, from the top folder of unpacked .zip, you would compile and run with
- pnut-ts -d -I src/ diagnostic-tests/SD_diag_cmd13_capture.spin2
- pnut-term-ts -r diagnostic-tests/SD_diag_cmd13_capture.bin
@"Stephen Moraco" said:
@evanh, yes, there are posts on the interwebs across various embedded forums and even microchip forums indicating cmd13 problems. We all know the quality of the information depends on the reporting user's experience level, but the reports are out there. I'm still reviewing the details you provided. Thank you.
Well, it's pretty clear now that anyone who has ever had a single issue with CMD13 is also using shitty drivers that can't even handle a pretty basic requirement of expecting multiple filler turn-around bytes. It shouldn't take anyone reading the spec all that long to work it out.
As for SD mode, it requires multiple filler turn-around bits, rather than bytes. Every clocked bit, starting from the third bit, has to be tested. And there's no particular limit on how many. But everyone uses a licenced hardware controller there instead, so you'll not be reading complaints about that.
@"Stephen Moraco" said:
FYI- This is now documented for this driver. The finding for this Elite card: multi-sector reads are supported in two ways: feed forward: send cmd23, number of sectors, then cmd18 reads the sectors, or terminate when complete: without using cmd23, use cmd18 to read the sectors, then send cmd12 to end the transfer. The Elite Card and the Lexar 64GB card both show cmd23 as supported in the register values, but in actual use, both devices, in SPI mode, fail the command as not supported, so the driver falls back to read and then terminates after the desired sector count is received.
CMD23 is a similar situation to CMD13 for me - And I'm suspecting a similar outcome here. My experience with CMD23 is a single test in the early days. CMD12 is simpler to manage so CMD23 comes across as redundant and ends up not being used by performant drivers. It's comparable to the old C strings vs Pascal strings.
At any rate, I expect we'll find out all the cards can handle both solutions and it's the driver with the bugs. Possibly the very same bug that threw CMD13.
@evanh, new v1.3.0 coming soon with revised CMD13 handling based on your findings above. It passes our new richer regression test suite. Please verify it's fully working for your older card now... thank you so much for being persistent.
The release package can be downloaded from the Releases page. Download the sd-card-driver-{version}.zip
file.
If you find issues, please file them at the Issues page.
What's next? Quickly address any reported issues. I've exhausted my card set after spending $$ to get a few more in my test pool. Hmm... what about SD Mode (6-wire spi) for this driver? Do we have users that would want that performance for the embedded application?
[doh] It looks like you're right. The card is violating Ncs minimum of zero. The Flexspin sdmm.c driver has obviously been developed through trial and error so it has one blank byte preceding every command. This makes that card happy - And presumably many others too.
I'll admit I'm surprised. And apologies for going a little aggressive. I can't say I've had too much of the driver not being the problem. Maybe you're also right about SPI mode being poor cousin too. ie: Manufacturers don't test it much.
Here's a snapshot of sdmm.c issuing CMD13 - But it's the same for all commands.
Top-mid screen - CS (Blue trace) is lowered to initiate a command. A blank spacer byte is issued with MOSI (Green trace) set high. Then the six byte command is issued. Then a blank response byte. Then the two byte R2 response (MISO, Pink trace) of all zeros. Orange trace is SD clock.
Congratulations on this driver - it opens up the available memory space for programmers enormously. Judging by this thread, it's no wonder that Taqoz forth was a little fussy over which SD cards it would work with. The documentation and examples look to be excellent - getting up to speed with it will be quick.
It took me ages to get the scope all wired up today to record the above snapshot. A probe was still at work and I also crafted an external trigger cable as a fifth probe. Then I had trouble coaxing Stephen's code to remap the pin order to my hand wired SD slot - Which I didn't really need to do but I wanted to use that slot for all tests.
Actually, what sdmm.c is really doing there is testing for card ready/busy. Which takes a minimum of one byte to confirm. It will in fact continue waiting for a ready state, clocking in more card busies for up to 500 ms.
It does this check at beginning of every command except CMD12.
PS: All very sensible and likely a common trait of well written drivers. Which maybe some card manufacturers have inadvertently keyed to.
Ha, and looking through your code, Stephen, it looks like for most if not all other command sequences you've already put a padding sp_transfer_8($FF) immediately following the pinl(cs). So that's why only CMD13 was a problem.
You might want to make a generic send_command() function instead of building each sequence separately like that.
@evanh, what is the current state with v1.3.0 vs. your older card? Is the logic working?
BTW- Good eye, and I had already noticed the code duplication when I saw so many identical fixes for the byte ignoring change. Reducing that now and rerunning the regression suite. Likely a v1.3.1 shortly. (it's much easier to make code reduction changes like this when we have a full regression suite in place!)
@"Stephen Moraco" said:
Hmm... what about SD Mode (6-wire spi) for this driver? Do we have users that would want that performance for the embedded application?
Yes, a higher performance SD card option for your driver would certainly be desirable. With sufficient buffering in RAM, it potentially opens the P2 & SD cards to further applications such as -
high speed logging - eg. logic analyser, high speed ADCs streaming to disk.
high speed video transfers to/from disk for capture/playback, even direct capture at VGA resolutions/refresh rates becomes feasible
running native P2 hubexec code or other bytecode directly off some cached removable storage?
faster transfers can increase performance when disk sharing amongst multiple COGs by reducing overall latency for other COGs to access the same disk
Comments
It's an older 2013 Adata 16GB. My first uSD card. But just marking cards as incompatible is hardly a good solution. Need to resolve to a solution that makes them work. That goes for your Silicon Power card too. I presume it works with Flexspin's built-in FAT32 filesystem just fine?
Also, we're hardly experts on implementing the spec. I found many times, that experience taught me, I wasn't reading the spec correctly in the first place. EDIT: Or just didn't read it at all.
My intent is to get every card I find working. I didn't want to delay releasing this driver to everyone while I worked on one errant card. ;-)
@evanh does it work with any other p2 usd driver? 2013 is pretty old…
Yes, it's one of my regular set of test cards.
Here it is with the plug-in 4-bit driver and Flexspin's built-in FAT32 filesystem:
And same again using Flexspin's built-in SD driver too:
Audit gets nowhere until I force an okay check:
checkCardStatus() forced okay:
Characterize with forced okay:
@evanh hmm... your detail is helping me understand. It's starting to look like some controllers in the past reported CMD13 poorly. We can test for this case and detune our use of CMD13. Then your card will work. Also, changing two of the audit findings from error to warning. Does all this sound like what you expect?
And thank you for all the details on what's happening. It left no question as to what's being seen and how the driver is reacting. As we learn about these edge case cards, I'm leaving detailed analysis documents in the repo for each case we find.
@"Stephen Moraco" some usd drivers have option to not use a cog but use inline assembly instead. Could that be a future feature here?
Until proven otherwise, I consider these cases as being buggy driver software not following the spec. I struck it a lot during the SD mode development. I'd mistime or reorder something that didn't upset most cards but there'd be one or two that threw a spaz because I did it wrong.
The challenge for me is that the data stream needs to be analyzed for cmd13 returns, as it's either bad content or mistimed (bit shifted), but how do we prove it? You have the card; I can't recreate this. Thoughts? Also, why are only the cmd13 responses affected if it's stream alignment? Your testing has proven that the data path for sector content is fine (CRC-protected reads/writes and is working). There are my other commands using the same SPI code, but only cmd13 is having sync problems? We've got more to learn here.
I'm releasing a modified driver shortly. Can you test it against this card, please? v1.2.1. With the release, you'll have the full cmd13 analysis in the repo for review.
Yup, you deal with the cards you've got. I'll see what I can do at this end. I have the gear, I just have to get motivated.
Actually, this is where splitting the SD driver from the FS handler would be helpful. Create a clear divide between what is filesystem management and what is device management.
The sequences in Flexspin's original sdmm.c driver is rather small. Admittedly, it also doesn't provide any card details but the support for generic command/response is all there and can be used to make large reports or pass back the card data, via an ioctl() say.
Also be able to easily swap in alternative drivers to compare. I did a lot more comparing once Eric had made a runtime plug-in interface for Flexspin's drivers.
OK, I published the point release v1.2.1. See also my findings from your logs: CMD13 Analysis and the implementation decision TD-009
I'm completing the adjustments to my unfinished card now, too. Upcoming release.
Interesting reading about CMD13 not always supported by cards. So maybe not a driver bug then. I wonder if that might sometimes apply to SD mode too. CMD13 is not something I used for that driver either.
Um, Stephen, where did you read about buggy CMD13 in cards? That better not have been AI hallucinations? I've just added it to the sdmm.c SPI mode driver from Flexspin and it's now happily producing valid CMD13 zero responses at end of every group of blocks read from all my SD cards.
send_cmd() has an intriguing check in it though. It seems to skip over any reply bytes that have bit7 set. Not something I'd paid any attention to until now:
... /* Receive command response */ if (cmd == CMD12) rcvr_mmc(buf+6, 1); /* Skip a stuff byte when stop reading */ n = 10; /* Wait for a valid response in timeout of 10 attempts */ do rcvr_mmc(buf+6, 1); while ((buf[6] & 0x80) && --n); return buf[6]; /* Return with the response value */Slop-driven development
Looking at the spec for SPI mode, there is indeed leeway for extra bytes between a command and its response:

Ncr can be anything from 1 to 8 bytes.

So it makes sense to discard any bytes with a leading bit7 set high.
@evanh, yes, there are posts on the interwebs across various embedded forums and even microchip forums indicating cmd13 problems. We all know the quality of the information depends on the reporting user's experience level, but the reports are out there. I'm still reviewing the details you provided. Thank you.
While chasing the SP Elite problems to their root cause (my other card), I learned that our driver was not logging traffic, which was very telling. The newer Elite card was sending the next sector start while we were commanding it to stop sectors, causing full-duplex traffic. This prevented the driver from having definitive proof of the correct behavior and caused stuff to be in our RX pipeline. The spec is very clear about how to reset and continue in this case. Which we now do, and this newly working card is now one of our top performers.
Given this new diagnostic thinking, I'm building a temporary early release, v1.2.9 (I'm about to release v1.3.0 after adding deeper regression testing). I'm adding full-duplex logging to the cmd13 handling to see if there is any further indication in the traffic pattern. I'll add a test/diagnostic source file to this distribution that you should be able to compile and run, then send me the logs. Since this is an older card, it is more of a long shot and may or may not provide new info to guide us, but it's worth looking at everything we can.
FYI- This is now documented for this driver. The finding for this Elite card: multi-sector reads are supported in two ways: feed forward: send cmd23, number of sectors, then cmd18 reads the sectors, or terminate when complete: without using cmd23, use cmd18 to read the sectors, then send cmd12 to end the transfer. The Elite Card and the Lexar 64GB card both show cmd23 as supported in the register values, but in actual use, both devices, in SPI mode, fail the command as not supported, so the driver falls back to read and then terminates after the desired sector count is received.
So it seems we have different behavior in SPI mode vs. SD mode. And we get to learn the boundaries experientially...
@evanh v1.2.9 is now available as a pre-release.
So we need to run this against your older card.
If you were using my tools, from the top folder of unpacked .zip, you would compile and run with
- pnut-ts -d -I src/ diagnostic-tests/SD_diag_cmd13_capture.spin2
- pnut-term-ts -r diagnostic-tests/SD_diag_cmd13_capture.bin
This would auto capture the log in ./logs/
Well, it's pretty clear now that anyone who has ever had a single issue with CMD13 is also using shitty drivers that can't even handle a pretty basic requirement of expecting multiple filler turn-around bytes. It shouldn't take anyone reading the spec all that long to work it out.
As for SD mode, it requires multiple filler turn-around bits, rather than bytes. Every clocked bit, starting from the third bit, has to be tested. And there's no particular limit on how many. But everyone uses a licenced hardware controller there instead, so you'll not be reading complaints about that.
CMD23 is a similar situation to CMD13 for me - And I'm suspecting a similar outcome here. My experience with CMD23 is a single test in the early days. CMD12 is simpler to manage so CMD23 comes across as redundant and ends up not being used by performant drivers. It's comparable to the old C strings vs Pascal strings.
At any rate, I expect we'll find out all the cards can handle both solutions and it's the driver with the bugs. Possibly the very same bug that threw CMD13.
@evanh, new v1.3.0 coming soon with revised CMD13 handling based on your findings above. It passes our new richer regression test suite. Please verify it's fully working for your older card now... thank you so much for being persistent.
NEWS
I just released v1.3.0
Here's what's new/fixed:
Visit the P2 microSD FAT32 Filesystem repository for full documentation, including a driver tutorial, theory of operations, and card catalog.
The release package can be downloaded from the Releases page. Download the sd-card-driver-{version}.zip
file.
If you find issues, please file them at the Issues page.
What's next? Quickly address any reported issues. I've exhausted my card set after spending $$ to get a few more in my test pool. Hmm... what about SD Mode (6-wire spi) for this driver? Do we have users that would want that performance for the embedded application?
Enjoy!
Stephen
[doh] It looks like you're right. The card is violating Ncs minimum of zero. The Flexspin sdmm.c driver has obviously been developed through trial and error so it has one blank byte preceding every command. This makes that card happy - And presumably many others too.
I'll admit I'm surprised. And apologies for going a little aggressive. I can't say I've had too much of the driver not being the problem. Maybe you're also right about SPI mode being poor cousin too. ie: Manufacturers don't test it much.
Here's a snapshot of sdmm.c issuing CMD13 - But it's the same for all commands.

Top-mid screen - CS (Blue trace) is lowered to initiate a command. A blank spacer byte is issued with MOSI (Green trace) set high. Then the six byte command is issued. Then a blank response byte. Then the two byte R2 response (MISO, Pink trace) of all zeros. Orange trace is SD clock.
Congratulations on this driver - it opens up the available memory space for programmers enormously. Judging by this thread, it's no wonder that Taqoz forth was a little fussy over which SD cards it would work with. The documentation and examples look to be excellent - getting up to speed with it will be quick.
It took me ages to get the scope all wired up today to record the above snapshot. A probe was still at work and I also crafted an external trigger cable as a fifth probe. Then I had trouble coaxing Stephen's code to remap the pin order to my hand wired SD slot - Which I didn't really need to do but I wanted to use that slot for all tests.
Actually, what sdmm.c is really doing there is testing for card ready/busy. Which takes a minimum of one byte to confirm. It will in fact continue waiting for a ready state, clocking in more card busies for up to 500 ms.
It does this check at beginning of every command except CMD12.
PS: All very sensible and likely a common trait of well written drivers. Which maybe some card manufacturers have inadvertently keyed to.
Ha, and looking through your code, Stephen, it looks like for most if not all other command sequences you've already put a padding
sp_transfer_8($FF)immediately following thepinl(cs). So that's why only CMD13 was a problem.You might want to make a generic
send_command()function instead of building each sequence separately like that.@evanh, what is the current state with v1.3.0 vs. your older card? Is the logic working?
BTW- Good eye, and I had already noticed the code duplication when I saw so many identical fixes for the byte ignoring change. Reducing that now and rerunning the regression suite. Likely a v1.3.1 shortly. (it's much easier to make code reduction changes like this when we have a full regression suite in place!)
Yes, a higher performance SD card option for your driver would certainly be desirable. With sufficient buffering in RAM, it potentially opens the P2 & SD cards to further applications such as -