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 15 17:54:13 2014 +0000
Parent:
11:67ddc53e3983
Child:
13:635147efa748
Commit message:
New switch types & minor 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 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 {
--- a/SDFileSystem.h	Thu Aug 14 22:27:07 2014 +0000
+++ b/SDFileSystem.h	Fri Aug 15 17:54:13 2014 +0000
@@ -30,7 +30,7 @@
  * #include "SDFileSystem.h"
  *
  * //Create an SDFileSystem object
- * SDFileSystem sd(p5, p6, p7, p20, "sd", p22)
+ * SDFileSystem sd(p5, p6, p7, p20, "sd", p22, SDFileSystem::SWITCH_NEG_NO);
  *
  * int main()
  * {
@@ -67,8 +67,10 @@
     /** Represents the different card detect switch types
      */
     enum SwitchType {
-        SWITCH_NO = 0,  /**< Switch shorts to GND when the socket is occupied (normally open) */
-        SWITCH_NC = 1   /**< Switch shorts to GND when the socket is empty (normally closed) */
+        SWITCH_POS_NO,  /**< Switch shorts to VDD when the socket is occupied (positive logic, normally open) */
+        SWITCH_POS_NC,  /**< Switch shorts to VDD when the socket is empty (positive logic, normally closed) */
+        SWITCH_NEG_NO,  /**< Switch shorts to GND when the socket is occupied (negative logic, normally open) */
+        SWITCH_NEG_NC   /**< Switch shorts to GND when the socket is empty (negative logic, normally closed) */
     };
 
     /** Represents the different SD/MMC card types
@@ -89,10 +91,10 @@
      * @param cs The SPI chip select pin.
      * @param name The name used to access the virtual filesystem.
      * @param cd The card detect pin.
-     * @param cdtype The type of card detect switch (defaults to SWITCH_NO).
+     * @param cdtype The type of card detect switch.
      * @param hz The SPI bus frequency (defaults to 1MHz).
      */
-    SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd, SwitchType cdtype = SWITCH_NO, int hz = 1000000);
+    SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd, SwitchType cdtype, int hz = 1000000);
 
     /** Get the detected SD/MMC card type
      *
@@ -163,7 +165,7 @@
     SPI m_Spi;
     DigitalOut m_Cs;
     InterruptIn m_Cd;
-    const int m_CD_ASSERT;
+    int m_CdAssert;
     const int m_FREQ;
     SDFileSystem::CardType m_CardType;
     bool m_Crc;