A re-written SDFileSystem library with improved compatibility, CRC support, and card removal/replacement support.
Dependencies: FATFileSystem
Fork of SDFileSystem by
Diff: SDFileSystem.cpp
- Revision:
- 9:1906befe7f30
- Parent:
- 8:7b6acbb6739b
- Child:
- 10:395539a1481a
--- a/SDFileSystem.cpp Thu Aug 07 16:44:42 2014 +0000 +++ b/SDFileSystem.cpp Mon Aug 11 15:28:11 2014 +0000 @@ -105,8 +105,8 @@ if (!(m_Status & STA_NOINIT)) return m_Status; - //Set the SPI frequency to 100kHz for initialization - m_Spi.frequency(100000); + //Set the SPI frequency to 400kHz for initialization + m_Spi.frequency(400000); //Send 80 dummy clocks with /CS and DI held high m_Cs = 1; @@ -251,7 +251,7 @@ else m_Spi.frequency(m_FREQ); - //Return the device status + //Return the disk status return m_Status; } @@ -260,13 +260,13 @@ //Check if there's a card in the socket checkSocket(); - //Return the device status + //Return the disk status return m_Status; } int SDFileSystem::disk_read(uint8_t* buffer, uint64_t sector) { - //Make sure the device is initialized before proceeding + //Make sure the card is initialized before proceeding if (m_Status & STA_NOINIT) return RES_NOTRDY; @@ -287,17 +287,17 @@ } } - //The read operation failed 3 times (CRC most likely) + //The read operation failed 3 times return RES_ERROR; } int SDFileSystem::disk_write(const uint8_t* buffer, uint64_t sector) { - //Make sure the device is initialized before proceeding + //Make sure the card is initialized before proceeding if (m_Status & STA_NOINIT) return RES_NOTRDY; - //Make sure the device isn't write protected before proceeding + //Make sure the card isn't write protected before proceeding if (m_Status & STA_PROTECT) return RES_WRPRT; @@ -309,58 +309,16 @@ for (int i = 0; i < 3; i++) { //Send CMD24(sector) to write a single block if (writeCommand(CMD24, sector) == 0x00) { - //Wait for up to 500ms for the card to become ready - if (!waitReady(500)) { - //We timed out, deselect and loop again - deselect(); - continue; - } - - //Send the write data token - m_Spi.write(0xFE); - - //Check if large frames are enabled or not - if (m_LargeFrames) { - //Switch to 16-bit frames for better performance - m_Spi.format(16, 0); - - //Write the data block from the buffer - for (int b = 0; b < 512; b += 2) { - m_Spi.write((buffer[b] << 8) | buffer[b + 1]); - } - - //Calculate the CRC16 checksum for the data block and send it (if enabled) - m_Spi.write(m_Crc ? CRC16((char*)buffer, 512) : 0xFFFF); - - //Switch back to 8-bit frames - m_Spi.format(8, 0); - } else { - //Write the data block from the buffer - for (int b = 0; b < 512; b++) - m_Spi.write(buffer[b]); - - //Calculate the CRC16 checksum for the data block and send it (if enabled) - unsigned short crc = m_Crc ? CRC16((char*)buffer, 512) : 0xFFFF; - m_Spi.write(crc >> 8); - m_Spi.write(crc); - } - - //Receive the data response, and deselect the card - char resp = m_Spi.write(0xFF) & 0x1F; - deselect(); - - //Check the response - if (resp == 0x05) + //Try to write the sector, and return if successful + if (writeData((char*)buffer)) return RES_OK; - else if (resp == 0x0D) - return RES_ERROR; } else { //The command failed return RES_ERROR; } } - //The operation either timed out 3 times, failed the CRC check 3 times, or experienced a write error + //The write operation failed 3 times return RES_ERROR; } @@ -376,7 +334,7 @@ uint64_t SDFileSystem::disk_sectors() { - //Make sure the device is initialized before proceeding + //Make sure the card is initialized before proceeding if (m_Status & STA_NOINIT) return 0; @@ -406,7 +364,7 @@ } } - //The read operation failed 3 times (CRC most likely) + //The read operation failed 3 times return 0; } @@ -441,16 +399,17 @@ //Pull /CS low m_Cs = 0; - //Send a dummy clock to enable DO + //Send 8 dummy clocks with DI held high to enable DO m_Spi.write(0xFF); //Wait for up to 500ms for the card to become ready - if (waitReady(500)) + if (waitReady(500)) { return true; - - //We timed out, deselect and return false - deselect(); - return false; + } else { + //We timed out, deselect and return false + deselect(); + return false; + } } inline void SDFileSystem::deselect() @@ -458,7 +417,7 @@ //Pull /CS high m_Cs = 1; - //Send a dummy byte to release DO + //Send 8 dummy clocks with DI held high to disable DO (will also initiate any internal write process) m_Spi.write(0xFF); } @@ -495,8 +454,8 @@ for (int b = 0; b < 6; b++) m_Spi.write(cmdPacket[b]); - //Allow up to 10 bytes of delay for the command response - for (int b = 0; b < 10; b++) { + //Allow up to 8 bytes of delay for the command response + for (int b = 0; b < 9; b++) { resp = m_Spi.write(0xFF); if (!(resp & 0x80)) break; @@ -506,12 +465,12 @@ if (resp > 0x01 || !(cmd == CMD8 || cmd == CMD9 || cmd == CMD17 || cmd == CMD24 || cmd == CMD55 || cmd == CMD58)) deselect(); - //Return the response unless there were CRC errors + //Return the response unless there was a CRC error if (resp == 0xFF || !(resp & (1 << 3))) return resp; } - //The command failed 3 times due to CRC errors + //The command failed 3 times return 0xFF; } @@ -537,7 +496,7 @@ char token; unsigned short crc; - //Wait for up to 200ms for the DataStart token to arrive + //Wait for up to 200ms for the data token to arrive for (int i = 0; i < 200; i++) { token = m_Spi.write(0xFF); if (token != 0xFF) @@ -556,7 +515,7 @@ //Switch to 16-bit frames for better performance m_Spi.format(16, 0); - //Read the data into the buffer + //Read the data block into the buffer unsigned short dataWord; for (int i = 0; i < length; i += 2) { dataWord = m_Spi.write(0xFFFF); @@ -582,6 +541,56 @@ //Deselect the card deselect(); - //Verify the CRC16 checksum (if enabled) + //Return the validity of the CRC16 checksum (if enabled) return (!m_Crc || crc == CRC16(buffer, length)); } + +bool SDFileSystem::writeData(char* buffer) +{ + //Wait for up to 500ms for the card to become ready + if (!waitReady(500)) { + //We timed out, deselect and indicate failure + deselect(); + return false; + } + + //Send the data token + m_Spi.write(0xFE); + + //Calculate the CRC16 checksum for the data block (if enabled) + unsigned short crc = (m_Crc) ? CRC16(buffer, 512) : 0xFFFF; + + //Check if large frames are enabled or not + if (m_LargeFrames) { + //Switch to 16-bit frames for better performance + m_Spi.format(16, 0); + + //Write the data block from the buffer + for (int b = 0; b < 512; b += 2) { + m_Spi.write((buffer[b] << 8) | buffer[b + 1]); + } + + //Send the CRC16 checksum for the data block + m_Spi.write(crc); + + //Switch back to 8-bit frames + m_Spi.format(8, 0); + } else { + //Write the data block from the buffer + for (int b = 0; b < 512; b++) + m_Spi.write(buffer[b]); + + //Send the CRC16 checksum for the data block + m_Spi.write(crc >> 8); + m_Spi.write(crc); + } + + //Receive the data response + char resp = m_Spi.write(0xFF); + + //Deselect the card (this will initiate the internal write process) + deselect(); + + //Return success/failure + return ((resp & 0x1F) == 0x05); +}