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 Feb 14 15:57:06 2016 +0900
Revision:
5:809e2eece945
Parent:
3:23e0dcc750fe
Child:
6:3f25251e2b78
DISCO-F303VC: OK. Verified

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 0:853a612ffb16 117
mimi3 0:853a612ffb16 118 #define SD_COMMAND_TIMEOUT 5000
mimi3 0:853a612ffb16 119
mimi3 0:853a612ffb16 120 #define SD_DBG 0
mimi3 0:853a612ffb16 121
mimi3 3:23e0dcc750fe 122 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, uint32_t hz) :
mimi3 2:0e871408d51b 123 FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0), _transfer_sck(hz) {
mimi3 0:853a612ffb16 124 _cs = 1;
mimi3 0:853a612ffb16 125
mimi3 0:853a612ffb16 126 // Set default to 100kHz for initialisation and 1MHz for data transfer
mimi3 0:853a612ffb16 127 _init_sck = 100000;
mimi3 2:0e871408d51b 128 //_transfer_sck = 12000000;
mimi3 0:853a612ffb16 129 }
mimi3 0:853a612ffb16 130
mimi3 0:853a612ffb16 131 #define R1_IDLE_STATE (1 << 0)
mimi3 0:853a612ffb16 132 #define R1_ERASE_RESET (1 << 1)
mimi3 0:853a612ffb16 133 #define R1_ILLEGAL_COMMAND (1 << 2)
mimi3 0:853a612ffb16 134 #define R1_COM_CRC_ERROR (1 << 3)
mimi3 0:853a612ffb16 135 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
mimi3 0:853a612ffb16 136 #define R1_ADDRESS_ERROR (1 << 5)
mimi3 0:853a612ffb16 137 #define R1_PARAMETER_ERROR (1 << 6)
mimi3 0:853a612ffb16 138
mimi3 0:853a612ffb16 139 // Types
mimi3 0:853a612ffb16 140 // - v1.x Standard Capacity
mimi3 0:853a612ffb16 141 // - v2.x Standard Capacity
mimi3 0:853a612ffb16 142 // - v2.x High Capacity
mimi3 0:853a612ffb16 143 // - Not recognised as an SD Card
mimi3 0:853a612ffb16 144 #define SDCARD_FAIL 0
mimi3 0:853a612ffb16 145 #define SDCARD_V1 1
mimi3 0:853a612ffb16 146 #define SDCARD_V2 2
mimi3 0:853a612ffb16 147 #define SDCARD_V2HC 3
mimi3 0:853a612ffb16 148
mimi3 0:853a612ffb16 149 int SDFileSystem::initialise_card() {
mimi3 0:853a612ffb16 150 // Set to SCK for initialisation, and clock card with cs = 1
mimi3 0:853a612ffb16 151 _spi.frequency(_init_sck);
mimi3 0:853a612ffb16 152 _cs = 1;
mimi3 0:853a612ffb16 153 for (int i = 0; i < 16; i++) {
mimi3 0:853a612ffb16 154 _spi.write(0xFF);
mimi3 0:853a612ffb16 155 }
mimi3 0:853a612ffb16 156
mimi3 0:853a612ffb16 157 // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
mimi3 0:853a612ffb16 158 if (_cmd(0, 0) != R1_IDLE_STATE) {
mimi3 0:853a612ffb16 159 debug("No disk, or could not put SD card in to SPI idle state\n");
mimi3 0:853a612ffb16 160 return SDCARD_FAIL;
mimi3 0:853a612ffb16 161 }
mimi3 0:853a612ffb16 162
mimi3 0:853a612ffb16 163 // send CMD8 to determine whther it is ver 2.x
mimi3 0:853a612ffb16 164 int r = _cmd8();
mimi3 0:853a612ffb16 165 if (r == R1_IDLE_STATE) {
mimi3 0:853a612ffb16 166 return initialise_card_v2();
mimi3 0:853a612ffb16 167 } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
mimi3 0:853a612ffb16 168 return initialise_card_v1();
mimi3 0:853a612ffb16 169 } else {
mimi3 0:853a612ffb16 170 debug("Not in idle state after sending CMD8 (not an SD card?)\n");
mimi3 0:853a612ffb16 171 return SDCARD_FAIL;
mimi3 0:853a612ffb16 172 }
mimi3 0:853a612ffb16 173 }
mimi3 0:853a612ffb16 174
mimi3 0:853a612ffb16 175 int SDFileSystem::initialise_card_v1() {
mimi3 0:853a612ffb16 176 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 177 _cmd(55, 0);
mimi3 0:853a612ffb16 178 if (_cmd(41, 0) == 0) {
mimi3 0:853a612ffb16 179 cdv = 512;
mimi3 0:853a612ffb16 180 debug_if(SD_DBG, "\n\rInit: SEDCARD_V1\n\r");
mimi3 0:853a612ffb16 181 return SDCARD_V1;
mimi3 0:853a612ffb16 182 }
mimi3 0:853a612ffb16 183 }
mimi3 0:853a612ffb16 184
mimi3 0:853a612ffb16 185 debug("Timeout waiting for v1.x card\n");
mimi3 0:853a612ffb16 186 return SDCARD_FAIL;
mimi3 0:853a612ffb16 187 }
mimi3 0:853a612ffb16 188
mimi3 0:853a612ffb16 189 int SDFileSystem::initialise_card_v2() {
mimi3 0:853a612ffb16 190 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 191 wait_ms(50);
mimi3 0:853a612ffb16 192 _cmd58();
mimi3 0:853a612ffb16 193 _cmd(55, 0);
mimi3 0:853a612ffb16 194 if (_cmd(41, 0x40000000) == 0) {
mimi3 0:853a612ffb16 195 _cmd58();
mimi3 0:853a612ffb16 196 debug_if(SD_DBG, "\n\rInit: SDCARD_V2\n\r");
mimi3 0:853a612ffb16 197 cdv = 1;
mimi3 0:853a612ffb16 198 return SDCARD_V2;
mimi3 0:853a612ffb16 199 }
mimi3 0:853a612ffb16 200 }
mimi3 0:853a612ffb16 201
mimi3 0:853a612ffb16 202 debug("Timeout waiting for v2.x card\n");
mimi3 0:853a612ffb16 203 return SDCARD_FAIL;
mimi3 0:853a612ffb16 204 }
mimi3 0:853a612ffb16 205
mimi3 0:853a612ffb16 206 int SDFileSystem::disk_initialize() {
mimi3 0:853a612ffb16 207 _is_initialized = initialise_card();
mimi3 0:853a612ffb16 208 if (_is_initialized == 0) {
mimi3 0:853a612ffb16 209 debug("Fail to initialize card\n");
mimi3 0:853a612ffb16 210 return 1;
mimi3 0:853a612ffb16 211 }
mimi3 0:853a612ffb16 212 debug_if(SD_DBG, "init card = %d\n", _is_initialized);
mimi3 0:853a612ffb16 213 _sectors = _sd_sectors();
mimi3 0:853a612ffb16 214
mimi3 0:853a612ffb16 215 // Set block length to 512 (CMD16)
mimi3 0:853a612ffb16 216 if (_cmd(16, 512) != 0) {
mimi3 0:853a612ffb16 217 debug("Set 512-byte block timed out\n");
mimi3 0:853a612ffb16 218 return 1;
mimi3 0:853a612ffb16 219 }
mimi3 0:853a612ffb16 220
mimi3 0:853a612ffb16 221 // Set SCK for data transfer
mimi3 0:853a612ffb16 222 _spi.frequency(_transfer_sck);
mimi3 0:853a612ffb16 223 return 0;
mimi3 0:853a612ffb16 224 }
mimi3 0:853a612ffb16 225
mimi3 0:853a612ffb16 226 int SDFileSystem::disk_write(const uint8_t* buffer, uint32_t block_number, uint32_t count) {
mimi3 0:853a612ffb16 227 if (!_is_initialized) {
mimi3 0:853a612ffb16 228 return -1;
mimi3 0:853a612ffb16 229 }
mimi3 0:853a612ffb16 230
mimi3 0:853a612ffb16 231 for (uint32_t b = block_number; b < block_number + count; b++) {
mimi3 0:853a612ffb16 232 // set write address for single block (CMD24)
mimi3 0:853a612ffb16 233 if (_cmd(24, b * cdv) != 0) {
mimi3 0:853a612ffb16 234 return 1;
mimi3 0:853a612ffb16 235 }
mimi3 0:853a612ffb16 236
mimi3 0:853a612ffb16 237 // send the data block
mimi3 0:853a612ffb16 238 _write(buffer, 512);
mimi3 0:853a612ffb16 239 buffer += 512;
mimi3 0:853a612ffb16 240 }
mimi3 0:853a612ffb16 241
mimi3 0:853a612ffb16 242 return 0;
mimi3 0:853a612ffb16 243 }
mimi3 0:853a612ffb16 244
mimi3 0:853a612ffb16 245 int SDFileSystem::disk_read(uint8_t* buffer, uint32_t block_number, uint32_t count) {
mimi3 0:853a612ffb16 246 if (!_is_initialized) {
mimi3 0:853a612ffb16 247 return -1;
mimi3 0:853a612ffb16 248 }
mimi3 0:853a612ffb16 249
mimi3 0:853a612ffb16 250 for (uint32_t b = block_number; b < block_number + count; b++) {
mimi3 0:853a612ffb16 251 // set read address for single block (CMD17)
mimi3 0:853a612ffb16 252 if (_cmd(17, b * cdv) != 0) {
mimi3 0:853a612ffb16 253 return 1;
mimi3 0:853a612ffb16 254 }
mimi3 0:853a612ffb16 255
mimi3 0:853a612ffb16 256 // receive the data
mimi3 0:853a612ffb16 257 _read(buffer, 512);
mimi3 0:853a612ffb16 258 buffer += 512;
mimi3 0:853a612ffb16 259 }
mimi3 0:853a612ffb16 260
mimi3 0:853a612ffb16 261 return 0;
mimi3 0:853a612ffb16 262 }
mimi3 0:853a612ffb16 263
mimi3 0:853a612ffb16 264 int SDFileSystem::disk_status() {
mimi3 0:853a612ffb16 265 // FATFileSystem::disk_status() returns 0 when initialized
mimi3 0:853a612ffb16 266 if (_is_initialized) {
mimi3 0:853a612ffb16 267 return 0;
mimi3 0:853a612ffb16 268 } else {
mimi3 0:853a612ffb16 269 return 1;
mimi3 0:853a612ffb16 270 }
mimi3 0:853a612ffb16 271 }
mimi3 0:853a612ffb16 272
mimi3 0:853a612ffb16 273 int SDFileSystem::disk_sync() { return 0; }
mimi3 0:853a612ffb16 274 uint32_t SDFileSystem::disk_sectors() { return _sectors; }
mimi3 0:853a612ffb16 275
mimi3 0:853a612ffb16 276
mimi3 0:853a612ffb16 277 // PRIVATE FUNCTIONS
mimi3 0:853a612ffb16 278 int SDFileSystem::_cmd(int cmd, int arg) {
mimi3 0:853a612ffb16 279 _cs = 0;
mimi3 0:853a612ffb16 280
mimi3 0:853a612ffb16 281 // send a command
mimi3 0:853a612ffb16 282 _spi.write(0x40 | cmd);
mimi3 0:853a612ffb16 283 _spi.write(arg >> 24);
mimi3 0:853a612ffb16 284 _spi.write(arg >> 16);
mimi3 0:853a612ffb16 285 _spi.write(arg >> 8);
mimi3 0:853a612ffb16 286 _spi.write(arg >> 0);
mimi3 0:853a612ffb16 287 _spi.write(0x95);
mimi3 0:853a612ffb16 288
mimi3 0:853a612ffb16 289 // wait for the repsonse (response[7] == 0)
mimi3 0:853a612ffb16 290 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 291 int response = _spi.write(0xFF);
mimi3 0:853a612ffb16 292 if (!(response & 0x80)) {
mimi3 0:853a612ffb16 293 _cs = 1;
mimi3 0:853a612ffb16 294 _spi.write(0xFF);
mimi3 0:853a612ffb16 295 return response;
mimi3 0:853a612ffb16 296 }
mimi3 0:853a612ffb16 297 }
mimi3 0:853a612ffb16 298 _cs = 1;
mimi3 0:853a612ffb16 299 _spi.write(0xFF);
mimi3 0:853a612ffb16 300 return -1; // timeout
mimi3 0:853a612ffb16 301 }
mimi3 0:853a612ffb16 302 int SDFileSystem::_cmdx(int cmd, int arg) {
mimi3 0:853a612ffb16 303 _cs = 0;
mimi3 0:853a612ffb16 304
mimi3 0:853a612ffb16 305 // send a command
mimi3 0:853a612ffb16 306 _spi.write(0x40 | cmd);
mimi3 0:853a612ffb16 307 _spi.write(arg >> 24);
mimi3 0:853a612ffb16 308 _spi.write(arg >> 16);
mimi3 0:853a612ffb16 309 _spi.write(arg >> 8);
mimi3 0:853a612ffb16 310 _spi.write(arg >> 0);
mimi3 0:853a612ffb16 311 _spi.write(0x95);
mimi3 0:853a612ffb16 312
mimi3 0:853a612ffb16 313 // wait for the repsonse (response[7] == 0)
mimi3 0:853a612ffb16 314 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 315 int response = _spi.write(0xFF);
mimi3 0:853a612ffb16 316 if (!(response & 0x80)) {
mimi3 0:853a612ffb16 317 return response;
mimi3 0:853a612ffb16 318 }
mimi3 0:853a612ffb16 319 }
mimi3 0:853a612ffb16 320 _cs = 1;
mimi3 0:853a612ffb16 321 _spi.write(0xFF);
mimi3 0:853a612ffb16 322 return -1; // timeout
mimi3 0:853a612ffb16 323 }
mimi3 0:853a612ffb16 324
mimi3 0:853a612ffb16 325
mimi3 0:853a612ffb16 326 int SDFileSystem::_cmd58() {
mimi3 0:853a612ffb16 327 _cs = 0;
mimi3 0:853a612ffb16 328 int arg = 0;
mimi3 0:853a612ffb16 329
mimi3 0:853a612ffb16 330 // send a command
mimi3 0:853a612ffb16 331 _spi.write(0x40 | 58);
mimi3 0:853a612ffb16 332 _spi.write(arg >> 24);
mimi3 0:853a612ffb16 333 _spi.write(arg >> 16);
mimi3 0:853a612ffb16 334 _spi.write(arg >> 8);
mimi3 0:853a612ffb16 335 _spi.write(arg >> 0);
mimi3 0:853a612ffb16 336 _spi.write(0x95);
mimi3 0:853a612ffb16 337
mimi3 0:853a612ffb16 338 // wait for the repsonse (response[7] == 0)
mimi3 0:853a612ffb16 339 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
mimi3 0:853a612ffb16 340 int response = _spi.write(0xFF);
mimi3 0:853a612ffb16 341 if (!(response & 0x80)) {
mimi3 0:853a612ffb16 342 int ocr = _spi.write(0xFF) << 24;
mimi3 0:853a612ffb16 343 ocr |= _spi.write(0xFF) << 16;
mimi3 0:853a612ffb16 344 ocr |= _spi.write(0xFF) << 8;
mimi3 0:853a612ffb16 345 ocr |= _spi.write(0xFF) << 0;
mimi3 0:853a612ffb16 346 _cs = 1;
mimi3 0:853a612ffb16 347 _spi.write(0xFF);
mimi3 0:853a612ffb16 348 return response;
mimi3 0:853a612ffb16 349 }
mimi3 0:853a612ffb16 350 }
mimi3 0:853a612ffb16 351 _cs = 1;
mimi3 0:853a612ffb16 352 _spi.write(0xFF);
mimi3 0:853a612ffb16 353 return -1; // timeout
mimi3 0:853a612ffb16 354 }
mimi3 0:853a612ffb16 355
mimi3 0:853a612ffb16 356 int SDFileSystem::_cmd8() {
mimi3 0:853a612ffb16 357 _cs = 0;
mimi3 0:853a612ffb16 358
mimi3 0:853a612ffb16 359 // send a command
mimi3 0:853a612ffb16 360 _spi.write(0x40 | 8); // CMD8
mimi3 0:853a612ffb16 361 _spi.write(0x00); // reserved
mimi3 0:853a612ffb16 362 _spi.write(0x00); // reserved
mimi3 0:853a612ffb16 363 _spi.write(0x01); // 3.3v
mimi3 0:853a612ffb16 364 _spi.write(0xAA); // check pattern
mimi3 0:853a612ffb16 365 _spi.write(0x87); // crc
mimi3 0:853a612ffb16 366
mimi3 0:853a612ffb16 367 // wait for the repsonse (response[7] == 0)
mimi3 0:853a612ffb16 368 for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) {
mimi3 0:853a612ffb16 369 char response[5];
mimi3 0:853a612ffb16 370 response[0] = _spi.write(0xFF);
mimi3 0:853a612ffb16 371 if (!(response[0] & 0x80)) {
mimi3 0:853a612ffb16 372 for (int j = 1; j < 5; j++) {
mimi3 0:853a612ffb16 373 response[i] = _spi.write(0xFF);
mimi3 0:853a612ffb16 374 }
mimi3 0:853a612ffb16 375 _cs = 1;
mimi3 0:853a612ffb16 376 _spi.write(0xFF);
mimi3 0:853a612ffb16 377 return response[0];
mimi3 0:853a612ffb16 378 }
mimi3 0:853a612ffb16 379 }
mimi3 0:853a612ffb16 380 _cs = 1;
mimi3 0:853a612ffb16 381 _spi.write(0xFF);
mimi3 0:853a612ffb16 382 return -1; // timeout
mimi3 0:853a612ffb16 383 }
mimi3 0:853a612ffb16 384
mimi3 0:853a612ffb16 385 #define __SPI_DMA__
mimi3 0:853a612ffb16 386 #include "spi_dma.h"
mimi3 5:809e2eece945 387 #if defined(TARGET_DISCO_F303VC)
mimi3 5:809e2eece945 388 SPI_TypeDef *spi_id = SPI3;
mimi3 5:809e2eece945 389 #else
mimi3 0:853a612ffb16 390 SPI_TypeDef *spi_id = SPI1;
mimi3 5:809e2eece945 391 #endif
mimi3 0:853a612ffb16 392 int SDFileSystem::_read(uint8_t *buffer, uint32_t length) {
mimi3 0:853a612ffb16 393 _cs = 0;
mimi3 0:853a612ffb16 394
mimi3 0:853a612ffb16 395 // read until start byte (0xFF)
mimi3 0:853a612ffb16 396 while (_spi.write(0xFF) != 0xFE);
mimi3 0:853a612ffb16 397
mimi3 0:853a612ffb16 398 // read data
mimi3 0:853a612ffb16 399 #if defined( __SPI_DMA__)
mimi3 0:853a612ffb16 400 uint8_t dummyByte = 0xFF;
mimi3 5:809e2eece945 401 spi_dma_read( spi_id, &dummyByte, buffer, length );
mimi3 0:853a612ffb16 402 #else
mimi3 0:853a612ffb16 403 for (uint32_t i = 0; i < length; i++) {
mimi3 0:853a612ffb16 404 buffer[i] = _spi.write(0xFF);
mimi3 0:853a612ffb16 405 }
mimi3 0:853a612ffb16 406 #endif
mimi3 0:853a612ffb16 407 _spi.write(0xFF); // checksum
mimi3 0:853a612ffb16 408 _spi.write(0xFF);
mimi3 0:853a612ffb16 409
mimi3 0:853a612ffb16 410 _cs = 1;
mimi3 0:853a612ffb16 411 _spi.write(0xFF);
mimi3 0:853a612ffb16 412 return 0;
mimi3 0:853a612ffb16 413 }
mimi3 0:853a612ffb16 414
mimi3 5:809e2eece945 415 int SDFileSystem::_write(const uint8_t *buffer, uint32_t length) {
mimi3 0:853a612ffb16 416 _cs = 0;
mimi3 0:853a612ffb16 417
mimi3 0:853a612ffb16 418 // indicate start of block
mimi3 0:853a612ffb16 419 _spi.write(0xFE);
mimi3 0:853a612ffb16 420
mimi3 0:853a612ffb16 421 // write the data
mimi3 0:853a612ffb16 422 #if defined( __SPI_DMA__)
mimi3 0:853a612ffb16 423 #if 0 /* Dangerous !! Very bugy at this moment ! Absolutely breaks SD card.*/
mimi3 0:853a612ffb16 424 uint8_t dummyByte ;
mimi3 0:853a612ffb16 425 spi_dma_write( spi_id, (uint8_t *)buffer, &dummyByte, length );
mimi3 0:853a612ffb16 426 #else
mimi3 0:853a612ffb16 427 for (uint32_t i = 0; i < length; i++) {
mimi3 0:853a612ffb16 428 _spi.write(buffer[i]);
mimi3 0:853a612ffb16 429 }
mimi3 0:853a612ffb16 430 #endif
mimi3 0:853a612ffb16 431 #else
mimi3 0:853a612ffb16 432 for (uint32_t i = 0; i < length; i++) {
mimi3 0:853a612ffb16 433 _spi.write(buffer[i]);
mimi3 0:853a612ffb16 434 }
mimi3 0:853a612ffb16 435 #endif
mimi3 0:853a612ffb16 436 // write the checksum
mimi3 0:853a612ffb16 437 _spi.write(0xFF);
mimi3 0:853a612ffb16 438 _spi.write(0xFF);
mimi3 0:853a612ffb16 439
mimi3 0:853a612ffb16 440 // check the response token
mimi3 0:853a612ffb16 441 if ((_spi.write(0xFF) & 0x1F) != 0x05) {
mimi3 0:853a612ffb16 442 _cs = 1;
mimi3 0:853a612ffb16 443 _spi.write(0xFF);
mimi3 0:853a612ffb16 444 return 1;
mimi3 0:853a612ffb16 445 }
mimi3 0:853a612ffb16 446
mimi3 0:853a612ffb16 447 // wait for write to finish
mimi3 0:853a612ffb16 448 while (_spi.write(0xFF) == 0);
mimi3 0:853a612ffb16 449
mimi3 0:853a612ffb16 450 _cs = 1;
mimi3 0:853a612ffb16 451 _spi.write(0xFF);
mimi3 0:853a612ffb16 452 return 0;
mimi3 0:853a612ffb16 453 }
mimi3 0:853a612ffb16 454
mimi3 0:853a612ffb16 455 static uint32_t ext_bits(unsigned char *data, int msb, int lsb) {
mimi3 0:853a612ffb16 456 uint32_t bits = 0;
mimi3 0:853a612ffb16 457 uint32_t size = 1 + msb - lsb;
mimi3 0:853a612ffb16 458 for (uint32_t i = 0; i < size; i++) {
mimi3 0:853a612ffb16 459 uint32_t position = lsb + i;
mimi3 0:853a612ffb16 460 uint32_t byte = 15 - (position >> 3);
mimi3 0:853a612ffb16 461 uint32_t bit = position & 0x7;
mimi3 0:853a612ffb16 462 uint32_t value = (data[byte] >> bit) & 1;
mimi3 0:853a612ffb16 463 bits |= value << i;
mimi3 0:853a612ffb16 464 }
mimi3 0:853a612ffb16 465 return bits;
mimi3 0:853a612ffb16 466 }
mimi3 0:853a612ffb16 467
mimi3 0:853a612ffb16 468 uint32_t SDFileSystem::_sd_sectors() {
mimi3 0:853a612ffb16 469 uint32_t c_size, c_size_mult, read_bl_len;
mimi3 0:853a612ffb16 470 uint32_t block_len, mult, blocknr, capacity;
mimi3 0:853a612ffb16 471 uint32_t hc_c_size;
mimi3 0:853a612ffb16 472 uint32_t blocks;
mimi3 0:853a612ffb16 473
mimi3 0:853a612ffb16 474 // CMD9, Response R2 (R1 byte + 16-byte block read)
mimi3 0:853a612ffb16 475 if (_cmdx(9, 0) != 0) {
mimi3 0:853a612ffb16 476 debug("Didn't get a response from the disk\n");
mimi3 0:853a612ffb16 477 return 0;
mimi3 0:853a612ffb16 478 }
mimi3 0:853a612ffb16 479
mimi3 0:853a612ffb16 480 uint8_t csd[16];
mimi3 0:853a612ffb16 481 if (_read(csd, 16) != 0) {
mimi3 0:853a612ffb16 482 debug("Couldn't read csd response from disk\n");
mimi3 0:853a612ffb16 483 return 0;
mimi3 0:853a612ffb16 484 }
mimi3 0:853a612ffb16 485
mimi3 0:853a612ffb16 486 // csd_structure : csd[127:126]
mimi3 0:853a612ffb16 487 // c_size : csd[73:62]
mimi3 0:853a612ffb16 488 // c_size_mult : csd[49:47]
mimi3 0:853a612ffb16 489 // read_bl_len : csd[83:80] - the *maximum* read block length
mimi3 0:853a612ffb16 490
mimi3 0:853a612ffb16 491 int csd_structure = ext_bits(csd, 127, 126);
mimi3 0:853a612ffb16 492
mimi3 0:853a612ffb16 493 switch (csd_structure) {
mimi3 0:853a612ffb16 494 case 0:
mimi3 0:853a612ffb16 495 cdv = 512;
mimi3 0:853a612ffb16 496 c_size = ext_bits(csd, 73, 62);
mimi3 0:853a612ffb16 497 c_size_mult = ext_bits(csd, 49, 47);
mimi3 0:853a612ffb16 498 read_bl_len = ext_bits(csd, 83, 80);
mimi3 0:853a612ffb16 499
mimi3 0:853a612ffb16 500 block_len = 1 << read_bl_len;
mimi3 0:853a612ffb16 501 mult = 1 << (c_size_mult + 2);
mimi3 0:853a612ffb16 502 blocknr = (c_size + 1) * mult;
mimi3 0:853a612ffb16 503 capacity = blocknr * block_len;
mimi3 0:853a612ffb16 504 blocks = capacity / 512;
mimi3 0:853a612ffb16 505 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 506 break;
mimi3 0:853a612ffb16 507
mimi3 0:853a612ffb16 508 case 1:
mimi3 0:853a612ffb16 509 cdv = 1;
mimi3 0:853a612ffb16 510 hc_c_size = ext_bits(csd, 63, 48);
mimi3 0:853a612ffb16 511 blocks = (hc_c_size+1)*1024;
mimi3 0:853a612ffb16 512 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 513 break;
mimi3 0:853a612ffb16 514
mimi3 0:853a612ffb16 515 default:
mimi3 0:853a612ffb16 516 debug("CSD struct unsupported\r\n");
mimi3 0:853a612ffb16 517 return 0;
mimi3 0:853a612ffb16 518 };
mimi3 0:853a612ffb16 519 return blocks;
mimi3 0:853a612ffb16 520 }