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:
Fri Aug 01 14:45:21 2014 +0000
Parent:
5:6befff2300d0
Child:
7:61db99e52c0d
Commit message:
Added the option to disable CRC, and enable 16-bit frames for data read/write operations

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 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));
 }
--- a/SDFileSystem.h	Thu Jul 31 17:40:50 2014 +0000
+++ b/SDFileSystem.h	Fri Aug 01 14:45:21 2014 +0000
@@ -30,7 +30,7 @@
  * #include "SDFileSystem.h"
  *
  * //Create an SDFileSystem object
- * SDFileSystem sd(p5, p6, p7, p19, p20, "sd")
+ * SDFileSystem sd(p5, p6, p7, p20, "sd", p22)
  *
  * int main()
  * {
@@ -100,6 +100,34 @@
      */
     SDFileSystem::CardType card_type();
 
+    /** Get whether or not CRC is enabled for commands and data
+     *
+     * @returns
+     *   'true' if CRC is enabled for commands and data,
+     *   'false' if CRC is disabled for commands and data.
+     */
+    bool crc_enabled();
+
+    /** Set whether or not CRC is enabled for commands and data
+     *
+     * @param enabled Whether or not to enable CRC for commands and data.
+     */
+    void crc_enabled(bool enabled);
+
+    /** Get whether or not 16-bit frames are enabled for data read/write operations
+     *
+     * @returns
+     *   'true' if 16-bit frames will be used during data read/write operations,
+     *   'false' if 8-bit frames will be used during data read/write operations.
+     */
+    bool large_frames();
+
+    /** Set whether or not 16-bit frames are enabled for data read/write operations
+     *
+     * @param enabled Whether or not 16-bit frames are enabled for data read/write operations.
+     */
+    void large_frames(bool enabled);
+
     virtual int disk_initialize();
     virtual int disk_status();
     virtual int disk_read(uint8_t* buffer, uint64_t sector);
@@ -129,9 +157,11 @@
     DigitalOut m_CS;
     InterruptIn m_CD;
     const int m_CD_ASSERT;
-    int m_SpiFreq;
+    const int m_FREQ;
+    SDFileSystem::CardType m_CardType;
+    bool m_CrcEnabled;
+    bool m_LargeFrames;
     int m_Status;
-    SDFileSystem::CardType m_CardType;
 
     //Internal methods
     void checkSocket();