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:
12:eebddab6eff2
Parent:
11:67ddc53e3983
Child:
13:635147efa748
--- a/SDFileSystem.cpp	Thu Aug 14 22:27:07 2014 +0000
+++ b/SDFileSystem.cpp	Fri Aug 15 17:54:13 2014 +0000
@@ -19,7 +19,7 @@
 #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), m_FREQ(hz)
+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_FREQ(hz)
 {
     //Initialize the member variables
     m_CardType = CARD_NONE;
@@ -31,11 +31,23 @@
     m_Spi.format(8, 0);
 
     //Configure the card detect pin
-    m_Cd.mode(PullUp);
-    if (cdtype == SWITCH_NO)
+    if (cdtype == SWITCH_POS_NO) {
+        m_Cd.mode(PullDown);
+        m_CdAssert = 1;
+        m_Cd.fall(this, &SDFileSystem::checkSocket);
+    } else if (cdtype == SWITCH_POS_NC) {
+        m_Cd.mode(PullDown);
+        m_CdAssert = 0;
         m_Cd.rise(this, &SDFileSystem::checkSocket);
-    else
+    } else if (cdtype == SWITCH_NEG_NO) {
+        m_Cd.mode(PullUp);
+        m_CdAssert = 0;
+        m_Cd.rise(this, &SDFileSystem::checkSocket);
+    } else {
+        m_Cd.mode(PullUp);
+        m_CdAssert = 1;
         m_Cd.fall(this, &SDFileSystem::checkSocket);
+    }
 }
 
 SDFileSystem::CardType SDFileSystem::card_type()
@@ -127,7 +139,7 @@
     for (int i = 0; i < 10; i++)
         m_Spi.write(0xFF);
 
-    //Write CMD0(0x00000000) to reset the card
+    //Send CMD0(0x00000000) to reset the card
     if (commandTransaction(CMD0, 0x00000000) != 0x01) {
         //Initialization failed
         m_CardType = CARD_UNKNOWN;
@@ -143,7 +155,7 @@
         }
     }
 
-    //Write CMD8(0x000001AA) to see if this is an SDCv2 card
+    //Send CMD8(0x000001AA) to see if this is an SDCv2 card
     if (commandTransaction(CMD8, 0x000001AA, &resp) == 0x01) {
         //This is an SDCv2 card, get the 32-bit return value and verify the voltage range/check pattern
         if ((resp & 0xFFF) != 0x1AA) {
@@ -181,6 +193,12 @@
                 m_CardType = CARD_SDHC;
             else
                 m_CardType = CARD_SD;
+
+            //Increase the SPI frequency to full speed (up to 25MHz for SDCv2)
+            if (m_FREQ > 25000000)
+                m_Spi.frequency(25000000);
+            else
+                m_Spi.frequency(m_FREQ);
         } else {
             //Initialization failed
             m_CardType = CARD_UNKNOWN;
@@ -207,6 +225,12 @@
         if (token == 0x00) {
             //This is an SDCv1 standard capacity card
             m_CardType = CARD_SD;
+
+            //Increase the SPI frequency to full speed (up to 25MHz for SDCv1)
+            if (m_FREQ > 25000000)
+                m_Spi.frequency(25000000);
+            else
+                m_Spi.frequency(m_FREQ);
         } else {
             //Try to initialize the card using CMD1(0x00100000) for 1 second
             for (int i = 0; i < 1000; i++) {
@@ -220,6 +244,12 @@
             if (token == 0x00) {
                 //This is an MMCv3 card
                 m_CardType = CARD_MMC;
+
+                //Increase the SPI frequency to full speed (up to 20MHz for MMCv3)
+                if (m_FREQ > 20000000)
+                    m_Spi.frequency(20000000);
+                else
+                    m_Spi.frequency(m_FREQ);
             } else {
                 //Initialization failed
                 m_CardType = CARD_UNKNOWN;
@@ -228,6 +258,15 @@
         }
     }
 
+    //Send ACMD42(0x00000000) to disconnect the internal pull-up resistor on pin 1 if necessary
+    if (m_CardType != CARD_MMC) {
+        if (commandTransaction(ACMD42, 0x00000000) != 0x00) {
+            //Initialization failed
+            m_CardType = CARD_UNKNOWN;
+            return m_Status;
+        }
+    }
+
     //Send CMD16(0x00000200) to force the block size to 512B if necessary
     if (m_CardType != CARD_SDHC) {
         if (commandTransaction(CMD16, 0x00000200) != 0x00) {
@@ -237,26 +276,9 @@
         }
     }
 
-    //Send ACMD42(0x00000000) to disconnect the internal pull-up resistor on pin 1 if necessary
-    if (m_CardType != CARD_MMC) {
-        if (commandTransaction(ACMD42, 0x00000000) != 0x00) {
-            //Initialization failed
-            m_CardType = CARD_UNKNOWN;
-            return m_Status;
-        }
-    }
-
     //The card is now initialized
     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_FREQ > 20000000)
-        m_Spi.frequency(20000000);
-    else if (m_FREQ > 25000000)
-        m_Spi.frequency(25000000);
-    else
-        m_Spi.frequency(m_FREQ);
-
     //Return the disk status
     return m_Status;
 }
@@ -369,7 +391,7 @@
 void SDFileSystem::checkSocket()
 {
     //Check if a card is in the socket
-    if (m_Cd == m_CD_ASSERT) {
+    if (m_Cd == m_CdAssert) {
         //The socket is occupied, clear the STA_NODISK flag
         m_Status &= ~STA_NODISK;
     } else {