A re-written SDFileSystem library with improved compatibility, CRC support, and card removal/replacement support.

Dependencies:   FATFileSystem

Dependents:   xadow_m0_SD_Hello roam_v1 roam_v2 Polytech_tours ... more

Files at this revision

API Documentation at this revision

Comitter:
neilt6
Date:
Mon Aug 11 15:28:11 2014 +0000
Parent:
8:7b6acbb6739b
Child:
10:395539a1481a
Commit message:
Readability improvements

Changed in this revision

SDFileSystem.cpp Show annotated file Show diff for this revision Revisions of this file
SDFileSystem.h Show annotated file Show diff for this revision Revisions of this file
--- 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);
+}
--- a/SDFileSystem.h	Thu Aug 07 16:44:42 2014 +0000
+++ b/SDFileSystem.h	Mon Aug 11 15:28:11 2014 +0000
@@ -171,6 +171,7 @@
     char writeCommand(char cmd, unsigned int arg);
     unsigned int readReturn();
     bool readData(char* buffer, int length);
+    bool writeData(char* buffer);
 };
 
 #endif