For the last day or two I’ve been getting well versed on the MMC/SD card protocol. You can’t actually get official documentation, officially, but I’ve managed to find a few documents from SanDisk which do actually cover the important parts. There’s also heaps of existing implementations out there which I’ve been referring to, so development is relatively straightforward. There is a catch, of course. Each 6-byte command packet to the SD card has a 7-bit CRC attached. Now technically you can get away without it; it’s only needed for the first command (go idle) which is empty and thus has a well defined, constant CRC7. But I loathe to sit back and miss out on extra bells and whistles… :)
But a 7-bit CRC?! C’mon, what were they thinking? That’s just mean. At least if it were 8-bit it’d be trivial to implement (albeit still a bit of a joke; heck, for ADD we implemented CRC16 even though we were only transmitting four bytes at a time, not a colossal six! ;) ). But no, CRC7 it is. We also need a CRC16 as well, but that’s much easier to implement.
It took me a while to figure out how to actually write the CRC7 code. I started with the CRC16 stuff I wrote two years ago for NET. I figured that should scale well enough – I didn’t use tables or anything like that, that you might find in more optimised implementations – aside from of course the issues with “word” (7 bits) alignment, or lack thereof, within the byte (8 bit) data. That took a while to work out… the first implementation was pretty long, special casing a lot of things, and was wrong anyway. But I refined that down, and now I’ve got it working nicely in only a dozen or so more lines of code than the trivial CRC16 implementation. Sweet.
But the problem now is how to actual verify that it’s working properly. As I noted, there’s one particular command which is well defined, so I have one test case from that. But I cannot find any more. Every software implementation I can find just doesn’t do the CRC calculation, aside from one which is written in some odd language I can’t work with directly. There’s a lot of ICs out there for doing SD/MMC interfacing, all of which do the CRC7 for you automagically, of course, and oddly enough don’t seem to be providing their VHDL source. :)
So it looks like I might just have to wait and see once we get it onto the AVR and talking with a real SD card. It does self-verify, which is something – I remember when I first tried to implement CRC16 I thought I’d gotten it right, until I tried to self-verify it, and realised I hadn’t implement CRC16 at all, just something superficially similar. Whoops. :)
In any case, at least now I can get on with the real work of the SD protocol. The FAT stuff is finished enough for real world testing, and I’ve written the trivial SPI interface… now just to put in the glue. How hard could it be? ;)