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

Revision:
6:55a26a56046a
Parent:
5:6befff2300d0
Child:
7:61db99e52c0d
--- a/SDFileSystem.cpp	Thu Jul 31 17:40:50 2014 +0000
+++ b/SDFileSystem.cpp	Fri Aug 01 14:45:21 2014 +0000
@@ -19,12 +19,13 @@
 #include "CRC7.h"
 #include "CRC16.h"
 
-SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd, SwitchType cdtype, int hz) : FATFileSystem(name), m_SPI(mosi, miso, sclk), m_CS(cs, 1), m_CD(cd), m_CD_ASSERT((int)cdtype)
+SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd, SwitchType cdtype, int hz) : FATFileSystem(name), m_SPI(mosi, miso, sclk), m_CS(cs, 1), m_CD(cd), m_CD_ASSERT((int)cdtype), m_FREQ(hz)
 {
     //Initialize the member variables
-    m_SpiFreq = hz;
+    m_CardType = CARD_NONE;
+    m_CrcEnabled = true;
+    m_LargeFrames = false;
     m_Status = STA_NOINIT;
-    m_CardType = CARD_NONE;
 
     //Configure the SPI bus
     m_SPI.format(8, 0);
@@ -50,6 +51,47 @@
     return m_CardType;
 }
 
+bool SDFileSystem::crc_enabled()
+{
+    //Return whether or not CRC is enabled
+    return m_CrcEnabled;
+}
+
+void SDFileSystem::crc_enabled(bool enabled)
+{
+    //Check the card socket
+    checkSocket();
+
+    //Just update the member variable if the card isn't initialized
+    if (m_Status & STA_NOINIT) {
+        m_CrcEnabled = enabled;
+        return;
+    }
+
+    //Enable or disable CRC
+    if (!m_CrcEnabled && enabled) {
+        //Send CMD59(0x00000001) to enable CRC
+        writeCommand(CMD59, 0x00000001);
+        m_CrcEnabled = true;
+    } else if (m_CrcEnabled && !enabled) {
+        //Send CMD59(0x00000000) to disable CRC
+        writeCommand(CMD59, 0x00000000);
+        m_CrcEnabled = false;
+    }
+}
+
+bool SDFileSystem::large_frames()
+{
+    //Return whether or not 16-bit frames are enabled
+    return m_LargeFrames;
+}
+
+void SDFileSystem::large_frames(bool enabled)
+{
+    //Set whether or not 16-bit frames are enabled
+    m_LargeFrames = enabled;
+}
+
 int SDFileSystem::disk_initialize()
 {
     char resp;
@@ -168,12 +210,14 @@
         }
     }
 
-    //Send CMD59(0x00000001) to re-enable CRC
-    resp = writeCommand(CMD59, 0x00000001);
-    if (resp != 0x00) {
-        //Initialization failed
-        m_CardType = CARD_UNKNOWN;
-        return m_Status;
+    //Send CMD59(0x00000001) to enable CRC if necessary
+    if (m_CrcEnabled) {
+        resp = writeCommand(CMD59, 0x00000001);
+        if (resp != 0x00) {
+            //Initialization failed
+            m_CardType = CARD_UNKNOWN;
+            return m_Status;
+        }
     }
 
     //Send CMD16(0x00000200) to force the block size to 512B if necessary
@@ -200,12 +244,12 @@
     m_Status &= ~STA_NOINIT;
 
     //Increase the SPI frequency to full speed (limited to 20MHz for MMC, or 25MHz for SDC)
-    if (m_CardType == CARD_MMC && m_SpiFreq > 20000000)
+    if (m_CardType == CARD_MMC && m_FREQ > 20000000)
         m_SPI.frequency(20000000);
-    else if (m_SpiFreq > 25000000)
+    else if (m_FREQ > 25000000)
         m_SPI.frequency(25000000);
     else
-        m_SPI.frequency(m_SpiFreq);
+        m_SPI.frequency(m_FREQ);
 
     //Return the device status
     return m_Status;
@@ -276,14 +320,31 @@
             //Send the write data token
             m_SPI.write(0xFE);
 
-            //Write the data block from the buffer
-            for (int b = 0; b < 512; b++)
-                m_SPI.write(buffer[b]);
+            //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_CrcEnabled ? CRC16((char*)buffer, 512) : 0xFFFF);
 
-            //Calculate the CRC16 checksum for the data block and send it
-            unsigned short crc = CRC16((char*)buffer, 512);
-            m_SPI.write(crc >> 8);
-            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]);
+
+                //Calculate the CRC16 checksum for the data block and send it (if enabled)
+                unsigned short crc = m_CrcEnabled ? 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;
@@ -426,7 +487,10 @@
         cmdPacket[2] = arg >> 16;
         cmdPacket[3] = arg >> 8;
         cmdPacket[4] = arg;
-        cmdPacket[5] = (CRC7(cmdPacket, 5) << 1) | 0x01;
+        if (m_CrcEnabled || cmd == CMD0 || cmd == CMD8)
+            cmdPacket[5] = (CRC7(cmdPacket, 5) << 1) | 0x01;
+        else
+            cmdPacket[5] = 0x01;
 
         //Send the command packet
         for (int b = 0; b < 6; b++)
@@ -472,6 +536,7 @@
 bool SDFileSystem::readData(char* buffer, int length)
 {
     char token;
+    unsigned short crc;
 
     //Wait for up to 200ms for the DataStart token to arrive
     for (int i = 0; i < 200; i++) {
@@ -482,21 +547,42 @@
     }
 
     //Make sure the token is valid
-    if (token != 0xFE)
+    if (token != 0xFE) {
+        deselect();
         return false;
+    }
+
+    //Check if large frames are enabled or not
+    if (m_LargeFrames) {
+        //Switch to 16-bit frames for better performance
+        m_SPI.format(16, 0);
 
-    //Read the data into the buffer
-    for (int i = 0; i < length; i++)
-        buffer[i] = m_SPI.write(0xFF);
+        //Read the data into the buffer
+        unsigned short dataWord;
+        for (int i = 0; i < length; i += 2) {
+            dataWord = m_SPI.write(0xFFFF);
+            buffer[i] = dataWord >> 8;
+            buffer[i + 1] = dataWord;
+        }
+
+        //Read the CRC16 checksum for the data block
+        crc = m_SPI.write(0xFFFF);
 
-    //Read the CRC16 checksum for the data block, and deselect the card
-    unsigned short crc = (m_SPI.write(0xFF) << 8);
-    crc |= m_SPI.write(0xFF);
+        //Switch back to 8-bit frames
+        m_SPI.format(8, 0);
+    } else {
+        //Read the data into the buffer
+        for (int i = 0; i < length; i++)
+            buffer[i] = m_SPI.write(0xFF);
+
+        //Read the CRC16 checksum for the data block
+        crc = (m_SPI.write(0xFF) << 8);
+        crc |= m_SPI.write(0xFF);
+    }
+
+    //Deselect the card
     deselect();
 
-    //Indicate whether the CRC16 checksum was valid or not
-    if (crc == CRC16(buffer, length))
-        return true;
-    else
-        return false;
+    //Verify the CRC16 checksum (if enabled)
+    return (!m_CrcEnabled || crc == CRC16(buffer, length));
 }