Test of Embedded Artists LPCXpresso baseboard ethernet, SD card, audio and OLED display facilities. The program displays the day, date and time on the baseboard OLED and sounds the Big Ben chimes on the hour and quarter hour. On initial startup the program checks that the mbed clock is set and that the chime wav files can be accessed on the SD card. If not it asks to be connected to the internet to obtain the current time and to download the wav files to the SD card.

Dependencies:   EthernetNetIf NTPClient_NetServices mbed EAOLED

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SDHCFileSystem.cpp Source File

SDHCFileSystem.cpp

00001 /* mbed SDFileSystem Library, for providing file access to SD cards
00002  * Copyright (c) 2008-2010, sford
00003  *
00004  * Permission is hereby granted, free of charge, to any person obtaining a copy
00005  * of this software and associated documentation files (the "Software"), to deal
00006  * in the Software without restriction, including without limitation the rights
00007  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
00008  * copies of the Software, and to permit persons to whom the Software is
00009  * furnished to do so, subject to the following conditions:
00010  *
00011  * The above copyright notice and this permission notice shall be included in
00012  * all copies or substantial portions of the Software.
00013  *
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00017  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00018  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00019  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00020  * THE SOFTWARE.
00021  */
00022 
00023 /* Introduction
00024  * ------------
00025  * SD and MMC cards support a number of interfaces, but common to them all
00026  * is one based on SPI. This is the one I'm implmenting because it means
00027  * it is much more portable even though not so performant, and we already 
00028  * have the mbed SPI Interface!
00029  *
00030  * The main reference I'm using is Chapter 7, "SPI Mode" of: 
00031  *  http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
00032  *
00033  * SPI Startup
00034  * -----------
00035  * The SD card powers up in SD mode. The SPI interface mode is selected by
00036  * asserting CS low and sending the reset command (CMD0). The card will 
00037  * respond with a (R1) response.
00038  *
00039  * CMD8 is optionally sent to determine the voltage range supported, and 
00040  * indirectly determine whether it is a version 1.x SD/non-SD card or 
00041  * version 2.x. I'll just ignore this for now.
00042  *
00043  * ACMD41 is repeatedly issued to initialise the card, until "in idle"
00044  * (bit 0) of the R1 response goes to '0', indicating it is initialised.
00045  *
00046  * You should also indicate whether the host supports High Capicity cards,
00047  * and check whether the card is high capacity - i'll also ignore this
00048  *
00049  * SPI Protocol
00050  * ------------
00051  * The SD SPI protocol is based on transactions made up of 8-bit words, with
00052  * the host starting every bus transaction by asserting the CS signal low. The
00053  * card always responds to commands, data blocks and errors.
00054  * 
00055  * The protocol supports a CRC, but by default it is off (except for the 
00056  * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
00057  * I'll leave the CRC off I think! 
00058  * 
00059  * Standard capacity cards have variable data block sizes, whereas High 
00060  * Capacity cards fix the size of data block to 512 bytes. I'll therefore
00061  * just always use the Standard Capacity cards with a block size of 512 bytes.
00062  * This is set with CMD16.
00063  *
00064  * You can read and write single blocks (CMD17, CMD25) or multiple blocks 
00065  * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
00066  * the card gets a read command, it responds with a response token, and then 
00067  * a data token or an error.
00068  * 
00069  * SPI Command Format
00070  * ------------------
00071  * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
00072  *
00073  * +---------------+------------+------------+-----------+----------+--------------+
00074  * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
00075  * +---------------+------------+------------+-----------+----------+--------------+
00076  *
00077  * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
00078  *
00079  * All Application Specific commands shall be preceded with APP_CMD (CMD55).
00080  *
00081  * SPI Response Format
00082  * -------------------
00083  * The main response format (R1) is a status byte (normally zero). Key flags:
00084  *  idle - 1 if the card is in an idle state/initialising 
00085  *  cmd  - 1 if an illegal command code was detected
00086  *
00087  *    +-------------------------------------------------+
00088  * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
00089  *    +-------------------------------------------------+
00090  *
00091  * R1b is the same, except it is followed by a busy signal (zeros) until
00092  * the first non-zero byte when it is ready again.
00093  *
00094  * Data Response Token
00095  * -------------------
00096  * Every data block written to the card is acknowledged by a byte 
00097  * response token
00098  *
00099  * +----------------------+
00100  * | xxx | 0 | status | 1 |
00101  * +----------------------+
00102  *              010 - OK!
00103  *              101 - CRC Error
00104  *              110 - Write Error
00105  *
00106  * Single Block Read and Write
00107  * ---------------------------
00108  *
00109  * Block transfers have a byte header, followed by the data, followed
00110  * by a 16-bit CRC. In our case, the data will always be 512 bytes.
00111  *  
00112  * +------+---------+---------+- -  - -+---------+-----------+----------+
00113  * | 0xFE | data[0] | data[1] |        | data[n] | crc[15:8] | crc[7:0] | 
00114  * +------+---------+---------+- -  - -+---------+-----------+----------+
00115  */
00116  
00117  /*
00118  * Comment: Changes for SDHC support till 32GB 
00119  * Name:    KB
00120  * Date:    07/24/2010
00121  * Release: 0.1
00122  */
00123  
00124 #include "SDHCFileSystem.h"
00125 
00126 #define DEBUG
00127 #define SD_COMMAND_TIMEOUT 5000
00128 
00129 
00130 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) :
00131   FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs) {
00132       _cs = 1; 
00133 }
00134 
00135 #define R1_IDLE_STATE           (1 << 0)
00136 #define R1_ERASE_RESET          (1 << 1)
00137 #define R1_ILLEGAL_COMMAND      (1 << 2)
00138 #define R1_COM_CRC_ERROR        (1 << 3)
00139 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
00140 #define R1_ADDRESS_ERROR        (1 << 5)
00141 #define R1_PARAMETER_ERROR      (1 << 6)
00142 
00143 // Types
00144 //  - v1.x Standard Capacity
00145 //  - v2.x Standard Capacity
00146 //  - v2.x High Capacity
00147 //  - Not recognised as an SD Card
00148 
00149 #define SDCARD_FAIL 0
00150 #define SDCARD_V1   1
00151 #define SDCARD_V2   2
00152 #define SDCARD_V2HC 3
00153 
00154 int SDFileSystem::initialise_card() {
00155     // Set to 100kHz for initialisation, and clock card with cs = 1
00156     _spi.frequency(100000); 
00157     _cs = 1;
00158     for(int i=0; i<16; i++) {   
00159         _spi.write(0xFF);
00160     }
00161 
00162     // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
00163     if(_cmd(0, 0) != R1_IDLE_STATE) { 
00164         fprintf(stderr, "No disk, or could not put SD card in to SPI idle state\n");
00165         return SDCARD_FAIL;
00166     }
00167 
00168     // send CMD8 to determine whther it is ver 2.x
00169     int r = _cmd8();
00170     if(r == R1_IDLE_STATE) {
00171         return initialise_card_v2();
00172     } else if(r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
00173         return initialise_card_v1();
00174     } else {
00175         fprintf(stderr, "Not in idle state after sending CMD8 (not an SD card?)\n");
00176         return SDCARD_FAIL;
00177     }
00178 }
00179 
00180 int SDFileSystem::initialise_card_v1() {
00181     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00182         _cmd(55, 0); 
00183         if(_cmd(41, 0) == 0) { 
00184             cdv = 512;
00185             #ifdef DEBUG 
00186             printf("\n\rInit: SEDCARD_V1\n\r");
00187             #endif
00188             return SDCARD_V1;
00189         }
00190     }
00191 
00192     fprintf(stderr, "Timeout waiting for v1.x card\n");
00193     return SDCARD_FAIL;
00194 }
00195 
00196 int SDFileSystem::initialise_card_v2() {
00197     
00198     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00199         wait_ms(50);
00200         _cmd58();
00201         _cmd(55, 0); 
00202         if(_cmd(41, 0x40000000) == 0) { 
00203             _cmd58();
00204             #ifdef DEBUG
00205             printf("\n\rInit: SDCARD_V2\n\r");
00206             #endif
00207             cdv = 1;
00208             return SDCARD_V2;
00209         }
00210     }
00211 
00212     fprintf(stderr, "Timeout waiting for v2.x card\n");
00213     return SDCARD_FAIL;
00214 }
00215 
00216 int SDFileSystem::disk_initialize() {
00217 
00218     int i = initialise_card();
00219     #ifdef DEBUG 
00220     printf("init card = %d\n", i);
00221     #endif
00222     _sectors = _sd_sectors();
00223 
00224     // Set block length to 512 (CMD16)
00225     if(_cmd(16, 512) != 0) {
00226         fprintf(stderr, "Set 512-byte block timed out\n");
00227         return 1;
00228     }
00229         
00230     _spi.frequency(1000000); // Set to 1MHz for data transfer
00231     return 0;
00232 }
00233 
00234 int SDFileSystem::disk_write(const char *buffer, int block_number) {
00235     // set write address for single block (CMD24)
00236     if(_cmd(24, block_number * cdv) != 0) {
00237         return 1;
00238     }
00239 
00240     // send the data block
00241     _write(buffer, 512);    
00242     return 0;    
00243 }
00244 
00245 int SDFileSystem::disk_read(char *buffer, int block_number) {        
00246     // set read address for single block (CMD17)
00247     if(_cmd(17, block_number * cdv) != 0) {
00248         return 1;
00249     }
00250     
00251     // receive the data
00252     _read(buffer, 512);
00253     return 0;
00254 }
00255 
00256 int SDFileSystem::disk_status() { return 0; }
00257 int SDFileSystem::disk_sync() { return 0; }
00258 int SDFileSystem::disk_sectors() { return _sectors; }
00259 
00260 // PRIVATE FUNCTIONS
00261 
00262 int SDFileSystem::_cmd(int cmd, int arg) {
00263     _cs = 0; 
00264 
00265     // send a command
00266     _spi.write(0x40 | cmd);
00267     _spi.write(arg >> 24);
00268     _spi.write(arg >> 16);
00269     _spi.write(arg >> 8);
00270     _spi.write(arg >> 0);
00271     _spi.write(0x95);
00272 
00273     // wait for the repsonse (response[7] == 0)
00274     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00275         int response = _spi.write(0xFF);
00276         if(!(response & 0x80)) {
00277             _cs = 1;
00278             _spi.write(0xFF);
00279             return response;
00280         }
00281     }
00282     _cs = 1;
00283     _spi.write(0xFF);
00284     return -1; // timeout
00285 }
00286 int SDFileSystem::_cmdx(int cmd, int arg) {
00287     _cs = 0; 
00288 
00289     // send a command
00290     _spi.write(0x40 | cmd);
00291     _spi.write(arg >> 24);
00292     _spi.write(arg >> 16);
00293     _spi.write(arg >> 8);
00294     _spi.write(arg >> 0);
00295     _spi.write(0x95);
00296 
00297     // wait for the repsonse (response[7] == 0)
00298     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00299         int response = _spi.write(0xFF);
00300         if(!(response & 0x80)) {
00301             return response;
00302         }
00303     }
00304     _cs = 1;
00305     _spi.write(0xFF);
00306     return -1; // timeout
00307 }
00308 
00309 
00310 int SDFileSystem::_cmd58() {
00311     _cs = 0; 
00312     int arg = 0;
00313     
00314     // send a command
00315     _spi.write(0x40 | 58);
00316     _spi.write(arg >> 24);
00317     _spi.write(arg >> 16);
00318     _spi.write(arg >> 8);
00319     _spi.write(arg >> 0);
00320     _spi.write(0x95);
00321 
00322     // wait for the repsonse (response[7] == 0)
00323     for(int i=0; i<SD_COMMAND_TIMEOUT; i++) {
00324         int response = _spi.write(0xFF);
00325         if(!(response & 0x80)) {
00326             int ocr = _spi.write(0xFF) << 24;
00327             ocr |= _spi.write(0xFF) << 16;
00328             ocr |= _spi.write(0xFF) << 8;
00329             ocr |= _spi.write(0xFF) << 0;
00330 //            printf("OCR = 0x%08X\n", ocr);
00331             _cs = 1;
00332             _spi.write(0xFF);
00333             return response;
00334         }
00335     }
00336     _cs = 1;
00337     _spi.write(0xFF);
00338     return -1; // timeout
00339 }
00340 
00341 int SDFileSystem::_cmd8() {
00342     _cs = 0; 
00343     
00344     // send a command
00345     _spi.write(0x40 | 8); // CMD8
00346     _spi.write(0x00);     // reserved
00347     _spi.write(0x00);     // reserved
00348     _spi.write(0x01);     // 3.3v
00349     _spi.write(0xAA);     // check pattern
00350     _spi.write(0x87);     // crc
00351 
00352     // wait for the repsonse (response[7] == 0)
00353     for(int i=0; i<SD_COMMAND_TIMEOUT * 1000; i++) {
00354         char response[5];
00355         response[0] = _spi.write(0xFF);
00356         if(!(response[0] & 0x80)) {
00357                 for(int j=1; j<5; j++) {
00358                     response[i] = _spi.write(0xFF);
00359                 }
00360                 _cs = 1;
00361                 _spi.write(0xFF);
00362                 return response[0];
00363         }
00364     }
00365     _cs = 1;
00366     _spi.write(0xFF);
00367     return -1; // timeout
00368 }
00369 
00370 int SDFileSystem::_read(char *buffer, int length) {
00371     _cs = 0;
00372 
00373     // read until start byte (0xFF)
00374     while(_spi.write(0xFF) != 0xFE);
00375 
00376     // read data
00377     for(int i=0; i<length; i++) {
00378         buffer[i] = _spi.write(0xFF);
00379     }
00380     _spi.write(0xFF); // checksum
00381     _spi.write(0xFF);
00382 
00383     _cs = 1;    
00384     _spi.write(0xFF);
00385     return 0;
00386 }
00387 
00388 int SDFileSystem::_write(const char *buffer, int length) {
00389     _cs = 0;
00390     
00391     // indicate start of block
00392     _spi.write(0xFE);
00393     
00394     // write the data
00395     for(int i=0; i<length; i++) {
00396         _spi.write(buffer[i]);
00397     }
00398     
00399     // write the checksum
00400     _spi.write(0xFF); 
00401     _spi.write(0xFF);
00402 
00403     // check the repsonse token
00404     if((_spi.write(0xFF) & 0x1F) != 0x05) {
00405         _cs = 1;
00406         _spi.write(0xFF);        
00407         return 1;
00408     }
00409 
00410     // wait for write to finish
00411     while(_spi.write(0xFF) == 0);
00412 
00413     _cs = 1; 
00414     _spi.write(0xFF);
00415     return 0;
00416 }
00417 
00418 static int ext_bits(char *data, int msb, int lsb) {
00419     int bits = 0;
00420     int size = 1 + msb - lsb; 
00421     for(int i=0; i<size; i++) {
00422         int position = lsb + i;
00423         int byte = 15 - (position >> 3);
00424         int bit = position & 0x7;
00425         int value = (data[byte] >> bit) & 1;
00426         bits |= value << i;
00427     }
00428     return bits;
00429 }
00430 
00431 int SDFileSystem::_sd_sectors() {
00432 
00433     int c_size, c_size_mult, read_bl_len;
00434     int block_len, mult, blocknr, capacity;       
00435     int blocks, hc_c_size;
00436     uint64_t hc_capacity;
00437      
00438     // CMD9, Response R2 (R1 byte + 16-byte block read)
00439     if(_cmdx(9, 0) != 0) {
00440         fprintf(stderr, "Didn't get a response from the disk\n");
00441         return 0;
00442     }
00443     
00444     char csd[16];    
00445     if(_read(csd, 16) != 0) {
00446         fprintf(stderr, "Couldn't read csd response from disk\n");
00447         return 0;
00448     }
00449 
00450     // csd_structure : csd[127:126]
00451     // c_size        : csd[73:62]
00452     // c_size_mult   : csd[49:47]
00453     // read_bl_len   : csd[83:80] - the *maximum* read block length
00454    
00455     int csd_structure = ext_bits(csd, 127, 126);
00456     
00457     #ifdef DEBUG 
00458     printf("\n\rCSD_STRUCT = %d\n", csd_structure);
00459     #endif
00460      
00461     switch (csd_structure){
00462      case 0:
00463       cdv = 512;
00464       c_size = ext_bits(csd, 73, 62);
00465       c_size_mult = ext_bits(csd, 49, 47);
00466       read_bl_len = ext_bits(csd, 83, 80);
00467      
00468       block_len = 1 << read_bl_len;
00469       mult = 1 << (c_size_mult + 2);
00470       blocknr = (c_size + 1) * mult;
00471       capacity = blocknr * block_len;
00472       blocks = capacity / 512;
00473       #ifdef DEBUG 
00474       printf("\n\rSDCard\n\rc_size: %.4X \n\rcapacity: %.ld \n\rsectors: %d\n\r", c_size, capacity, blocks);
00475       #endif
00476       break;
00477     
00478      case 1:
00479       cdv = 1;
00480       hc_c_size = ext_bits(csd, 63, 48);
00481       int hc_read_bl_len = ext_bits(csd, 83, 80);
00482       hc_capacity = hc_c_size+1;   
00483       blocks = (hc_c_size+1)*1024;
00484       #ifdef DEBUG 
00485       printf("\n\rSDHC Card \n\rhc_c_size: %.4X \n\rcapacity: %.lld \n\rsectors: %d\n\r", hc_c_size, hc_capacity*512*1024, blocks);
00486       #endif
00487       break;
00488    
00489     default:    
00490        fprintf(stderr, "This disk tastes funny! I only know about type 0 CSD structures\n");
00491      return 0;
00492  //    break;
00493     };
00494  return blocks;
00495 }