Working on my 6502 computer I have gathered a significant amount of wisdom around working with SD Cards and FAT32. I am documenting all this as much for myself as others.
Writing a sector
CMD24 is used to write a single block to the SD Card.
Send CMD24 with the address to write and the SD Card will respond with R1.
Send the Data Start Token of $FE, then 512 bytes of data.
The card will send a data response token. (see below)
Then the card will send $00 until the internal write has finished and the card is ready for more commands.
Data Response Token
Bits 7,6,5 are all undefined.
Bit 4 is always 0.
Bits 3,2,1 are the status bits.
Bit 0 is always 1.
Status bits 010 - Data Acepted.
Status bits 101 - CRC error.
Status bits 110 - Write error.
Masking off the upper bits and taking in to account the bit 0, you get this:
5 - Data Acepted.
11 - CRC error.
13 - Write error.
Pseudocode
Write_SPI($FF) ; Always send an $FF byte before a CS change
SetCS(Low) ; Sets the CS line low
Write_SPI($FF) ; Always send an $FF byte after a CS change
Write_SPI($FF) ; Always send an $FF byte before a command
Write_SPI($58) ; CMD24 - Note we OR command number with $40
Write_SPI($00) ; CMD24 - Address (MSB)
Write_SPI($00) ; CMD24 - Address
Write_SPI($00) ; CMD24 - Address
Write_SPI($00) ; CMD24 - Address (LSB)
Write_SPI($FF) ; CMD24 - No CRC needed.
Result = Read_SPI ; Read the R1 result byte
While(Result == $FF) ; Wait till returned byte is not $FF
Result = Read_SPI ; Read the R1 result byte
If (Result != $00) then Error ; Return an error
Write_SPI($FE) ; Send start data marker.
For I=0 to 511 do ; Write the 512 bytes.
Write_SPI(Data[I]) ; Write a data byte.
Next ; End of the for loop.
DataResponse = Read_SPI ; Read the Data Response code
If (DataResponse != $05) then Error ; Return an error
Result = Read_SPI ; Read the R1 result byte
While(Result == $00) ; Wait till returned byte is not $FF
Result = Read_SPI ; Read the R1 result byte
Write_SPI($FF) ; Always send an $FF byte before a CS change
SetCS(High) ; Sets the CS line high
Write_SPI($FF) ; Always send an $FF byte after a CS change
What’s next?
In part 5 we will start work on reading a file system.