first 2016/02 SDFileSystemDMA inherited from Official SDFileSystem.

Dependents:   SDFileSystemDMA-test DmdFullRGB_0_1

Fork of SDFileSystemDMA by mi mi

SDFileSystemDMA is enhanced SDFileSystem library for STM32 micros by using DMA functionality.
Max read transfer rate reaches over 2MByte/sec at 24MHz SPI clock if enough read buffer size is set.
Even though minimum read buffer size (512Byte) is set, read transfer rate will reach over 1MByte/sec at 24MHz SPI Clock.
( but depends on the ability of each SD card)

Test program is here.
https://developer.mbed.org/users/mimi3/code/SDFileSystemDMA-test/

/media/uploads/mimi3/sdfilesystemdma-speed-test3-read-buffer-512byte.png

/media/uploads/mimi3/sdfilesystemdma-speed-test-buffer-vs-spi-clock-nucleo-f411re-96mhz.png

Supported SPI port is shown below table.

(v): Verified. It works well.
(w): Probably it will work well. (not tested)
(c): Only compiled. (not tested)
(f): Over flash.
(r): Only read mode. (when _FS_READONLY==1)
(u) Under construction
(z): Dose not work.

Caution

If your board has SRAM less than or equal to 8KB, the buffer size must be set to 512 Bytes.

Supported Boards:
Cortex-M0

BoardSRAMSPI1SPI2SPI3
NUCLEO-F030R88KB(v)
DISCO-F051R88KB(w)
NUCLEO-F031K64KB(f)
NUCLEO-F042K66KB(r)
NUCLEO-F070RB16KB(w)
NUCLEO-F072RB16KB(w)
NUCLEO-F091RC32KB(c)

Cortex-L0

BoardSRAMSPI1SPI2SPI3
DISCO-L053C88KB(c)
NUCLEO-L053R88KB(c)
NUCLEO-L073RZ20KB(c)

Cortex-M3

BoardSRAMSPI1SPI2SPI3
DISCO-F100RB8KB(v)(v)-
BLUEPILL-F103CB20KB(w)(w)-
NUCLEO-F103RB20KB(v)(v)-
NUCLEO-L152RE80KB(v)(w)-
MOTE-L152RC32KB(w)(w)-

Cortex-M4
F3

BoardSRAMSPI1SPI2SPI3
DISCO-F303VC40KB-(v)(v)
NUCLEO-F303RE64KB(w)(w)(w)
NUCLEO-F302R816KB--(c)
NUCLEO-F303K812KB(c)--
DISCO-F334C812KB(c)--
NUCLEO-F334R812KB(c)--

F4

BoardSPI1SPI2SPI3
ELMO-F411RE(w)-(w)
MTS-MDOT-F411RE(u)-(u)
MTS-DRAGONFLY-F411RE(w)-(w)
NUCLEO-F411RE(v)-(v)
NUCLEO-F401RE(w)-(w)
MTS-MDOT-F405RG(u)-(u)
NUCLEO-F410RB(c)-(c)
NUCLEO-F446RE(c)-(c)
NUCLEO-F429ZI(c)-(c)
B96B-F446VE(c)-(c)
NUCLEO-F446ZE(c)-(c)
DISCO-F429ZI(u)-(u)
DISCO-F469NI(c)-(c)

Information

This library is set to use "short file name" in SDFileSystemDMA/FATFileSystem/ChaN/ffconf.h . ( _USE_LFN=0)
You can change this option to _USE_LFN=1 .

Committer:
mimi3
Date:
Sun Jan 22 23:12:42 2017 +0900
Revision:
37:844a602e6edf
Parent:
29:5375c51d0cfc
Silent: warning

Who changed what in which revision?

UserRevisionLine numberNew contents of line
mimi3 0:853a612ffb16 1 /* mbed Microcontroller Library
mimi3 0:853a612ffb16 2 * Copyright (c) 2006-2012 ARM Limited
mimi3 0:853a612ffb16 3 *
mimi3 0:853a612ffb16 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
mimi3 0:853a612ffb16 5 * of this software and associated documentation files (the "Software"), to deal
mimi3 0:853a612ffb16 6 * in the Software without restriction, including without limitation the rights
mimi3 0:853a612ffb16 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
mimi3 0:853a612ffb16 8 * copies of the Software, and to permit persons to whom the Software is
mimi3 0:853a612ffb16 9 * furnished to do so, subject to the following conditions:
mimi3 0:853a612ffb16 10 *
mimi3 0:853a612ffb16 11 * The above copyright notice and this permission notice shall be included in
mimi3 0:853a612ffb16 12 * all copies or substantial portions of the Software.
mimi3 0:853a612ffb16 13 *
mimi3 0:853a612ffb16 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
mimi3 0:853a612ffb16 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
mimi3 0:853a612ffb16 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
mimi3 0:853a612ffb16 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
mimi3 0:853a612ffb16 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
mimi3 0:853a612ffb16 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
mimi3 0:853a612ffb16 20 * SOFTWARE.
mimi3 0:853a612ffb16 21 */
mimi3 0:853a612ffb16 22 /* Introduction
mimi3 0:853a612ffb16 23 * ------------
mimi3 0:853a612ffb16 24 * SD and MMC cards support a number of interfaces, but common to them all
mimi3 0:853a612ffb16 25 * is one based on SPI. This is the one I'm implmenting because it means
mimi3 0:853a612ffb16 26 * it is much more portable even though not so performant, and we already
mimi3 0:853a612ffb16 27 * have the mbed SPI Interface!
mimi3 0:853a612ffb16 28 *
mimi3 0:853a612ffb16 29 * The main reference I'm using is Chapter 7, "SPI Mode" of:
mimi3 0:853a612ffb16 30 * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
mimi3 0:853a612ffb16 31 *
mimi3 0:853a612ffb16 32 * SPI Startup
mimi3 0:853a612ffb16 33 * -----------
mimi3 0:853a612ffb16 34 * The SD card powers up in SD mode. The SPI interface mode is selected by
mimi3 0:853a612ffb16 35 * asserting CS low and sending the reset command (CMD0). The card will
mimi3 0:853a612ffb16 36 * respond with a (R1) response.
mimi3 0:853a612ffb16 37 *
mimi3 0:853a612ffb16 38 * CMD8 is optionally sent to determine the voltage range supported, and
mimi3 0:853a612ffb16 39 * indirectly determine whether it is a version 1.x SD/non-SD card or
mimi3 0:853a612ffb16 40 * version 2.x. I'll just ignore this for now.
mimi3 0:853a612ffb16 41 *
mimi3 0:853a612ffb16 42 * ACMD41 is repeatedly issued to initialise the card, until "in idle"
mimi3 0:853a612ffb16 43 * (bit 0) of the R1 response goes to '0', indicating it is initialised.
mimi3 0:853a612ffb16 44 *
mimi3 0:853a612ffb16 45 * You should also indicate whether the host supports High Capicity cards,
mimi3 0:853a612ffb16 46 * and check whether the card is high capacity - i'll also ignore this
mimi3 0:853a612ffb16 47 *
mimi3 0:853a612ffb16 48 * SPI Protocol
mimi3 0:853a612ffb16 49 * ------------
mimi3 0:853a612ffb16 50 * The SD SPI protocol is based on transactions made up of 8-bit words, with
mimi3 0:853a612ffb16 51 * the host starting every bus transaction by asserting the CS signal low. The
mimi3 0:853a612ffb16 52 * card always responds to commands, data blocks and errors.
mimi3 0:853a612ffb16 53 *
mimi3 0:853a612ffb16 54 * The protocol supports a CRC, but by default it is off (except for the
mimi3 0:853a612ffb16 55 * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
mimi3 0:853a612ffb16 56 * I'll leave the CRC off I think!
mimi3 0:853a612ffb16 57 *
mimi3 0:853a612ffb16 58 * Standard capacity cards have variable data block sizes, whereas High
mimi3 0:853a612ffb16 59 * Capacity cards fix the size of data block to 512 bytes. I'll therefore
mimi3 0:853a612ffb16 60 * just always use the Standard Capacity cards with a block size of 512 bytes.
mimi3 0:853a612ffb16 61 * This is set with CMD16.
mimi3 0:853a612ffb16 62 *
mimi3 0:853a612ffb16 63 * You can read and write single blocks (CMD17, CMD25) or multiple blocks
mimi3 0:853a612ffb16 64 * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
mimi3 0:853a612ffb16 65 * the card gets a read command, it responds with a response token, and then
mimi3 0:853a612ffb16 66 * a data token or an error.
mimi3 0:853a612ffb16 67 *
mimi3 0:853a612ffb16 68 * SPI Command Format
mimi3 0:853a612ffb16 69 * ------------------
mimi3 0:853a612ffb16 70 * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
mimi3 0:853a612ffb16 71 *
mimi3 0:853a612ffb16 72 * +---------------+------------+------------+-----------+----------+--------------+
mimi3 0:853a612ffb16 73 * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
mimi3 0:853a612ffb16 74 * +---------------+------------+------------+-----------+----------+--------------+
mimi3 0:853a612ffb16 75 *
mimi3 0:853a612ffb16 76 * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
mimi3 0:853a612ffb16 77 *
mimi3 0:853a612ffb16 78 * All Application Specific commands shall be preceded with APP_CMD (CMD55).
mimi3 0:853a612ffb16 79 *
mimi3 0:853a612ffb16 80 * SPI Response Format
mimi3 0:853a612ffb16 81 * -------------------
mimi3 0:853a612ffb16 82 * The main response format (R1) is a status byte (normally zero). Key flags:
mimi3 0:853a612ffb16 83 * idle - 1 if the card is in an idle state/initialising
mimi3 0:853a612ffb16 84 * cmd - 1 if an illegal command code was detected
mimi3 0:853a612ffb16 85 *
mimi3 0:853a612ffb16 86 * +-------------------------------------------------+
mimi3 0:853a612ffb16 87 * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
mimi3 0:853a612ffb16 88 * +-------------------------------------------------+
mimi3 0:853a612ffb16 89 *
mimi3 0:853a612ffb16 90 * R1b is the same, except it is followed by a busy signal (zeros) until
mimi3 0:853a612ffb16 91 * the first non-zero byte when it is ready again.
mimi3 0:853a612ffb16 92 *
mimi3 0:853a612ffb16 93 * Data Response Token
mimi3 0:853a612ffb16 94 * -------------------
mimi3 0:853a612ffb16 95 * Every data block written to the card is acknowledged by a byte
mimi3 0:853a612ffb16 96 * response token
mimi3 0:853a612ffb16 97 *
mimi3 0:853a612ffb16 98 * +----------------------+
mimi3 0:853a612ffb16 99 * | xxx | 0 | status | 1 |
mimi3 0:853a612ffb16 100 * +----------------------+
mimi3 0:853a612ffb16 101 * 010 - OK!
mimi3 0:853a612ffb16 102 * 101 - CRC Error
mimi3 0:853a612ffb16 103 * 110 - Write Error
mimi3 0:853a612ffb16 104 *
mimi3 0:853a612ffb16 105 * Single Block Read and Write
mimi3 0:853a612ffb16 106 * ---------------------------
mimi3 0:853a612ffb16 107 *
mimi3 0:853a612ffb16 108 * Block transfers have a byte header, followed by the data, followed
mimi3 0:853a612ffb16 109 * by a 16-bit CRC. In our case, the data will always be 512 bytes.
mimi3 0:853a612ffb16 110 *
mimi3 0:853a612ffb16 111 * +------+---------+---------+- - - -+---------+-----------+----------+
mimi3 0:853a612ffb16 112 * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] |
mimi3 0:853a612ffb16 113 * +------+---------+---------+- - - -+---------+-----------+----------+
mimi3 0:853a612ffb16 114 */
mimi3 0:853a612ffb16 115 #include "SDFileSystemDMA.h"
mimi3 0:853a612ffb16 116 #include "mbed_debug.h"
mimi3 21:41129109d6ab 117 #include "spi_dma.h"
mimi3 21:41129109d6ab 118
mimi3 21:41129109d6ab 119 #define __SPI_DMA__
mimi3 0:853a612ffb16 120
mimi3 0:853a612ffb16 121 #define SD_COMMAND_TIMEOUT 5000
mimi3 0:853a612ffb16 122
mimi3 0:853a612ffb16 123 #define SD_DBG 0
mimi3 0:853a612ffb16 124
mimi3 3:23e0dcc750fe 125 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, uint32_t hz) :
mimi3 2:0e871408d51b 126 FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0), _transfer_sck(hz) {
mimi3 0:853a612ffb16 127 _cs = 1;
mimi3 0:853a612ffb16 128
mimi3 0:853a612ffb16 129 // Set default to 100kHz for initialisation and 1MHz for data transfer
mimi3 0:853a612ffb16 130 _init_sck = 100000;
mimi3 2:0e871408d51b 131 //_transfer_sck = 12000000;
mimi3 21:41129109d6ab 132 _spi_id = spi_get_id(mosi, miso, sclk, NC);
mimi3 21:41129109d6ab 133 spi_dma_init( _spi_id );
mimi3 0:853a612ffb16 134 }
mimi3 0:853a612ffb16 135
mimi3 0:853a612ffb16 136 #define R1_IDLE_STATE (1 << 0)
mimi3 0:853a612ffb16 137 #define R1_ERASE_RESET (1 << 1)
mimi3 0:853a612ffb16 138 #define R1_ILLEGAL_COMMAND (1 << 2)
mimi3 0:853a612ffb16 139 #define R1_COM_CRC_ERROR (1 << 3)
mimi3 0:853a612ffb16 140 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
mimi3 0:853a612ffb16 141 #define R1_ADDRESS_ERROR (1 << 5)
mimi3 0:853a612ffb16 142 #define R1_PARAMETER_ERROR (1 << 6)
mimi3 0:853a612ffb16 143
mimi3 0:853a612ffb16 144 // Types
mimi3 0:853a612ffb16 145 // - v1.x Standard Capacity
mimi3 0:853a612ffb16 146 // - v2.x Standard Capacity
mimi3 0:853a612ffb16 147 // - v2.x High Capacity
mimi3 0:853a612ffb16 148 // - Not recognised as an SD Card
mimi3 0:853a612ffb16 149 #define SDCARD_FAIL 0
mimi3 0:853a612ffb16 150 #define SDCARD_V1 1
mimi3 0:853a612ffb16 151 #define SDCARD_V2 2
mimi3 0:853a612ffb16 152 #define SDCARD_V2HC 3
mimi3 0:853a612ffb16 153
mimi3 0:853a612ffb16 154 int SDFileSystem::initialise_card() {
mimi3 0:853a612ffb16 155 // Set to SCK for initialisation, and clock card with cs = 1
mimi3 0:853a612ffb16 156 _spi.frequency(_init_sck);
mimi3 0:853a612ffb16 157 _cs = 1;
mimi3 0:853a612ffb16 158 for (int i = 0; i < 16; i++) {
mimi3 0:853a612ffb16 159 _spi.write(0xFF);
mimi3 0:853a612ffb16 160 }
mimi3 0:853a612ffb16 161
mimi3 0:853a612ffb16 162 // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
mimi3 0:853a612ffb16 163 if (_cmd(0, 0) != R1_IDLE_STATE) {
mimi3 0:853a612ffb16 164 debug("No disk, or could not put SD card in to SPI idle state\n");
mimi3 0:853a612ffb16 165 return SDCARD_FAIL;
mimi3 0:853a612ffb16 166 }
mimi3 0:853a612ffb16 167
mimi3 0:853a612ffb16 168 // send CMD8 to determine whther it is ver 2.x
mimi3 0:853a612ffb16 169 int r = _cmd8();
mimi3 0:853a612ffb16 170 if (r == R1_IDLE_STATE) {
mimi3 0:853a612ffb16 171 return initialise_card_v2();
mimi3 0:853a612ffb16 172 } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
mimi3 0:853a612ffb16 173 return initialise_card_v1();
mimi3 0:853a612ffb16 174 } else {
mimi3 0:853a612ffb16 175 debug("Not in idle state after sending CMD8 (not an SD card?)\n");
mimi3 0:853a612ffb16 176 return SDCARD_FAIL;
mimi3 0:853a612ffb16 177 }
mimi3 0:853a612ffb16 178 }
mimi3 0:853a612ffb16 179
mimi3 0:853a612ffb16 180 int SDFileSystem::initialise_card_v1() {
mimi3 0:853a612ffb16 181 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 182 _cmd(55, 0);
mimi3 0:853a612ffb16 183 if (_cmd(41, 0) == 0) {
mimi3 0:853a612ffb16 184 cdv = 512;
mimi3 0:853a612ffb16 185 debug_if(SD_DBG, "\n\rInit: SEDCARD_V1\n\r");
mimi3 0:853a612ffb16 186 return SDCARD_V1;
mimi3 0:853a612ffb16 187 }
mimi3 0:853a612ffb16 188 }
mimi3 0:853a612ffb16 189
mimi3 0:853a612ffb16 190 debug("Timeout waiting for v1.x card\n");
mimi3 0:853a612ffb16 191 return SDCARD_FAIL;
mimi3 0:853a612ffb16 192 }
mimi3 0:853a612ffb16 193
mimi3 0:853a612ffb16 194 int SDFileSystem::initialise_card_v2() {
mimi3 0:853a612ffb16 195 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 196 wait_ms(50);
mimi3 0:853a612ffb16 197 _cmd58();
mimi3 0:853a612ffb16 198 _cmd(55, 0);
mimi3 0:853a612ffb16 199 if (_cmd(41, 0x40000000) == 0) {
mimi3 0:853a612ffb16 200 _cmd58();
mimi3 0:853a612ffb16 201 debug_if(SD_DBG, "\n\rInit: SDCARD_V2\n\r");
mimi3 0:853a612ffb16 202 cdv = 1;
mimi3 0:853a612ffb16 203 return SDCARD_V2;
mimi3 0:853a612ffb16 204 }
mimi3 0:853a612ffb16 205 }
mimi3 0:853a612ffb16 206
mimi3 0:853a612ffb16 207 debug("Timeout waiting for v2.x card\n");
mimi3 0:853a612ffb16 208 return SDCARD_FAIL;
mimi3 0:853a612ffb16 209 }
mimi3 0:853a612ffb16 210
mimi3 0:853a612ffb16 211 int SDFileSystem::disk_initialize() {
mimi3 0:853a612ffb16 212 _is_initialized = initialise_card();
mimi3 0:853a612ffb16 213 if (_is_initialized == 0) {
mimi3 0:853a612ffb16 214 debug("Fail to initialize card\n");
mimi3 0:853a612ffb16 215 return 1;
mimi3 0:853a612ffb16 216 }
mimi3 0:853a612ffb16 217 debug_if(SD_DBG, "init card = %d\n", _is_initialized);
mimi3 0:853a612ffb16 218 _sectors = _sd_sectors();
mimi3 0:853a612ffb16 219
mimi3 0:853a612ffb16 220 // Set block length to 512 (CMD16)
mimi3 0:853a612ffb16 221 if (_cmd(16, 512) != 0) {
mimi3 0:853a612ffb16 222 debug("Set 512-byte block timed out\n");
mimi3 0:853a612ffb16 223 return 1;
mimi3 0:853a612ffb16 224 }
mimi3 0:853a612ffb16 225
mimi3 0:853a612ffb16 226 // Set SCK for data transfer
mimi3 0:853a612ffb16 227 _spi.frequency(_transfer_sck);
mimi3 0:853a612ffb16 228 return 0;
mimi3 0:853a612ffb16 229 }
mimi3 0:853a612ffb16 230
mimi3 0:853a612ffb16 231 int SDFileSystem::disk_write(const uint8_t* buffer, uint32_t block_number, uint32_t count) {
mimi3 0:853a612ffb16 232 if (!_is_initialized) {
mimi3 0:853a612ffb16 233 return -1;
mimi3 0:853a612ffb16 234 }
mimi3 0:853a612ffb16 235
mimi3 0:853a612ffb16 236 for (uint32_t b = block_number; b < block_number + count; b++) {
mimi3 0:853a612ffb16 237 // set write address for single block (CMD24)
mimi3 0:853a612ffb16 238 if (_cmd(24, b * cdv) != 0) {
mimi3 0:853a612ffb16 239 return 1;
mimi3 0:853a612ffb16 240 }
mimi3 0:853a612ffb16 241
mimi3 0:853a612ffb16 242 // send the data block
mimi3 0:853a612ffb16 243 _write(buffer, 512);
mimi3 0:853a612ffb16 244 buffer += 512;
mimi3 0:853a612ffb16 245 }
mimi3 0:853a612ffb16 246
mimi3 0:853a612ffb16 247 return 0;
mimi3 0:853a612ffb16 248 }
mimi3 0:853a612ffb16 249
mimi3 0:853a612ffb16 250 int SDFileSystem::disk_read(uint8_t* buffer, uint32_t block_number, uint32_t count) {
mimi3 0:853a612ffb16 251 if (!_is_initialized) {
mimi3 0:853a612ffb16 252 return -1;
mimi3 0:853a612ffb16 253 }
mimi3 29:5375c51d0cfc 254
mimi3 29:5375c51d0cfc 255 if(count==1){
mimi3 29:5375c51d0cfc 256 //for (uint32_t b = block_number; b < block_number + count; b++) {
mimi3 29:5375c51d0cfc 257 // set read address for single block (CMD17)
mimi3 29:5375c51d0cfc 258 if (_cmd(17, block_number * cdv) != 0) {
mimi3 29:5375c51d0cfc 259 return 1;
mimi3 29:5375c51d0cfc 260 }
mimi3 29:5375c51d0cfc 261
mimi3 29:5375c51d0cfc 262 // receive the data
mimi3 29:5375c51d0cfc 263 _read(buffer, 512);
mimi3 29:5375c51d0cfc 264 buffer += 512;
mimi3 29:5375c51d0cfc 265 //}
mimi3 29:5375c51d0cfc 266 } else {
mimi3 29:5375c51d0cfc 267 int retry=4;
mimi3 29:5375c51d0cfc 268 while(retry--){
mimi3 29:5375c51d0cfc 269 if (_cmd(18, block_number * cdv ) == 0) { /* READ_MULTIPLE_BLOCK */
mimi3 29:5375c51d0cfc 270 do {
mimi3 29:5375c51d0cfc 271 _read(buffer, 512);
mimi3 29:5375c51d0cfc 272 buffer += 512;
mimi3 29:5375c51d0cfc 273 } while (--count);
mimi3 29:5375c51d0cfc 274 _cmd(12, 0); /* STOP_TRANSMISSION */
mimi3 29:5375c51d0cfc 275 break;
mimi3 29:5375c51d0cfc 276 }
mimi3 29:5375c51d0cfc 277 else {
mimi3 29:5375c51d0cfc 278 //error("\nCMD18: disk_read()");
mimi3 29:5375c51d0cfc 279 }
mimi3 29:5375c51d0cfc 280 }
mimi3 29:5375c51d0cfc 281 if(!retry) return 1;
mimi3 29:5375c51d0cfc 282 }
mimi3 0:853a612ffb16 283
mimi3 0:853a612ffb16 284 return 0;
mimi3 0:853a612ffb16 285 }
mimi3 0:853a612ffb16 286
mimi3 0:853a612ffb16 287 int SDFileSystem::disk_status() {
mimi3 0:853a612ffb16 288 // FATFileSystem::disk_status() returns 0 when initialized
mimi3 0:853a612ffb16 289 if (_is_initialized) {
mimi3 0:853a612ffb16 290 return 0;
mimi3 0:853a612ffb16 291 } else {
mimi3 0:853a612ffb16 292 return 1;
mimi3 0:853a612ffb16 293 }
mimi3 0:853a612ffb16 294 }
mimi3 0:853a612ffb16 295
mimi3 0:853a612ffb16 296 int SDFileSystem::disk_sync() { return 0; }
mimi3 0:853a612ffb16 297 uint32_t SDFileSystem::disk_sectors() { return _sectors; }
mimi3 0:853a612ffb16 298
mimi3 0:853a612ffb16 299
mimi3 0:853a612ffb16 300 // PRIVATE FUNCTIONS
mimi3 0:853a612ffb16 301 int SDFileSystem::_cmd(int cmd, int arg) {
mimi3 0:853a612ffb16 302 _cs = 0;
mimi3 0:853a612ffb16 303
mimi3 0:853a612ffb16 304 // send a command
mimi3 0:853a612ffb16 305 _spi.write(0x40 | cmd);
mimi3 0:853a612ffb16 306 _spi.write(arg >> 24);
mimi3 0:853a612ffb16 307 _spi.write(arg >> 16);
mimi3 0:853a612ffb16 308 _spi.write(arg >> 8);
mimi3 0:853a612ffb16 309 _spi.write(arg >> 0);
mimi3 0:853a612ffb16 310 _spi.write(0x95);
mimi3 0:853a612ffb16 311
mimi3 0:853a612ffb16 312 // wait for the repsonse (response[7] == 0)
mimi3 0:853a612ffb16 313 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 314 int response = _spi.write(0xFF);
mimi3 0:853a612ffb16 315 if (!(response & 0x80)) {
mimi3 0:853a612ffb16 316 _cs = 1;
mimi3 0:853a612ffb16 317 _spi.write(0xFF);
mimi3 0:853a612ffb16 318 return response;
mimi3 0:853a612ffb16 319 }
mimi3 0:853a612ffb16 320 }
mimi3 0:853a612ffb16 321 _cs = 1;
mimi3 0:853a612ffb16 322 _spi.write(0xFF);
mimi3 0:853a612ffb16 323 return -1; // timeout
mimi3 0:853a612ffb16 324 }
mimi3 0:853a612ffb16 325 int SDFileSystem::_cmdx(int cmd, int arg) {
mimi3 0:853a612ffb16 326 _cs = 0;
mimi3 0:853a612ffb16 327
mimi3 0:853a612ffb16 328 // send a command
mimi3 0:853a612ffb16 329 _spi.write(0x40 | cmd);
mimi3 0:853a612ffb16 330 _spi.write(arg >> 24);
mimi3 0:853a612ffb16 331 _spi.write(arg >> 16);
mimi3 0:853a612ffb16 332 _spi.write(arg >> 8);
mimi3 0:853a612ffb16 333 _spi.write(arg >> 0);
mimi3 0:853a612ffb16 334 _spi.write(0x95);
mimi3 0:853a612ffb16 335
mimi3 0:853a612ffb16 336 // wait for the repsonse (response[7] == 0)
mimi3 0:853a612ffb16 337 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 338 int response = _spi.write(0xFF);
mimi3 0:853a612ffb16 339 if (!(response & 0x80)) {
mimi3 0:853a612ffb16 340 return response;
mimi3 0:853a612ffb16 341 }
mimi3 0:853a612ffb16 342 }
mimi3 0:853a612ffb16 343 _cs = 1;
mimi3 0:853a612ffb16 344 _spi.write(0xFF);
mimi3 0:853a612ffb16 345 return -1; // timeout
mimi3 0:853a612ffb16 346 }
mimi3 0:853a612ffb16 347
mimi3 0:853a612ffb16 348
mimi3 0:853a612ffb16 349 int SDFileSystem::_cmd58() {
mimi3 0:853a612ffb16 350 _cs = 0;
mimi3 0:853a612ffb16 351 int arg = 0;
mimi3 0:853a612ffb16 352
mimi3 0:853a612ffb16 353 // send a command
mimi3 0:853a612ffb16 354 _spi.write(0x40 | 58);
mimi3 0:853a612ffb16 355 _spi.write(arg >> 24);
mimi3 0:853a612ffb16 356 _spi.write(arg >> 16);
mimi3 0:853a612ffb16 357 _spi.write(arg >> 8);
mimi3 0:853a612ffb16 358 _spi.write(arg >> 0);
mimi3 0:853a612ffb16 359 _spi.write(0x95);
mimi3 0:853a612ffb16 360
mimi3 0:853a612ffb16 361 // wait for the repsonse (response[7] == 0)
mimi3 0:853a612ffb16 362 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 363 int response = _spi.write(0xFF);
mimi3 0:853a612ffb16 364 if (!(response & 0x80)) {
mimi3 0:853a612ffb16 365 int ocr = _spi.write(0xFF) << 24;
mimi3 0:853a612ffb16 366 ocr |= _spi.write(0xFF) << 16;
mimi3 0:853a612ffb16 367 ocr |= _spi.write(0xFF) << 8;
mimi3 0:853a612ffb16 368 ocr |= _spi.write(0xFF) << 0;
mimi3 0:853a612ffb16 369 _cs = 1;
mimi3 0:853a612ffb16 370 _spi.write(0xFF);
mimi3 0:853a612ffb16 371 return response;
mimi3 0:853a612ffb16 372 }
mimi3 0:853a612ffb16 373 }
mimi3 0:853a612ffb16 374 _cs = 1;
mimi3 0:853a612ffb16 375 _spi.write(0xFF);
mimi3 0:853a612ffb16 376 return -1; // timeout
mimi3 0:853a612ffb16 377 }
mimi3 0:853a612ffb16 378
mimi3 0:853a612ffb16 379 int SDFileSystem::_cmd8() {
mimi3 0:853a612ffb16 380 _cs = 0;
mimi3 0:853a612ffb16 381
mimi3 0:853a612ffb16 382 // send a command
mimi3 0:853a612ffb16 383 _spi.write(0x40 | 8); // CMD8
mimi3 0:853a612ffb16 384 _spi.write(0x00); // reserved
mimi3 0:853a612ffb16 385 _spi.write(0x00); // reserved
mimi3 0:853a612ffb16 386 _spi.write(0x01); // 3.3v
mimi3 0:853a612ffb16 387 _spi.write(0xAA); // check pattern
mimi3 0:853a612ffb16 388 _spi.write(0x87); // crc
mimi3 0:853a612ffb16 389
mimi3 0:853a612ffb16 390 // wait for the repsonse (response[7] == 0)
mimi3 0:853a612ffb16 391 for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) {
mimi3 0:853a612ffb16 392 char response[5];
mimi3 0:853a612ffb16 393 response[0] = _spi.write(0xFF);
mimi3 0:853a612ffb16 394 if (!(response[0] & 0x80)) {
mimi3 0:853a612ffb16 395 for (int j = 1; j < 5; j++) {
mimi3 0:853a612ffb16 396 response[i] = _spi.write(0xFF);
mimi3 0:853a612ffb16 397 }
mimi3 0:853a612ffb16 398 _cs = 1;
mimi3 0:853a612ffb16 399 _spi.write(0xFF);
mimi3 0:853a612ffb16 400 return response[0];
mimi3 0:853a612ffb16 401 }
mimi3 0:853a612ffb16 402 }
mimi3 0:853a612ffb16 403 _cs = 1;
mimi3 0:853a612ffb16 404 _spi.write(0xFF);
mimi3 0:853a612ffb16 405 return -1; // timeout
mimi3 0:853a612ffb16 406 }
mimi3 0:853a612ffb16 407
mimi3 0:853a612ffb16 408 int SDFileSystem::_read(uint8_t *buffer, uint32_t length) {
mimi3 0:853a612ffb16 409 _cs = 0;
mimi3 0:853a612ffb16 410
mimi3 0:853a612ffb16 411 // read until start byte (0xFF)
mimi3 37:844a602e6edf 412 while (_spi.write(0xFF) != 0xFE){/* just wait */}
mimi3 0:853a612ffb16 413
mimi3 0:853a612ffb16 414 // read data
mimi3 0:853a612ffb16 415 #if defined( __SPI_DMA__)
mimi3 0:853a612ffb16 416 uint8_t dummyByte = 0xFF;
mimi3 21:41129109d6ab 417 spi_dma_read( _spi_id, &dummyByte, buffer, length );
mimi3 0:853a612ffb16 418 #else
mimi3 0:853a612ffb16 419 for (uint32_t i = 0; i < length; i++) {
mimi3 0:853a612ffb16 420 buffer[i] = _spi.write(0xFF);
mimi3 0:853a612ffb16 421 }
mimi3 0:853a612ffb16 422 #endif
mimi3 0:853a612ffb16 423 _spi.write(0xFF); // checksum
mimi3 0:853a612ffb16 424 _spi.write(0xFF);
mimi3 0:853a612ffb16 425
mimi3 0:853a612ffb16 426 _cs = 1;
mimi3 0:853a612ffb16 427 _spi.write(0xFF);
mimi3 0:853a612ffb16 428 return 0;
mimi3 0:853a612ffb16 429 }
mimi3 0:853a612ffb16 430
mimi3 5:809e2eece945 431 int SDFileSystem::_write(const uint8_t *buffer, uint32_t length) {
mimi3 0:853a612ffb16 432 _cs = 0;
mimi3 0:853a612ffb16 433
mimi3 0:853a612ffb16 434 // indicate start of block
mimi3 0:853a612ffb16 435 _spi.write(0xFE);
mimi3 0:853a612ffb16 436
mimi3 0:853a612ffb16 437 // write the data
mimi3 0:853a612ffb16 438 #if defined( __SPI_DMA__)
mimi3 21:41129109d6ab 439 #if 1
mimi3 0:853a612ffb16 440 uint8_t dummyByte ;
mimi3 21:41129109d6ab 441 spi_dma_write( _spi_id, (uint8_t *)buffer, &dummyByte, length );
mimi3 0:853a612ffb16 442 #else
mimi3 0:853a612ffb16 443 for (uint32_t i = 0; i < length; i++) {
mimi3 0:853a612ffb16 444 _spi.write(buffer[i]);
mimi3 0:853a612ffb16 445 }
mimi3 0:853a612ffb16 446 #endif
mimi3 0:853a612ffb16 447 #else
mimi3 0:853a612ffb16 448 for (uint32_t i = 0; i < length; i++) {
mimi3 0:853a612ffb16 449 _spi.write(buffer[i]);
mimi3 0:853a612ffb16 450 }
mimi3 0:853a612ffb16 451 #endif
mimi3 0:853a612ffb16 452 // write the checksum
mimi3 0:853a612ffb16 453 _spi.write(0xFF);
mimi3 0:853a612ffb16 454 _spi.write(0xFF);
mimi3 0:853a612ffb16 455
mimi3 0:853a612ffb16 456 // check the response token
mimi3 0:853a612ffb16 457 if ((_spi.write(0xFF) & 0x1F) != 0x05) {
mimi3 0:853a612ffb16 458 _cs = 1;
mimi3 0:853a612ffb16 459 _spi.write(0xFF);
mimi3 0:853a612ffb16 460 return 1;
mimi3 0:853a612ffb16 461 }
mimi3 0:853a612ffb16 462
mimi3 0:853a612ffb16 463 // wait for write to finish
mimi3 0:853a612ffb16 464 while (_spi.write(0xFF) == 0);
mimi3 0:853a612ffb16 465
mimi3 0:853a612ffb16 466 _cs = 1;
mimi3 0:853a612ffb16 467 _spi.write(0xFF);
mimi3 0:853a612ffb16 468 return 0;
mimi3 0:853a612ffb16 469 }
mimi3 0:853a612ffb16 470
mimi3 0:853a612ffb16 471 static uint32_t ext_bits(unsigned char *data, int msb, int lsb) {
mimi3 0:853a612ffb16 472 uint32_t bits = 0;
mimi3 0:853a612ffb16 473 uint32_t size = 1 + msb - lsb;
mimi3 0:853a612ffb16 474 for (uint32_t i = 0; i < size; i++) {
mimi3 0:853a612ffb16 475 uint32_t position = lsb + i;
mimi3 0:853a612ffb16 476 uint32_t byte = 15 - (position >> 3);
mimi3 0:853a612ffb16 477 uint32_t bit = position & 0x7;
mimi3 0:853a612ffb16 478 uint32_t value = (data[byte] >> bit) & 1;
mimi3 0:853a612ffb16 479 bits |= value << i;
mimi3 0:853a612ffb16 480 }
mimi3 0:853a612ffb16 481 return bits;
mimi3 0:853a612ffb16 482 }
mimi3 0:853a612ffb16 483
mimi3 0:853a612ffb16 484 uint32_t SDFileSystem::_sd_sectors() {
mimi3 0:853a612ffb16 485 uint32_t c_size, c_size_mult, read_bl_len;
mimi3 0:853a612ffb16 486 uint32_t block_len, mult, blocknr, capacity;
mimi3 0:853a612ffb16 487 uint32_t hc_c_size;
mimi3 0:853a612ffb16 488 uint32_t blocks;
mimi3 0:853a612ffb16 489
mimi3 0:853a612ffb16 490 // CMD9, Response R2 (R1 byte + 16-byte block read)
mimi3 0:853a612ffb16 491 if (_cmdx(9, 0) != 0) {
mimi3 0:853a612ffb16 492 debug("Didn't get a response from the disk\n");
mimi3 0:853a612ffb16 493 return 0;
mimi3 0:853a612ffb16 494 }
mimi3 0:853a612ffb16 495
mimi3 0:853a612ffb16 496 uint8_t csd[16];
mimi3 0:853a612ffb16 497 if (_read(csd, 16) != 0) {
mimi3 0:853a612ffb16 498 debug("Couldn't read csd response from disk\n");
mimi3 0:853a612ffb16 499 return 0;
mimi3 0:853a612ffb16 500 }
mimi3 0:853a612ffb16 501
mimi3 0:853a612ffb16 502 // csd_structure : csd[127:126]
mimi3 0:853a612ffb16 503 // c_size : csd[73:62]
mimi3 0:853a612ffb16 504 // c_size_mult : csd[49:47]
mimi3 0:853a612ffb16 505 // read_bl_len : csd[83:80] - the *maximum* read block length
mimi3 0:853a612ffb16 506
mimi3 0:853a612ffb16 507 int csd_structure = ext_bits(csd, 127, 126);
mimi3 0:853a612ffb16 508
mimi3 0:853a612ffb16 509 switch (csd_structure) {
mimi3 0:853a612ffb16 510 case 0:
mimi3 0:853a612ffb16 511 cdv = 512;
mimi3 0:853a612ffb16 512 c_size = ext_bits(csd, 73, 62);
mimi3 0:853a612ffb16 513 c_size_mult = ext_bits(csd, 49, 47);
mimi3 0:853a612ffb16 514 read_bl_len = ext_bits(csd, 83, 80);
mimi3 0:853a612ffb16 515
mimi3 0:853a612ffb16 516 block_len = 1 << read_bl_len;
mimi3 0:853a612ffb16 517 mult = 1 << (c_size_mult + 2);
mimi3 0:853a612ffb16 518 blocknr = (c_size + 1) * mult;
mimi3 0:853a612ffb16 519 capacity = blocknr * block_len;
mimi3 0:853a612ffb16 520 blocks = capacity / 512;
mimi3 0:853a612ffb16 521 debug_if(SD_DBG, "\n\rSDCard\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks);
mimi3 0:853a612ffb16 522 break;
mimi3 0:853a612ffb16 523
mimi3 0:853a612ffb16 524 case 1:
mimi3 0:853a612ffb16 525 cdv = 1;
mimi3 0:853a612ffb16 526 hc_c_size = ext_bits(csd, 63, 48);
mimi3 0:853a612ffb16 527 blocks = (hc_c_size+1)*1024;
mimi3 0:853a612ffb16 528 debug_if(SD_DBG, "\n\rSDHC Card \n\rhc_c_size: %d\n\rcapacity: %lld \n\rsectors: %lld\n\r", hc_c_size, blocks*512, blocks);
mimi3 0:853a612ffb16 529 break;
mimi3 0:853a612ffb16 530
mimi3 0:853a612ffb16 531 default:
mimi3 0:853a612ffb16 532 debug("CSD struct unsupported\r\n");
mimi3 0:853a612ffb16 533 return 0;
mimi3 0:853a612ffb16 534 };
mimi3 0:853a612ffb16 535 return blocks;
mimi3 0:853a612ffb16 536 }