RainbowTeam / Mbed 2 deprecated ProjectTheseus

Dependencies:   mbed

Committer:
wengefa1
Date:
Wed Jul 04 09:14:37 2018 +0000
Revision:
15:31d09ee65cf1
Parent:
6:a1fd0f1374e6
Schalter f?r Moduswechsel implementiert

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Alexander_Zuest 6:a1fd0f1374e6 1 /* SD/MMC File System Library
Alexander_Zuest 6:a1fd0f1374e6 2 * Copyright (c) 2016 Neil Thiessen
Alexander_Zuest 6:a1fd0f1374e6 3 *
Alexander_Zuest 6:a1fd0f1374e6 4 * Licensed under the Apache License, Version 2.0 (the "License");
Alexander_Zuest 6:a1fd0f1374e6 5 * you may not use this file except in compliance with the License.
Alexander_Zuest 6:a1fd0f1374e6 6 * You may obtain a copy of the License at
Alexander_Zuest 6:a1fd0f1374e6 7 *
Alexander_Zuest 6:a1fd0f1374e6 8 * http://www.apache.org/licenses/LICENSE-2.0
Alexander_Zuest 6:a1fd0f1374e6 9 *
Alexander_Zuest 6:a1fd0f1374e6 10 * Unless required by applicable law or agreed to in writing, software
Alexander_Zuest 6:a1fd0f1374e6 11 * distributed under the License is distributed on an "AS IS" BASIS,
Alexander_Zuest 6:a1fd0f1374e6 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Alexander_Zuest 6:a1fd0f1374e6 13 * See the License for the specific language governing permissions and
Alexander_Zuest 6:a1fd0f1374e6 14 * limitations under the License.
Alexander_Zuest 6:a1fd0f1374e6 15 */
Alexander_Zuest 6:a1fd0f1374e6 16
Alexander_Zuest 6:a1fd0f1374e6 17 #include "SDFileSystem.h"
Alexander_Zuest 6:a1fd0f1374e6 18 #include "diskio.h"
Alexander_Zuest 6:a1fd0f1374e6 19 #include "pinmap.h"
Alexander_Zuest 6:a1fd0f1374e6 20 #include "SDCRC.h"
Alexander_Zuest 6:a1fd0f1374e6 21
Alexander_Zuest 6:a1fd0f1374e6 22 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd, SwitchType cdtype, int hz)
Alexander_Zuest 6:a1fd0f1374e6 23 : FATFileSystem(name),
Alexander_Zuest 6:a1fd0f1374e6 24 m_Spi(mosi, miso, sclk),
Alexander_Zuest 6:a1fd0f1374e6 25 m_Cs(cs, 1),
Alexander_Zuest 6:a1fd0f1374e6 26 m_Cd(cd),
Alexander_Zuest 6:a1fd0f1374e6 27 m_FREQ(hz)
Alexander_Zuest 6:a1fd0f1374e6 28 {
Alexander_Zuest 6:a1fd0f1374e6 29 //Initialize the member variables
Alexander_Zuest 6:a1fd0f1374e6 30 m_CardType = CARD_NONE;
Alexander_Zuest 6:a1fd0f1374e6 31 m_Crc = true;
Alexander_Zuest 6:a1fd0f1374e6 32 m_LargeFrames = false;
Alexander_Zuest 6:a1fd0f1374e6 33 m_WriteValidation = true;
Alexander_Zuest 6:a1fd0f1374e6 34 m_Status = STA_NOINIT;
Alexander_Zuest 6:a1fd0f1374e6 35
Alexander_Zuest 6:a1fd0f1374e6 36 //Enable the internal pull-up resistor on MISO
Alexander_Zuest 6:a1fd0f1374e6 37 pin_mode(miso, PullUp);
Alexander_Zuest 6:a1fd0f1374e6 38
Alexander_Zuest 6:a1fd0f1374e6 39 //Configure the SPI bus
Alexander_Zuest 6:a1fd0f1374e6 40 m_Spi.format(8, 0);
Alexander_Zuest 6:a1fd0f1374e6 41
Alexander_Zuest 6:a1fd0f1374e6 42 //Configure the card detect pin
Alexander_Zuest 6:a1fd0f1374e6 43 if (cdtype == SWITCH_POS_NO) {
Alexander_Zuest 6:a1fd0f1374e6 44 m_Cd.mode(PullDown);
Alexander_Zuest 6:a1fd0f1374e6 45 m_CdAssert = 1;
Alexander_Zuest 6:a1fd0f1374e6 46 m_Cd.fall(this, &SDFileSystem::onCardRemoval);
Alexander_Zuest 6:a1fd0f1374e6 47 } else if (cdtype == SWITCH_POS_NC) {
Alexander_Zuest 6:a1fd0f1374e6 48 m_Cd.mode(PullDown);
Alexander_Zuest 6:a1fd0f1374e6 49 m_CdAssert = 0;
Alexander_Zuest 6:a1fd0f1374e6 50 m_Cd.rise(this, &SDFileSystem::onCardRemoval);
Alexander_Zuest 6:a1fd0f1374e6 51 } else if (cdtype == SWITCH_NEG_NO) {
Alexander_Zuest 6:a1fd0f1374e6 52 m_Cd.mode(PullUp);
Alexander_Zuest 6:a1fd0f1374e6 53 m_CdAssert = 0;
Alexander_Zuest 6:a1fd0f1374e6 54 m_Cd.rise(this, &SDFileSystem::onCardRemoval);
Alexander_Zuest 6:a1fd0f1374e6 55 } else if (cdtype == SWITCH_NEG_NC) {
Alexander_Zuest 6:a1fd0f1374e6 56 m_Cd.mode(PullUp);
Alexander_Zuest 6:a1fd0f1374e6 57 m_CdAssert = 1;
Alexander_Zuest 6:a1fd0f1374e6 58 m_Cd.fall(this, &SDFileSystem::onCardRemoval);
Alexander_Zuest 6:a1fd0f1374e6 59 } else {
Alexander_Zuest 6:a1fd0f1374e6 60 m_CdAssert = -1;
Alexander_Zuest 6:a1fd0f1374e6 61 }
Alexander_Zuest 6:a1fd0f1374e6 62 }
Alexander_Zuest 6:a1fd0f1374e6 63
Alexander_Zuest 6:a1fd0f1374e6 64 bool SDFileSystem::card_present()
Alexander_Zuest 6:a1fd0f1374e6 65 {
Alexander_Zuest 6:a1fd0f1374e6 66 //Check the card socket
Alexander_Zuest 6:a1fd0f1374e6 67 checkSocket();
Alexander_Zuest 6:a1fd0f1374e6 68
Alexander_Zuest 6:a1fd0f1374e6 69 //Return whether or not a card is present
Alexander_Zuest 6:a1fd0f1374e6 70 return !(m_Status & STA_NODISK);
Alexander_Zuest 6:a1fd0f1374e6 71 }
Alexander_Zuest 6:a1fd0f1374e6 72
Alexander_Zuest 6:a1fd0f1374e6 73 SDFileSystem::CardType SDFileSystem::card_type()
Alexander_Zuest 6:a1fd0f1374e6 74 {
Alexander_Zuest 6:a1fd0f1374e6 75 //Check the card socket
Alexander_Zuest 6:a1fd0f1374e6 76 checkSocket();
Alexander_Zuest 6:a1fd0f1374e6 77
Alexander_Zuest 6:a1fd0f1374e6 78 //Return the card type
Alexander_Zuest 6:a1fd0f1374e6 79 return m_CardType;
Alexander_Zuest 6:a1fd0f1374e6 80 }
Alexander_Zuest 6:a1fd0f1374e6 81
Alexander_Zuest 6:a1fd0f1374e6 82 bool SDFileSystem::crc()
Alexander_Zuest 6:a1fd0f1374e6 83 {
Alexander_Zuest 6:a1fd0f1374e6 84 //Return whether or not CRC is enabled
Alexander_Zuest 6:a1fd0f1374e6 85 return m_Crc;
Alexander_Zuest 6:a1fd0f1374e6 86 }
Alexander_Zuest 6:a1fd0f1374e6 87
Alexander_Zuest 6:a1fd0f1374e6 88 void SDFileSystem::crc(bool enabled)
Alexander_Zuest 6:a1fd0f1374e6 89 {
Alexander_Zuest 6:a1fd0f1374e6 90 //Check the card socket
Alexander_Zuest 6:a1fd0f1374e6 91 checkSocket();
Alexander_Zuest 6:a1fd0f1374e6 92
Alexander_Zuest 6:a1fd0f1374e6 93 //Just update the member variable if the card isn't initialized
Alexander_Zuest 6:a1fd0f1374e6 94 if (m_Status & STA_NOINIT) {
Alexander_Zuest 6:a1fd0f1374e6 95 m_Crc = enabled;
Alexander_Zuest 6:a1fd0f1374e6 96 return;
Alexander_Zuest 6:a1fd0f1374e6 97 }
Alexander_Zuest 6:a1fd0f1374e6 98
Alexander_Zuest 6:a1fd0f1374e6 99 //Enable or disable CRC
Alexander_Zuest 6:a1fd0f1374e6 100 if (enabled && !m_Crc) {
Alexander_Zuest 6:a1fd0f1374e6 101 //Send CMD59(0x00000001) to enable CRC
Alexander_Zuest 6:a1fd0f1374e6 102 m_Crc = true;
Alexander_Zuest 6:a1fd0f1374e6 103 commandTransaction(CMD59, 0x00000001);
Alexander_Zuest 6:a1fd0f1374e6 104 } else if (!enabled && m_Crc) {
Alexander_Zuest 6:a1fd0f1374e6 105 //Send CMD59(0x00000000) to disable CRC
Alexander_Zuest 6:a1fd0f1374e6 106 commandTransaction(CMD59, 0x00000000);
Alexander_Zuest 6:a1fd0f1374e6 107 m_Crc = false;
Alexander_Zuest 6:a1fd0f1374e6 108 }
Alexander_Zuest 6:a1fd0f1374e6 109 }
Alexander_Zuest 6:a1fd0f1374e6 110
Alexander_Zuest 6:a1fd0f1374e6 111 bool SDFileSystem::large_frames()
Alexander_Zuest 6:a1fd0f1374e6 112 {
Alexander_Zuest 6:a1fd0f1374e6 113 //Return whether or not 16-bit frames are enabled
Alexander_Zuest 6:a1fd0f1374e6 114 return m_LargeFrames;
Alexander_Zuest 6:a1fd0f1374e6 115 }
Alexander_Zuest 6:a1fd0f1374e6 116
Alexander_Zuest 6:a1fd0f1374e6 117 void SDFileSystem::large_frames(bool enabled)
Alexander_Zuest 6:a1fd0f1374e6 118 {
Alexander_Zuest 6:a1fd0f1374e6 119 //Set whether or not 16-bit frames are enabled
Alexander_Zuest 6:a1fd0f1374e6 120 m_LargeFrames = enabled;
Alexander_Zuest 6:a1fd0f1374e6 121 }
Alexander_Zuest 6:a1fd0f1374e6 122
Alexander_Zuest 6:a1fd0f1374e6 123 bool SDFileSystem::write_validation()
Alexander_Zuest 6:a1fd0f1374e6 124 {
Alexander_Zuest 6:a1fd0f1374e6 125 //Return whether or not write validation is enabled
Alexander_Zuest 6:a1fd0f1374e6 126 return m_WriteValidation;
Alexander_Zuest 6:a1fd0f1374e6 127 }
Alexander_Zuest 6:a1fd0f1374e6 128
Alexander_Zuest 6:a1fd0f1374e6 129 void SDFileSystem::write_validation(bool enabled)
Alexander_Zuest 6:a1fd0f1374e6 130 {
Alexander_Zuest 6:a1fd0f1374e6 131 //Set whether or not write validation is enabled
Alexander_Zuest 6:a1fd0f1374e6 132 m_WriteValidation = enabled;
Alexander_Zuest 6:a1fd0f1374e6 133 }
Alexander_Zuest 6:a1fd0f1374e6 134
Alexander_Zuest 6:a1fd0f1374e6 135 int SDFileSystem::unmount()
Alexander_Zuest 6:a1fd0f1374e6 136 {
Alexander_Zuest 6:a1fd0f1374e6 137 //Unmount the filesystem
Alexander_Zuest 6:a1fd0f1374e6 138 FATFileSystem::unmount();
Alexander_Zuest 6:a1fd0f1374e6 139
Alexander_Zuest 6:a1fd0f1374e6 140 //Change the status to not initialized, and the card type to unknown
Alexander_Zuest 6:a1fd0f1374e6 141 m_Status |= STA_NOINIT;
Alexander_Zuest 6:a1fd0f1374e6 142 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 143
Alexander_Zuest 6:a1fd0f1374e6 144 //Always succeeds
Alexander_Zuest 6:a1fd0f1374e6 145 return 0;
Alexander_Zuest 6:a1fd0f1374e6 146 }
Alexander_Zuest 6:a1fd0f1374e6 147
Alexander_Zuest 6:a1fd0f1374e6 148 int SDFileSystem::disk_initialize()
Alexander_Zuest 6:a1fd0f1374e6 149 {
Alexander_Zuest 6:a1fd0f1374e6 150 char token;
Alexander_Zuest 6:a1fd0f1374e6 151 unsigned int resp;
Alexander_Zuest 6:a1fd0f1374e6 152 Timer timer;
Alexander_Zuest 6:a1fd0f1374e6 153
Alexander_Zuest 6:a1fd0f1374e6 154 //Make sure there's a card in the socket before proceeding
Alexander_Zuest 6:a1fd0f1374e6 155 checkSocket();
Alexander_Zuest 6:a1fd0f1374e6 156 if (m_Status & STA_NODISK)
Alexander_Zuest 6:a1fd0f1374e6 157 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 158
Alexander_Zuest 6:a1fd0f1374e6 159 //Make sure we're not already initialized before proceeding
Alexander_Zuest 6:a1fd0f1374e6 160 if (!(m_Status & STA_NOINIT))
Alexander_Zuest 6:a1fd0f1374e6 161 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 162
Alexander_Zuest 6:a1fd0f1374e6 163 //Set the SPI frequency to 400kHz for initialization
Alexander_Zuest 6:a1fd0f1374e6 164 m_Spi.frequency(400000);
Alexander_Zuest 6:a1fd0f1374e6 165
Alexander_Zuest 6:a1fd0f1374e6 166 //Try to reset the card up to 3 times
Alexander_Zuest 6:a1fd0f1374e6 167 for (int f = 0; f < 3; f++) {
Alexander_Zuest 6:a1fd0f1374e6 168 //Send 80 dummy clocks with /CS deasserted and DI held high
Alexander_Zuest 6:a1fd0f1374e6 169 m_Cs = 1;
Alexander_Zuest 6:a1fd0f1374e6 170 for (int i = 0; i < 10; i++) {
Alexander_Zuest 6:a1fd0f1374e6 171 m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 172 }
Alexander_Zuest 6:a1fd0f1374e6 173
Alexander_Zuest 6:a1fd0f1374e6 174 //Send CMD0(0x00000000) to reset the card
Alexander_Zuest 6:a1fd0f1374e6 175 token = commandTransaction(CMD0, 0x00000000);
Alexander_Zuest 6:a1fd0f1374e6 176 if (token == 0x01) {
Alexander_Zuest 6:a1fd0f1374e6 177 break;
Alexander_Zuest 6:a1fd0f1374e6 178 }
Alexander_Zuest 6:a1fd0f1374e6 179 }
Alexander_Zuest 6:a1fd0f1374e6 180
Alexander_Zuest 6:a1fd0f1374e6 181 //Check if the card reset
Alexander_Zuest 6:a1fd0f1374e6 182 if (token != 0x01) {
Alexander_Zuest 6:a1fd0f1374e6 183 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 184 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 185 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 186 }
Alexander_Zuest 6:a1fd0f1374e6 187
Alexander_Zuest 6:a1fd0f1374e6 188 //Send CMD59(0x00000001) to enable CRC if necessary
Alexander_Zuest 6:a1fd0f1374e6 189 if (m_Crc) {
Alexander_Zuest 6:a1fd0f1374e6 190 if (commandTransaction(CMD59, 0x00000001) != 0x01) {
Alexander_Zuest 6:a1fd0f1374e6 191 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 192 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 193 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 194 }
Alexander_Zuest 6:a1fd0f1374e6 195 }
Alexander_Zuest 6:a1fd0f1374e6 196
Alexander_Zuest 6:a1fd0f1374e6 197 //Send CMD8(0x000001AA) to see if this is an SDCv2 card
Alexander_Zuest 6:a1fd0f1374e6 198 if (commandTransaction(CMD8, 0x000001AA, &resp) == 0x01) {
Alexander_Zuest 6:a1fd0f1374e6 199 //This is an SDCv2 card, get the 32-bit return value and verify the voltage range/check pattern
Alexander_Zuest 6:a1fd0f1374e6 200 if ((resp & 0xFFF) != 0x1AA) {
Alexander_Zuest 6:a1fd0f1374e6 201 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 202 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 203 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 204 }
Alexander_Zuest 6:a1fd0f1374e6 205
Alexander_Zuest 6:a1fd0f1374e6 206 //Send CMD58(0x00000000) to read the OCR, and verify that the card supports 3.2-3.3V
Alexander_Zuest 6:a1fd0f1374e6 207 if (commandTransaction(CMD58, 0x00000000, &resp) != 0x01 || !(resp & (1 << 20))) {
Alexander_Zuest 6:a1fd0f1374e6 208 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 209 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 210 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 211 }
Alexander_Zuest 6:a1fd0f1374e6 212
Alexander_Zuest 6:a1fd0f1374e6 213 //Try to initialize the card using ACMD41(0x40100000) for up to 2 seconds
Alexander_Zuest 6:a1fd0f1374e6 214 timer.start();
Alexander_Zuest 6:a1fd0f1374e6 215 do {
Alexander_Zuest 6:a1fd0f1374e6 216 token = commandTransaction(ACMD41, 0x40100000);
Alexander_Zuest 6:a1fd0f1374e6 217 } while (token == 0x01 && timer.read_ms() < 2000);
Alexander_Zuest 6:a1fd0f1374e6 218 timer.stop();
Alexander_Zuest 6:a1fd0f1374e6 219 timer.reset();
Alexander_Zuest 6:a1fd0f1374e6 220
Alexander_Zuest 6:a1fd0f1374e6 221 //Check if the card initialized
Alexander_Zuest 6:a1fd0f1374e6 222 if (token != 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 223 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 224 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 225 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 226 }
Alexander_Zuest 6:a1fd0f1374e6 227
Alexander_Zuest 6:a1fd0f1374e6 228 //Send CMD58(0x00000000) to read the OCR
Alexander_Zuest 6:a1fd0f1374e6 229 if (commandTransaction(CMD58, 0x00000000, &resp) == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 230 //Check the CCS bit to determine if this is a high capacity card
Alexander_Zuest 6:a1fd0f1374e6 231 if (resp & (1 << 30))
Alexander_Zuest 6:a1fd0f1374e6 232 m_CardType = CARD_SDHC;
Alexander_Zuest 6:a1fd0f1374e6 233 else
Alexander_Zuest 6:a1fd0f1374e6 234 m_CardType = CARD_SD;
Alexander_Zuest 6:a1fd0f1374e6 235
Alexander_Zuest 6:a1fd0f1374e6 236 //Increase the SPI frequency to full speed (up to 50MHz for SDCv2)
Alexander_Zuest 6:a1fd0f1374e6 237 if (m_FREQ > 25000000) {
Alexander_Zuest 6:a1fd0f1374e6 238 if (enableHighSpeedMode()) {
Alexander_Zuest 6:a1fd0f1374e6 239 if (m_FREQ > 50000000) {
Alexander_Zuest 6:a1fd0f1374e6 240 m_Spi.frequency(50000000);
Alexander_Zuest 6:a1fd0f1374e6 241 } else {
Alexander_Zuest 6:a1fd0f1374e6 242 m_Spi.frequency(m_FREQ);
Alexander_Zuest 6:a1fd0f1374e6 243 }
Alexander_Zuest 6:a1fd0f1374e6 244 } else {
Alexander_Zuest 6:a1fd0f1374e6 245 m_Spi.frequency(25000000);
Alexander_Zuest 6:a1fd0f1374e6 246 }
Alexander_Zuest 6:a1fd0f1374e6 247 } else {
Alexander_Zuest 6:a1fd0f1374e6 248 m_Spi.frequency(m_FREQ);
Alexander_Zuest 6:a1fd0f1374e6 249 }
Alexander_Zuest 6:a1fd0f1374e6 250 } else {
Alexander_Zuest 6:a1fd0f1374e6 251 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 252 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 253 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 254 }
Alexander_Zuest 6:a1fd0f1374e6 255 } else {
Alexander_Zuest 6:a1fd0f1374e6 256 //Didn't respond or illegal command, this is either an SDCv1 or MMC card
Alexander_Zuest 6:a1fd0f1374e6 257 //Send CMD58(0x00000000) to read the OCR, and verify that the card supports 3.2-3.3V
Alexander_Zuest 6:a1fd0f1374e6 258 if (commandTransaction(CMD58, 0x00000000, &resp) != 0x01 || !(resp & (1 << 20))) {
Alexander_Zuest 6:a1fd0f1374e6 259 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 260 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 261 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 262 }
Alexander_Zuest 6:a1fd0f1374e6 263
Alexander_Zuest 6:a1fd0f1374e6 264 //Try to initialize the card using ACMD41(0x40100000) for up to 2 seconds
Alexander_Zuest 6:a1fd0f1374e6 265 timer.start();
Alexander_Zuest 6:a1fd0f1374e6 266 do {
Alexander_Zuest 6:a1fd0f1374e6 267 token = commandTransaction(ACMD41, 0x40100000);
Alexander_Zuest 6:a1fd0f1374e6 268 } while (token == 0x01 && timer.read_ms() < 2000);
Alexander_Zuest 6:a1fd0f1374e6 269 timer.stop();
Alexander_Zuest 6:a1fd0f1374e6 270 timer.reset();
Alexander_Zuest 6:a1fd0f1374e6 271
Alexander_Zuest 6:a1fd0f1374e6 272 //Check if the card initialized
Alexander_Zuest 6:a1fd0f1374e6 273 if (token == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 274 //This is an SDCv1 standard capacity card
Alexander_Zuest 6:a1fd0f1374e6 275 m_CardType = CARD_SD;
Alexander_Zuest 6:a1fd0f1374e6 276
Alexander_Zuest 6:a1fd0f1374e6 277 //Increase the SPI frequency to full speed (up to 25MHz for SDCv1)
Alexander_Zuest 6:a1fd0f1374e6 278 if (m_FREQ > 25000000)
Alexander_Zuest 6:a1fd0f1374e6 279 m_Spi.frequency(25000000);
Alexander_Zuest 6:a1fd0f1374e6 280 else
Alexander_Zuest 6:a1fd0f1374e6 281 m_Spi.frequency(m_FREQ);
Alexander_Zuest 6:a1fd0f1374e6 282 } else {
Alexander_Zuest 6:a1fd0f1374e6 283 //Try to initialize the card using CMD1(0x00100000) for up to 2 seconds
Alexander_Zuest 6:a1fd0f1374e6 284 timer.start();
Alexander_Zuest 6:a1fd0f1374e6 285 do {
Alexander_Zuest 6:a1fd0f1374e6 286 token = commandTransaction(CMD1, 0x00100000);
Alexander_Zuest 6:a1fd0f1374e6 287 } while (token == 0x01 && timer.read_ms() < 2000);
Alexander_Zuest 6:a1fd0f1374e6 288 timer.stop();
Alexander_Zuest 6:a1fd0f1374e6 289 timer.reset();
Alexander_Zuest 6:a1fd0f1374e6 290
Alexander_Zuest 6:a1fd0f1374e6 291 //Check if the card initialized
Alexander_Zuest 6:a1fd0f1374e6 292 if (token == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 293 //This is an MMCv3 card
Alexander_Zuest 6:a1fd0f1374e6 294 m_CardType = CARD_MMC;
Alexander_Zuest 6:a1fd0f1374e6 295
Alexander_Zuest 6:a1fd0f1374e6 296 //Increase the SPI frequency to full speed (up to 20MHz for MMCv3)
Alexander_Zuest 6:a1fd0f1374e6 297 if (m_FREQ > 20000000)
Alexander_Zuest 6:a1fd0f1374e6 298 m_Spi.frequency(20000000);
Alexander_Zuest 6:a1fd0f1374e6 299 else
Alexander_Zuest 6:a1fd0f1374e6 300 m_Spi.frequency(m_FREQ);
Alexander_Zuest 6:a1fd0f1374e6 301 } else {
Alexander_Zuest 6:a1fd0f1374e6 302 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 303 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 304 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 305 }
Alexander_Zuest 6:a1fd0f1374e6 306 }
Alexander_Zuest 6:a1fd0f1374e6 307 }
Alexander_Zuest 6:a1fd0f1374e6 308
Alexander_Zuest 6:a1fd0f1374e6 309 //Send ACMD42(0x00000000) to disconnect the internal pull-up resistor on pin 1 if necessary
Alexander_Zuest 6:a1fd0f1374e6 310 if (m_CardType != CARD_MMC) {
Alexander_Zuest 6:a1fd0f1374e6 311 if (commandTransaction(ACMD42, 0x00000000) != 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 312 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 313 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 314 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 315 }
Alexander_Zuest 6:a1fd0f1374e6 316 }
Alexander_Zuest 6:a1fd0f1374e6 317
Alexander_Zuest 6:a1fd0f1374e6 318 //Send CMD16(0x00000200) to force the block size to 512B if necessary
Alexander_Zuest 6:a1fd0f1374e6 319 if (m_CardType != CARD_SDHC) {
Alexander_Zuest 6:a1fd0f1374e6 320 if (commandTransaction(CMD16, 0x00000200) != 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 321 //Initialization failed
Alexander_Zuest 6:a1fd0f1374e6 322 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 323 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 324 }
Alexander_Zuest 6:a1fd0f1374e6 325 }
Alexander_Zuest 6:a1fd0f1374e6 326
Alexander_Zuest 6:a1fd0f1374e6 327 //The card is now initialized
Alexander_Zuest 6:a1fd0f1374e6 328 m_Status &= ~STA_NOINIT;
Alexander_Zuest 6:a1fd0f1374e6 329
Alexander_Zuest 6:a1fd0f1374e6 330 //Return the disk status
Alexander_Zuest 6:a1fd0f1374e6 331 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 332 }
Alexander_Zuest 6:a1fd0f1374e6 333
Alexander_Zuest 6:a1fd0f1374e6 334 int SDFileSystem::disk_status()
Alexander_Zuest 6:a1fd0f1374e6 335 {
Alexander_Zuest 6:a1fd0f1374e6 336 //Check the card socket
Alexander_Zuest 6:a1fd0f1374e6 337 checkSocket();
Alexander_Zuest 6:a1fd0f1374e6 338
Alexander_Zuest 6:a1fd0f1374e6 339 //Return the disk status
Alexander_Zuest 6:a1fd0f1374e6 340 return m_Status;
Alexander_Zuest 6:a1fd0f1374e6 341 }
Alexander_Zuest 6:a1fd0f1374e6 342
Alexander_Zuest 6:a1fd0f1374e6 343 int SDFileSystem::disk_read(uint8_t* buffer, uint32_t sector, uint32_t count)
Alexander_Zuest 6:a1fd0f1374e6 344 {
Alexander_Zuest 6:a1fd0f1374e6 345 //Make sure the card is initialized before proceeding
Alexander_Zuest 6:a1fd0f1374e6 346 if (m_Status & STA_NOINIT)
Alexander_Zuest 6:a1fd0f1374e6 347 return RES_NOTRDY;
Alexander_Zuest 6:a1fd0f1374e6 348
Alexander_Zuest 6:a1fd0f1374e6 349 //Read a single block, or multiple blocks
Alexander_Zuest 6:a1fd0f1374e6 350 if (count > 1) {
Alexander_Zuest 6:a1fd0f1374e6 351 return readBlocks((char*)buffer, sector, count) ? RES_OK : RES_ERROR;
Alexander_Zuest 6:a1fd0f1374e6 352 } else {
Alexander_Zuest 6:a1fd0f1374e6 353 return readBlock((char*)buffer, sector) ? RES_OK : RES_ERROR;
Alexander_Zuest 6:a1fd0f1374e6 354 }
Alexander_Zuest 6:a1fd0f1374e6 355 }
Alexander_Zuest 6:a1fd0f1374e6 356
Alexander_Zuest 6:a1fd0f1374e6 357 int SDFileSystem::disk_write(const uint8_t* buffer, uint32_t sector, uint32_t count)
Alexander_Zuest 6:a1fd0f1374e6 358 {
Alexander_Zuest 6:a1fd0f1374e6 359 //Make sure the card is initialized before proceeding
Alexander_Zuest 6:a1fd0f1374e6 360 if (m_Status & STA_NOINIT)
Alexander_Zuest 6:a1fd0f1374e6 361 return RES_NOTRDY;
Alexander_Zuest 6:a1fd0f1374e6 362
Alexander_Zuest 6:a1fd0f1374e6 363 //Make sure the card isn't write protected before proceeding
Alexander_Zuest 6:a1fd0f1374e6 364 if (m_Status & STA_PROTECT)
Alexander_Zuest 6:a1fd0f1374e6 365 return RES_WRPRT;
Alexander_Zuest 6:a1fd0f1374e6 366
Alexander_Zuest 6:a1fd0f1374e6 367 //Write a single block, or multiple blocks
Alexander_Zuest 6:a1fd0f1374e6 368 if (count > 1) {
Alexander_Zuest 6:a1fd0f1374e6 369 return writeBlocks((const char*)buffer, sector, count) ? RES_OK : RES_ERROR;
Alexander_Zuest 6:a1fd0f1374e6 370 } else {
Alexander_Zuest 6:a1fd0f1374e6 371 return writeBlock((const char*)buffer, sector) ? RES_OK : RES_ERROR;
Alexander_Zuest 6:a1fd0f1374e6 372 }
Alexander_Zuest 6:a1fd0f1374e6 373 }
Alexander_Zuest 6:a1fd0f1374e6 374
Alexander_Zuest 6:a1fd0f1374e6 375 int SDFileSystem::disk_sync()
Alexander_Zuest 6:a1fd0f1374e6 376 {
Alexander_Zuest 6:a1fd0f1374e6 377 //Select the card so we're forced to wait for the end of any internal write processes
Alexander_Zuest 6:a1fd0f1374e6 378 if (select()) {
Alexander_Zuest 6:a1fd0f1374e6 379 deselect();
Alexander_Zuest 6:a1fd0f1374e6 380 return RES_OK;
Alexander_Zuest 6:a1fd0f1374e6 381 } else {
Alexander_Zuest 6:a1fd0f1374e6 382 return RES_ERROR;
Alexander_Zuest 6:a1fd0f1374e6 383 }
Alexander_Zuest 6:a1fd0f1374e6 384 }
Alexander_Zuest 6:a1fd0f1374e6 385
Alexander_Zuest 6:a1fd0f1374e6 386 uint32_t SDFileSystem::disk_sectors()
Alexander_Zuest 6:a1fd0f1374e6 387 {
Alexander_Zuest 6:a1fd0f1374e6 388 //Make sure the card is initialized before proceeding
Alexander_Zuest 6:a1fd0f1374e6 389 if (m_Status & STA_NOINIT)
Alexander_Zuest 6:a1fd0f1374e6 390 return 0;
Alexander_Zuest 6:a1fd0f1374e6 391
Alexander_Zuest 6:a1fd0f1374e6 392 //Try to read the CSD register up to 3 times
Alexander_Zuest 6:a1fd0f1374e6 393 for (int f = 0; f < 3; f++) {
Alexander_Zuest 6:a1fd0f1374e6 394 //Select the card, and wait for ready
Alexander_Zuest 6:a1fd0f1374e6 395 if(!select())
Alexander_Zuest 6:a1fd0f1374e6 396 break;
Alexander_Zuest 6:a1fd0f1374e6 397
Alexander_Zuest 6:a1fd0f1374e6 398 //Send CMD9(0x00000000) to read the CSD register
Alexander_Zuest 6:a1fd0f1374e6 399 if (writeCommand(CMD9, 0x00000000) == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 400 //Read the 16B CSD data block
Alexander_Zuest 6:a1fd0f1374e6 401 char csd[16];
Alexander_Zuest 6:a1fd0f1374e6 402 bool success = readData(csd, 16);
Alexander_Zuest 6:a1fd0f1374e6 403 deselect();
Alexander_Zuest 6:a1fd0f1374e6 404 if (success) {
Alexander_Zuest 6:a1fd0f1374e6 405 //Calculate the sector count based on the card type
Alexander_Zuest 6:a1fd0f1374e6 406 if ((csd[0] >> 6) == 0x01) {
Alexander_Zuest 6:a1fd0f1374e6 407 //Calculate the sector count for a high capacity card
Alexander_Zuest 6:a1fd0f1374e6 408 unsigned int size = (((csd[7] & 0x3F) << 16) | (csd[8] << 8) | csd[9]) + 1;
Alexander_Zuest 6:a1fd0f1374e6 409 return size << 10;
Alexander_Zuest 6:a1fd0f1374e6 410 } else {
Alexander_Zuest 6:a1fd0f1374e6 411 //Calculate the sector count for a standard capacity card
Alexander_Zuest 6:a1fd0f1374e6 412 unsigned int size = (((csd[6] & 0x03) << 10) | (csd[7] << 2) | ((csd[8] & 0xC0) >> 6)) + 1;
Alexander_Zuest 6:a1fd0f1374e6 413 size <<= ((((csd[9] & 0x03) << 1) | ((csd[10] & 0x80) >> 7)) + 2);
Alexander_Zuest 6:a1fd0f1374e6 414 size <<= (csd[5] & 0x0F);
Alexander_Zuest 6:a1fd0f1374e6 415 return size >> 9;
Alexander_Zuest 6:a1fd0f1374e6 416 }
Alexander_Zuest 6:a1fd0f1374e6 417 }
Alexander_Zuest 6:a1fd0f1374e6 418 } else {
Alexander_Zuest 6:a1fd0f1374e6 419 //The command failed, get out
Alexander_Zuest 6:a1fd0f1374e6 420 break;
Alexander_Zuest 6:a1fd0f1374e6 421 }
Alexander_Zuest 6:a1fd0f1374e6 422 }
Alexander_Zuest 6:a1fd0f1374e6 423
Alexander_Zuest 6:a1fd0f1374e6 424 //The read operation failed 3 times
Alexander_Zuest 6:a1fd0f1374e6 425 deselect();
Alexander_Zuest 6:a1fd0f1374e6 426 return 0;
Alexander_Zuest 6:a1fd0f1374e6 427 }
Alexander_Zuest 6:a1fd0f1374e6 428
Alexander_Zuest 6:a1fd0f1374e6 429 void SDFileSystem::onCardRemoval()
Alexander_Zuest 6:a1fd0f1374e6 430 {
Alexander_Zuest 6:a1fd0f1374e6 431 //Check the card socket
Alexander_Zuest 6:a1fd0f1374e6 432 checkSocket();
Alexander_Zuest 6:a1fd0f1374e6 433 }
Alexander_Zuest 6:a1fd0f1374e6 434
Alexander_Zuest 6:a1fd0f1374e6 435 inline void SDFileSystem::checkSocket()
Alexander_Zuest 6:a1fd0f1374e6 436 {
Alexander_Zuest 6:a1fd0f1374e6 437 //Use the card detect switch (if available) to determine if the socket is occupied
Alexander_Zuest 6:a1fd0f1374e6 438 if (m_CdAssert != -1) {
Alexander_Zuest 6:a1fd0f1374e6 439 if (m_Status & STA_NODISK) {
Alexander_Zuest 6:a1fd0f1374e6 440 if (m_Cd == m_CdAssert) {
Alexander_Zuest 6:a1fd0f1374e6 441 //The socket is now occupied
Alexander_Zuest 6:a1fd0f1374e6 442 m_Status &= ~STA_NODISK;
Alexander_Zuest 6:a1fd0f1374e6 443 m_CardType = CARD_UNKNOWN;
Alexander_Zuest 6:a1fd0f1374e6 444 }
Alexander_Zuest 6:a1fd0f1374e6 445 } else {
Alexander_Zuest 6:a1fd0f1374e6 446 if (m_Cd != m_CdAssert) {
Alexander_Zuest 6:a1fd0f1374e6 447 //The socket is now empty
Alexander_Zuest 6:a1fd0f1374e6 448 m_Status |= (STA_NODISK | STA_NOINIT);
Alexander_Zuest 6:a1fd0f1374e6 449 m_CardType = CARD_NONE;
Alexander_Zuest 6:a1fd0f1374e6 450 }
Alexander_Zuest 6:a1fd0f1374e6 451 }
Alexander_Zuest 6:a1fd0f1374e6 452 }
Alexander_Zuest 6:a1fd0f1374e6 453 }
Alexander_Zuest 6:a1fd0f1374e6 454
Alexander_Zuest 6:a1fd0f1374e6 455 inline bool SDFileSystem::waitReady(int timeout)
Alexander_Zuest 6:a1fd0f1374e6 456 {
Alexander_Zuest 6:a1fd0f1374e6 457 char resp;
Alexander_Zuest 6:a1fd0f1374e6 458
Alexander_Zuest 6:a1fd0f1374e6 459 //Keep sending dummy clocks with DI held high until the card releases the DO line
Alexander_Zuest 6:a1fd0f1374e6 460 m_Timer.start();
Alexander_Zuest 6:a1fd0f1374e6 461 do {
Alexander_Zuest 6:a1fd0f1374e6 462 resp = m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 463 } while (resp == 0x00 && m_Timer.read_ms() < timeout);
Alexander_Zuest 6:a1fd0f1374e6 464 m_Timer.stop();
Alexander_Zuest 6:a1fd0f1374e6 465 m_Timer.reset();
Alexander_Zuest 6:a1fd0f1374e6 466
Alexander_Zuest 6:a1fd0f1374e6 467 //Return success/failure
Alexander_Zuest 6:a1fd0f1374e6 468 return (resp > 0x00);
Alexander_Zuest 6:a1fd0f1374e6 469 }
Alexander_Zuest 6:a1fd0f1374e6 470
Alexander_Zuest 6:a1fd0f1374e6 471 inline bool SDFileSystem::select()
Alexander_Zuest 6:a1fd0f1374e6 472 {
Alexander_Zuest 6:a1fd0f1374e6 473 //Assert /CS
Alexander_Zuest 6:a1fd0f1374e6 474 m_Cs = 0;
Alexander_Zuest 6:a1fd0f1374e6 475
Alexander_Zuest 6:a1fd0f1374e6 476 //Send 8 dummy clocks with DI held high to enable DO
Alexander_Zuest 6:a1fd0f1374e6 477 m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 478
Alexander_Zuest 6:a1fd0f1374e6 479 //Wait for up to 500ms for the card to become ready
Alexander_Zuest 6:a1fd0f1374e6 480 if (waitReady(500)) {
Alexander_Zuest 6:a1fd0f1374e6 481 return true;
Alexander_Zuest 6:a1fd0f1374e6 482 } else {
Alexander_Zuest 6:a1fd0f1374e6 483 //We timed out, deselect and return false
Alexander_Zuest 6:a1fd0f1374e6 484 deselect();
Alexander_Zuest 6:a1fd0f1374e6 485 return false;
Alexander_Zuest 6:a1fd0f1374e6 486 }
Alexander_Zuest 6:a1fd0f1374e6 487 }
Alexander_Zuest 6:a1fd0f1374e6 488
Alexander_Zuest 6:a1fd0f1374e6 489 inline void SDFileSystem::deselect()
Alexander_Zuest 6:a1fd0f1374e6 490 {
Alexander_Zuest 6:a1fd0f1374e6 491 //Deassert /CS
Alexander_Zuest 6:a1fd0f1374e6 492 m_Cs = 1;
Alexander_Zuest 6:a1fd0f1374e6 493
Alexander_Zuest 6:a1fd0f1374e6 494 //Send 8 dummy clocks with DI held high to disable DO
Alexander_Zuest 6:a1fd0f1374e6 495 m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 496 }
Alexander_Zuest 6:a1fd0f1374e6 497
Alexander_Zuest 6:a1fd0f1374e6 498 inline char SDFileSystem::commandTransaction(char cmd, unsigned int arg, unsigned int* resp)
Alexander_Zuest 6:a1fd0f1374e6 499 {
Alexander_Zuest 6:a1fd0f1374e6 500 //Select the card, and wait for ready
Alexander_Zuest 6:a1fd0f1374e6 501 if(!select())
Alexander_Zuest 6:a1fd0f1374e6 502 return 0xFF;
Alexander_Zuest 6:a1fd0f1374e6 503
Alexander_Zuest 6:a1fd0f1374e6 504 //Perform the command transaction
Alexander_Zuest 6:a1fd0f1374e6 505 char token = writeCommand(cmd, arg, resp);
Alexander_Zuest 6:a1fd0f1374e6 506
Alexander_Zuest 6:a1fd0f1374e6 507 //Deselect the card, and return the R1 response token
Alexander_Zuest 6:a1fd0f1374e6 508 deselect();
Alexander_Zuest 6:a1fd0f1374e6 509 return token;
Alexander_Zuest 6:a1fd0f1374e6 510 }
Alexander_Zuest 6:a1fd0f1374e6 511
Alexander_Zuest 6:a1fd0f1374e6 512 char SDFileSystem::writeCommand(char cmd, unsigned int arg, unsigned int* resp)
Alexander_Zuest 6:a1fd0f1374e6 513 {
Alexander_Zuest 6:a1fd0f1374e6 514 char token;
Alexander_Zuest 6:a1fd0f1374e6 515
Alexander_Zuest 6:a1fd0f1374e6 516 //Try to send the command up to 3 times
Alexander_Zuest 6:a1fd0f1374e6 517 for (int f = 0; f < 3; f++) {
Alexander_Zuest 6:a1fd0f1374e6 518 //Send CMD55(0x00000000) prior to an application specific command
Alexander_Zuest 6:a1fd0f1374e6 519 if (cmd == ACMD22 || cmd == ACMD23 || cmd == ACMD41 || cmd == ACMD42) {
Alexander_Zuest 6:a1fd0f1374e6 520 token = writeCommand(CMD55, 0x00000000);
Alexander_Zuest 6:a1fd0f1374e6 521 if (token > 0x01)
Alexander_Zuest 6:a1fd0f1374e6 522 return token;
Alexander_Zuest 6:a1fd0f1374e6 523
Alexander_Zuest 6:a1fd0f1374e6 524 //Deselect and reselect the card between CMD55 and an ACMD
Alexander_Zuest 6:a1fd0f1374e6 525 deselect();
Alexander_Zuest 6:a1fd0f1374e6 526 if(!select())
Alexander_Zuest 6:a1fd0f1374e6 527 return 0xFF;
Alexander_Zuest 6:a1fd0f1374e6 528 }
Alexander_Zuest 6:a1fd0f1374e6 529
Alexander_Zuest 6:a1fd0f1374e6 530 //Prepare the command packet
Alexander_Zuest 6:a1fd0f1374e6 531 char cmdPacket[6];
Alexander_Zuest 6:a1fd0f1374e6 532 cmdPacket[0] = cmd;
Alexander_Zuest 6:a1fd0f1374e6 533 cmdPacket[1] = arg >> 24;
Alexander_Zuest 6:a1fd0f1374e6 534 cmdPacket[2] = arg >> 16;
Alexander_Zuest 6:a1fd0f1374e6 535 cmdPacket[3] = arg >> 8;
Alexander_Zuest 6:a1fd0f1374e6 536 cmdPacket[4] = arg;
Alexander_Zuest 6:a1fd0f1374e6 537 if (m_Crc || cmd == CMD0 || cmd == CMD8)
Alexander_Zuest 6:a1fd0f1374e6 538 cmdPacket[5] = (SDCRC::crc7(cmdPacket, 5) << 1) | 0x01;
Alexander_Zuest 6:a1fd0f1374e6 539 else
Alexander_Zuest 6:a1fd0f1374e6 540 cmdPacket[5] = 0x01;
Alexander_Zuest 6:a1fd0f1374e6 541
Alexander_Zuest 6:a1fd0f1374e6 542 //Send the command packet
Alexander_Zuest 6:a1fd0f1374e6 543 for (int i = 0; i < 6; i++)
Alexander_Zuest 6:a1fd0f1374e6 544 m_Spi.write(cmdPacket[i]);
Alexander_Zuest 6:a1fd0f1374e6 545
Alexander_Zuest 6:a1fd0f1374e6 546 //Discard the stuff byte immediately following CMD12
Alexander_Zuest 6:a1fd0f1374e6 547 if (cmd == CMD12)
Alexander_Zuest 6:a1fd0f1374e6 548 m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 549
Alexander_Zuest 6:a1fd0f1374e6 550 //Allow up to 8 bytes of delay for the R1 response token
Alexander_Zuest 6:a1fd0f1374e6 551 for (int i = 0; i < 9; i++) {
Alexander_Zuest 6:a1fd0f1374e6 552 token = m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 553 if (!(token & 0x80))
Alexander_Zuest 6:a1fd0f1374e6 554 break;
Alexander_Zuest 6:a1fd0f1374e6 555 }
Alexander_Zuest 6:a1fd0f1374e6 556
Alexander_Zuest 6:a1fd0f1374e6 557 //Verify the R1 response token
Alexander_Zuest 6:a1fd0f1374e6 558 if (token == 0xFF) {
Alexander_Zuest 6:a1fd0f1374e6 559 //No data was received, get out early
Alexander_Zuest 6:a1fd0f1374e6 560 break;
Alexander_Zuest 6:a1fd0f1374e6 561 } else if (token & (1 << 3)) {
Alexander_Zuest 6:a1fd0f1374e6 562 //There was a CRC error, try again
Alexander_Zuest 6:a1fd0f1374e6 563 continue;
Alexander_Zuest 6:a1fd0f1374e6 564 } else if (token > 0x01) {
Alexander_Zuest 6:a1fd0f1374e6 565 //An error occured, get out early
Alexander_Zuest 6:a1fd0f1374e6 566 break;
Alexander_Zuest 6:a1fd0f1374e6 567 }
Alexander_Zuest 6:a1fd0f1374e6 568
Alexander_Zuest 6:a1fd0f1374e6 569 //Handle R2 and R3/R7 response tokens
Alexander_Zuest 6:a1fd0f1374e6 570 if (cmd == CMD13 && resp != NULL) {
Alexander_Zuest 6:a1fd0f1374e6 571 //Read the R2 response value
Alexander_Zuest 6:a1fd0f1374e6 572 *resp = m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 573 } else if ((cmd == CMD8 || cmd == CMD58) && resp != NULL) {
Alexander_Zuest 6:a1fd0f1374e6 574 //Read the R3/R7 response value
Alexander_Zuest 6:a1fd0f1374e6 575 *resp = (m_Spi.write(0xFF) << 24);
Alexander_Zuest 6:a1fd0f1374e6 576 *resp |= (m_Spi.write(0xFF) << 16);
Alexander_Zuest 6:a1fd0f1374e6 577 *resp |= (m_Spi.write(0xFF) << 8);
Alexander_Zuest 6:a1fd0f1374e6 578 *resp |= m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 579 }
Alexander_Zuest 6:a1fd0f1374e6 580
Alexander_Zuest 6:a1fd0f1374e6 581 //The command was successful
Alexander_Zuest 6:a1fd0f1374e6 582 break;
Alexander_Zuest 6:a1fd0f1374e6 583 }
Alexander_Zuest 6:a1fd0f1374e6 584
Alexander_Zuest 6:a1fd0f1374e6 585 //Return the R1 response token
Alexander_Zuest 6:a1fd0f1374e6 586 return token;
Alexander_Zuest 6:a1fd0f1374e6 587 }
Alexander_Zuest 6:a1fd0f1374e6 588
Alexander_Zuest 6:a1fd0f1374e6 589 bool SDFileSystem::readData(char* buffer, int length)
Alexander_Zuest 6:a1fd0f1374e6 590 {
Alexander_Zuest 6:a1fd0f1374e6 591 char token;
Alexander_Zuest 6:a1fd0f1374e6 592 unsigned short crc;
Alexander_Zuest 6:a1fd0f1374e6 593
Alexander_Zuest 6:a1fd0f1374e6 594 //Wait for up to 500ms for a token to arrive
Alexander_Zuest 6:a1fd0f1374e6 595 m_Timer.start();
Alexander_Zuest 6:a1fd0f1374e6 596 do {
Alexander_Zuest 6:a1fd0f1374e6 597 token = m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 598 } while (token == 0xFF && m_Timer.read_ms() < 500);
Alexander_Zuest 6:a1fd0f1374e6 599 m_Timer.stop();
Alexander_Zuest 6:a1fd0f1374e6 600 m_Timer.reset();
Alexander_Zuest 6:a1fd0f1374e6 601
Alexander_Zuest 6:a1fd0f1374e6 602 //Check if a valid start block token was received
Alexander_Zuest 6:a1fd0f1374e6 603 if (token != 0xFE)
Alexander_Zuest 6:a1fd0f1374e6 604 return false;
Alexander_Zuest 6:a1fd0f1374e6 605
Alexander_Zuest 6:a1fd0f1374e6 606 //Check if large frames are enabled or not
Alexander_Zuest 6:a1fd0f1374e6 607 if (m_LargeFrames) {
Alexander_Zuest 6:a1fd0f1374e6 608 //Switch to 16-bit frames for better performance
Alexander_Zuest 6:a1fd0f1374e6 609 m_Spi.format(16, 0);
Alexander_Zuest 6:a1fd0f1374e6 610
Alexander_Zuest 6:a1fd0f1374e6 611 //Read the data block into the buffer
Alexander_Zuest 6:a1fd0f1374e6 612 unsigned short dataWord;
Alexander_Zuest 6:a1fd0f1374e6 613 for (int i = 0; i < length; i += 2) {
Alexander_Zuest 6:a1fd0f1374e6 614 dataWord = m_Spi.write(0xFFFF);
Alexander_Zuest 6:a1fd0f1374e6 615 buffer[i] = dataWord >> 8;
Alexander_Zuest 6:a1fd0f1374e6 616 buffer[i + 1] = dataWord;
Alexander_Zuest 6:a1fd0f1374e6 617 }
Alexander_Zuest 6:a1fd0f1374e6 618
Alexander_Zuest 6:a1fd0f1374e6 619 //Read the CRC16 checksum for the data block
Alexander_Zuest 6:a1fd0f1374e6 620 crc = m_Spi.write(0xFFFF);
Alexander_Zuest 6:a1fd0f1374e6 621
Alexander_Zuest 6:a1fd0f1374e6 622 //Switch back to 8-bit frames
Alexander_Zuest 6:a1fd0f1374e6 623 m_Spi.format(8, 0);
Alexander_Zuest 6:a1fd0f1374e6 624 } else {
Alexander_Zuest 6:a1fd0f1374e6 625 //Read the data into the buffer
Alexander_Zuest 6:a1fd0f1374e6 626 for (int i = 0; i < length; i++)
Alexander_Zuest 6:a1fd0f1374e6 627 buffer[i] = m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 628
Alexander_Zuest 6:a1fd0f1374e6 629 //Read the CRC16 checksum for the data block
Alexander_Zuest 6:a1fd0f1374e6 630 crc = (m_Spi.write(0xFF) << 8);
Alexander_Zuest 6:a1fd0f1374e6 631 crc |= m_Spi.write(0xFF);
Alexander_Zuest 6:a1fd0f1374e6 632 }
Alexander_Zuest 6:a1fd0f1374e6 633
Alexander_Zuest 6:a1fd0f1374e6 634 //Return the validity of the CRC16 checksum (if enabled)
Alexander_Zuest 6:a1fd0f1374e6 635 return (!m_Crc || crc == SDCRC::crc16(buffer, length));
Alexander_Zuest 6:a1fd0f1374e6 636 }
Alexander_Zuest 6:a1fd0f1374e6 637
Alexander_Zuest 6:a1fd0f1374e6 638 char SDFileSystem::writeData(const char* buffer, char token)
Alexander_Zuest 6:a1fd0f1374e6 639 {
Alexander_Zuest 6:a1fd0f1374e6 640 //Calculate the CRC16 checksum for the data block (if enabled)
Alexander_Zuest 6:a1fd0f1374e6 641 unsigned short crc = (m_Crc) ? SDCRC::crc16(buffer, 512) : 0xFFFF;
Alexander_Zuest 6:a1fd0f1374e6 642
Alexander_Zuest 6:a1fd0f1374e6 643 //Wait for up to 500ms for the card to become ready
Alexander_Zuest 6:a1fd0f1374e6 644 if (!waitReady(500))
Alexander_Zuest 6:a1fd0f1374e6 645 return false;
Alexander_Zuest 6:a1fd0f1374e6 646
Alexander_Zuest 6:a1fd0f1374e6 647 //Send the start block token
Alexander_Zuest 6:a1fd0f1374e6 648 m_Spi.write(token);
Alexander_Zuest 6:a1fd0f1374e6 649
Alexander_Zuest 6:a1fd0f1374e6 650 //Check if large frames are enabled or not
Alexander_Zuest 6:a1fd0f1374e6 651 if (m_LargeFrames) {
Alexander_Zuest 6:a1fd0f1374e6 652 //Switch to 16-bit frames for better performance
Alexander_Zuest 6:a1fd0f1374e6 653 m_Spi.format(16, 0);
Alexander_Zuest 6:a1fd0f1374e6 654
Alexander_Zuest 6:a1fd0f1374e6 655 //Write the data block from the buffer
Alexander_Zuest 6:a1fd0f1374e6 656 for (int i = 0; i < 512; i += 2)
Alexander_Zuest 6:a1fd0f1374e6 657 m_Spi.write((buffer[i] << 8) | buffer[i + 1]);
Alexander_Zuest 6:a1fd0f1374e6 658
Alexander_Zuest 6:a1fd0f1374e6 659 //Send the CRC16 checksum for the data block
Alexander_Zuest 6:a1fd0f1374e6 660 m_Spi.write(crc);
Alexander_Zuest 6:a1fd0f1374e6 661
Alexander_Zuest 6:a1fd0f1374e6 662 //Switch back to 8-bit frames
Alexander_Zuest 6:a1fd0f1374e6 663 m_Spi.format(8, 0);
Alexander_Zuest 6:a1fd0f1374e6 664 } else {
Alexander_Zuest 6:a1fd0f1374e6 665 //Write the data block from the buffer
Alexander_Zuest 6:a1fd0f1374e6 666 for (int i = 0; i < 512; i++)
Alexander_Zuest 6:a1fd0f1374e6 667 m_Spi.write(buffer[i]);
Alexander_Zuest 6:a1fd0f1374e6 668
Alexander_Zuest 6:a1fd0f1374e6 669 //Send the CRC16 checksum for the data block
Alexander_Zuest 6:a1fd0f1374e6 670 m_Spi.write(crc >> 8);
Alexander_Zuest 6:a1fd0f1374e6 671 m_Spi.write(crc);
Alexander_Zuest 6:a1fd0f1374e6 672 }
Alexander_Zuest 6:a1fd0f1374e6 673
Alexander_Zuest 6:a1fd0f1374e6 674 //Return the data response token
Alexander_Zuest 6:a1fd0f1374e6 675 return (m_Spi.write(0xFF) & 0x1F);
Alexander_Zuest 6:a1fd0f1374e6 676 }
Alexander_Zuest 6:a1fd0f1374e6 677
Alexander_Zuest 6:a1fd0f1374e6 678 inline bool SDFileSystem::readBlock(char* buffer, unsigned int lba)
Alexander_Zuest 6:a1fd0f1374e6 679 {
Alexander_Zuest 6:a1fd0f1374e6 680 //Try to read the block up to 3 times
Alexander_Zuest 6:a1fd0f1374e6 681 for (int f = 0; f < 3; f++) {
Alexander_Zuest 6:a1fd0f1374e6 682 //Select the card, and wait for ready
Alexander_Zuest 6:a1fd0f1374e6 683 if(!select())
Alexander_Zuest 6:a1fd0f1374e6 684 break;
Alexander_Zuest 6:a1fd0f1374e6 685
Alexander_Zuest 6:a1fd0f1374e6 686 //Send CMD17(block) to read a single block
Alexander_Zuest 6:a1fd0f1374e6 687 if (writeCommand(CMD17, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 688 //Try to read the block, and deselect the card
Alexander_Zuest 6:a1fd0f1374e6 689 bool success = readData(buffer, 512);
Alexander_Zuest 6:a1fd0f1374e6 690 deselect();
Alexander_Zuest 6:a1fd0f1374e6 691
Alexander_Zuest 6:a1fd0f1374e6 692 //Return if successful
Alexander_Zuest 6:a1fd0f1374e6 693 if (success)
Alexander_Zuest 6:a1fd0f1374e6 694 return true;
Alexander_Zuest 6:a1fd0f1374e6 695 } else {
Alexander_Zuest 6:a1fd0f1374e6 696 //The command failed, get out
Alexander_Zuest 6:a1fd0f1374e6 697 break;
Alexander_Zuest 6:a1fd0f1374e6 698 }
Alexander_Zuest 6:a1fd0f1374e6 699 }
Alexander_Zuest 6:a1fd0f1374e6 700
Alexander_Zuest 6:a1fd0f1374e6 701 //The single block read failed
Alexander_Zuest 6:a1fd0f1374e6 702 deselect();
Alexander_Zuest 6:a1fd0f1374e6 703 return false;
Alexander_Zuest 6:a1fd0f1374e6 704 }
Alexander_Zuest 6:a1fd0f1374e6 705
Alexander_Zuest 6:a1fd0f1374e6 706 inline bool SDFileSystem::readBlocks(char* buffer, unsigned int lba, unsigned int count)
Alexander_Zuest 6:a1fd0f1374e6 707 {
Alexander_Zuest 6:a1fd0f1374e6 708 //Try to read each block up to 3 times
Alexander_Zuest 6:a1fd0f1374e6 709 for (int f = 0; f < 3;) {
Alexander_Zuest 6:a1fd0f1374e6 710 //Select the card, and wait for ready
Alexander_Zuest 6:a1fd0f1374e6 711 if(!select())
Alexander_Zuest 6:a1fd0f1374e6 712 break;
Alexander_Zuest 6:a1fd0f1374e6 713
Alexander_Zuest 6:a1fd0f1374e6 714 //Send CMD18(block) to read multiple blocks
Alexander_Zuest 6:a1fd0f1374e6 715 if (writeCommand(CMD18, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 716 //Try to read all of the data blocks
Alexander_Zuest 6:a1fd0f1374e6 717 do {
Alexander_Zuest 6:a1fd0f1374e6 718 //Read the next block, and break on errors
Alexander_Zuest 6:a1fd0f1374e6 719 if (!readData(buffer, 512)) {
Alexander_Zuest 6:a1fd0f1374e6 720 f++;
Alexander_Zuest 6:a1fd0f1374e6 721 break;
Alexander_Zuest 6:a1fd0f1374e6 722 }
Alexander_Zuest 6:a1fd0f1374e6 723
Alexander_Zuest 6:a1fd0f1374e6 724 //Update the variables
Alexander_Zuest 6:a1fd0f1374e6 725 lba++;
Alexander_Zuest 6:a1fd0f1374e6 726 buffer += 512;
Alexander_Zuest 6:a1fd0f1374e6 727 f = 0;
Alexander_Zuest 6:a1fd0f1374e6 728 } while (--count);
Alexander_Zuest 6:a1fd0f1374e6 729
Alexander_Zuest 6:a1fd0f1374e6 730 //Send CMD12(0x00000000) to stop the transmission
Alexander_Zuest 6:a1fd0f1374e6 731 if (writeCommand(CMD12, 0x00000000) != 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 732 //The command failed, get out
Alexander_Zuest 6:a1fd0f1374e6 733 break;
Alexander_Zuest 6:a1fd0f1374e6 734 }
Alexander_Zuest 6:a1fd0f1374e6 735
Alexander_Zuest 6:a1fd0f1374e6 736 //Deselect the card, and return if successful
Alexander_Zuest 6:a1fd0f1374e6 737 deselect();
Alexander_Zuest 6:a1fd0f1374e6 738 if (count == 0)
Alexander_Zuest 6:a1fd0f1374e6 739 return true;
Alexander_Zuest 6:a1fd0f1374e6 740 } else {
Alexander_Zuest 6:a1fd0f1374e6 741 //The command failed, get out
Alexander_Zuest 6:a1fd0f1374e6 742 break;
Alexander_Zuest 6:a1fd0f1374e6 743 }
Alexander_Zuest 6:a1fd0f1374e6 744 }
Alexander_Zuest 6:a1fd0f1374e6 745
Alexander_Zuest 6:a1fd0f1374e6 746 //The multiple block read failed
Alexander_Zuest 6:a1fd0f1374e6 747 deselect();
Alexander_Zuest 6:a1fd0f1374e6 748 return false;
Alexander_Zuest 6:a1fd0f1374e6 749 }
Alexander_Zuest 6:a1fd0f1374e6 750
Alexander_Zuest 6:a1fd0f1374e6 751 inline bool SDFileSystem::writeBlock(const char* buffer, unsigned int lba)
Alexander_Zuest 6:a1fd0f1374e6 752 {
Alexander_Zuest 6:a1fd0f1374e6 753 //Try to write the block up to 3 times
Alexander_Zuest 6:a1fd0f1374e6 754 for (int f = 0; f < 3; f++) {
Alexander_Zuest 6:a1fd0f1374e6 755 //Select the card, and wait for ready
Alexander_Zuest 6:a1fd0f1374e6 756 if(!select())
Alexander_Zuest 6:a1fd0f1374e6 757 break;
Alexander_Zuest 6:a1fd0f1374e6 758
Alexander_Zuest 6:a1fd0f1374e6 759 //Send CMD24(block) to write a single block
Alexander_Zuest 6:a1fd0f1374e6 760 if (writeCommand(CMD24, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 761 //Try to write the block, and deselect the card
Alexander_Zuest 6:a1fd0f1374e6 762 char token = writeData(buffer, 0xFE);
Alexander_Zuest 6:a1fd0f1374e6 763 deselect();
Alexander_Zuest 6:a1fd0f1374e6 764
Alexander_Zuest 6:a1fd0f1374e6 765 //Check the data response token
Alexander_Zuest 6:a1fd0f1374e6 766 if (token == 0x0A) {
Alexander_Zuest 6:a1fd0f1374e6 767 //A CRC error occured, try again
Alexander_Zuest 6:a1fd0f1374e6 768 continue;
Alexander_Zuest 6:a1fd0f1374e6 769 } else if (token == 0x0C) {
Alexander_Zuest 6:a1fd0f1374e6 770 //A write error occured, get out
Alexander_Zuest 6:a1fd0f1374e6 771 break;
Alexander_Zuest 6:a1fd0f1374e6 772 }
Alexander_Zuest 6:a1fd0f1374e6 773
Alexander_Zuest 6:a1fd0f1374e6 774 //Send CMD13(0x00000000) to verify that the programming was successful if enabled
Alexander_Zuest 6:a1fd0f1374e6 775 if (m_WriteValidation) {
Alexander_Zuest 6:a1fd0f1374e6 776 unsigned int resp;
Alexander_Zuest 6:a1fd0f1374e6 777 if (commandTransaction(CMD13, 0x00000000, &resp) != 0x00 || resp != 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 778 //Some manner of unrecoverable write error occured during programming, get out
Alexander_Zuest 6:a1fd0f1374e6 779 break;
Alexander_Zuest 6:a1fd0f1374e6 780 }
Alexander_Zuest 6:a1fd0f1374e6 781 }
Alexander_Zuest 6:a1fd0f1374e6 782
Alexander_Zuest 6:a1fd0f1374e6 783 //The data was written successfully
Alexander_Zuest 6:a1fd0f1374e6 784 return true;
Alexander_Zuest 6:a1fd0f1374e6 785 } else {
Alexander_Zuest 6:a1fd0f1374e6 786 //The command failed, get out
Alexander_Zuest 6:a1fd0f1374e6 787 break;
Alexander_Zuest 6:a1fd0f1374e6 788 }
Alexander_Zuest 6:a1fd0f1374e6 789 }
Alexander_Zuest 6:a1fd0f1374e6 790
Alexander_Zuest 6:a1fd0f1374e6 791 //The single block write failed
Alexander_Zuest 6:a1fd0f1374e6 792 deselect();
Alexander_Zuest 6:a1fd0f1374e6 793 return false;
Alexander_Zuest 6:a1fd0f1374e6 794 }
Alexander_Zuest 6:a1fd0f1374e6 795
Alexander_Zuest 6:a1fd0f1374e6 796 inline bool SDFileSystem::writeBlocks(const char* buffer, unsigned int lba, unsigned int count)
Alexander_Zuest 6:a1fd0f1374e6 797 {
Alexander_Zuest 6:a1fd0f1374e6 798 char token;
Alexander_Zuest 6:a1fd0f1374e6 799 const char* currentBuffer = buffer;
Alexander_Zuest 6:a1fd0f1374e6 800 unsigned int currentLba = lba;
Alexander_Zuest 6:a1fd0f1374e6 801 int currentCount = count;
Alexander_Zuest 6:a1fd0f1374e6 802
Alexander_Zuest 6:a1fd0f1374e6 803 //Try to write each block up to 3 times
Alexander_Zuest 6:a1fd0f1374e6 804 for (int f = 0; f < 3;) {
Alexander_Zuest 6:a1fd0f1374e6 805 //If this is an SD card, send ACMD23(count) to set the number of blocks to pre-erase
Alexander_Zuest 6:a1fd0f1374e6 806 if (m_CardType != CARD_MMC) {
Alexander_Zuest 6:a1fd0f1374e6 807 if (commandTransaction(ACMD23, currentCount) != 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 808 //The command failed, get out
Alexander_Zuest 6:a1fd0f1374e6 809 break;
Alexander_Zuest 6:a1fd0f1374e6 810 }
Alexander_Zuest 6:a1fd0f1374e6 811 }
Alexander_Zuest 6:a1fd0f1374e6 812
Alexander_Zuest 6:a1fd0f1374e6 813 //Select the card, and wait for ready
Alexander_Zuest 6:a1fd0f1374e6 814 if(!select())
Alexander_Zuest 6:a1fd0f1374e6 815 break;
Alexander_Zuest 6:a1fd0f1374e6 816
Alexander_Zuest 6:a1fd0f1374e6 817 //Send CMD25(block) to write multiple blocks
Alexander_Zuest 6:a1fd0f1374e6 818 if (writeCommand(CMD25, (m_CardType == CARD_SDHC) ? currentLba : currentLba << 9) == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 819 //Try to write all of the data blocks
Alexander_Zuest 6:a1fd0f1374e6 820 do {
Alexander_Zuest 6:a1fd0f1374e6 821 //Write the next block and break on errors
Alexander_Zuest 6:a1fd0f1374e6 822 token = writeData(currentBuffer, 0xFC);
Alexander_Zuest 6:a1fd0f1374e6 823 if (token != 0x05) {
Alexander_Zuest 6:a1fd0f1374e6 824 f++;
Alexander_Zuest 6:a1fd0f1374e6 825 break;
Alexander_Zuest 6:a1fd0f1374e6 826 }
Alexander_Zuest 6:a1fd0f1374e6 827
Alexander_Zuest 6:a1fd0f1374e6 828 //Update the variables
Alexander_Zuest 6:a1fd0f1374e6 829 currentBuffer += 512;
Alexander_Zuest 6:a1fd0f1374e6 830 f = 0;
Alexander_Zuest 6:a1fd0f1374e6 831 } while (--currentCount);
Alexander_Zuest 6:a1fd0f1374e6 832
Alexander_Zuest 6:a1fd0f1374e6 833 //Wait for up to 500ms for the card to finish processing the last block
Alexander_Zuest 6:a1fd0f1374e6 834 if (!waitReady(500))
Alexander_Zuest 6:a1fd0f1374e6 835 break;
Alexander_Zuest 6:a1fd0f1374e6 836
Alexander_Zuest 6:a1fd0f1374e6 837 //Finalize the transmission
Alexander_Zuest 6:a1fd0f1374e6 838 if (currentCount == 0) {
Alexander_Zuest 6:a1fd0f1374e6 839 //Send the stop tran token, and deselect the card
Alexander_Zuest 6:a1fd0f1374e6 840 m_Spi.write(0xFD);
Alexander_Zuest 6:a1fd0f1374e6 841 deselect();
Alexander_Zuest 6:a1fd0f1374e6 842
Alexander_Zuest 6:a1fd0f1374e6 843 //Send CMD13(0x00000000) to verify that the programming was successful if enabled
Alexander_Zuest 6:a1fd0f1374e6 844 if (m_WriteValidation) {
Alexander_Zuest 6:a1fd0f1374e6 845 unsigned int resp;
Alexander_Zuest 6:a1fd0f1374e6 846 if (commandTransaction(CMD13, 0x00000000, &resp) != 0x00 || resp != 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 847 //Some manner of unrecoverable write error occured during programming, get out
Alexander_Zuest 6:a1fd0f1374e6 848 break;
Alexander_Zuest 6:a1fd0f1374e6 849 }
Alexander_Zuest 6:a1fd0f1374e6 850 }
Alexander_Zuest 6:a1fd0f1374e6 851
Alexander_Zuest 6:a1fd0f1374e6 852 //The data was written successfully
Alexander_Zuest 6:a1fd0f1374e6 853 return true;
Alexander_Zuest 6:a1fd0f1374e6 854 } else {
Alexander_Zuest 6:a1fd0f1374e6 855 //Send CMD12(0x00000000) to abort the transmission
Alexander_Zuest 6:a1fd0f1374e6 856 if (writeCommand(CMD12, 0x00000000) != 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 857 //The command failed, get out
Alexander_Zuest 6:a1fd0f1374e6 858 break;
Alexander_Zuest 6:a1fd0f1374e6 859 }
Alexander_Zuest 6:a1fd0f1374e6 860
Alexander_Zuest 6:a1fd0f1374e6 861 //Deselect the card
Alexander_Zuest 6:a1fd0f1374e6 862 deselect();
Alexander_Zuest 6:a1fd0f1374e6 863
Alexander_Zuest 6:a1fd0f1374e6 864 //Check the error token
Alexander_Zuest 6:a1fd0f1374e6 865 if (token == 0x0A) {
Alexander_Zuest 6:a1fd0f1374e6 866 //Determine the number of well written blocks if possible
Alexander_Zuest 6:a1fd0f1374e6 867 unsigned int writtenBlocks = 0;
Alexander_Zuest 6:a1fd0f1374e6 868 if (m_CardType != CARD_MMC && select()) {
Alexander_Zuest 6:a1fd0f1374e6 869 //Send ACMD22(0x00000000) to get the number of well written blocks
Alexander_Zuest 6:a1fd0f1374e6 870 if (writeCommand(ACMD22, 0x00000000) == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 871 //Read the data
Alexander_Zuest 6:a1fd0f1374e6 872 char acmdData[4];
Alexander_Zuest 6:a1fd0f1374e6 873 if (readData(acmdData, 4)) {
Alexander_Zuest 6:a1fd0f1374e6 874 //Extract the number of well written blocks
Alexander_Zuest 6:a1fd0f1374e6 875 writtenBlocks = acmdData[0] << 24;
Alexander_Zuest 6:a1fd0f1374e6 876 writtenBlocks |= acmdData[1] << 16;
Alexander_Zuest 6:a1fd0f1374e6 877 writtenBlocks |= acmdData[2] << 8;
Alexander_Zuest 6:a1fd0f1374e6 878 writtenBlocks |= acmdData[3];
Alexander_Zuest 6:a1fd0f1374e6 879 }
Alexander_Zuest 6:a1fd0f1374e6 880 }
Alexander_Zuest 6:a1fd0f1374e6 881 deselect();
Alexander_Zuest 6:a1fd0f1374e6 882 }
Alexander_Zuest 6:a1fd0f1374e6 883
Alexander_Zuest 6:a1fd0f1374e6 884 //Roll back the variables based on the number of well written blocks
Alexander_Zuest 6:a1fd0f1374e6 885 currentBuffer = buffer + (writtenBlocks << 9);
Alexander_Zuest 6:a1fd0f1374e6 886 currentLba = lba + writtenBlocks;
Alexander_Zuest 6:a1fd0f1374e6 887 currentCount = count - writtenBlocks;
Alexander_Zuest 6:a1fd0f1374e6 888
Alexander_Zuest 6:a1fd0f1374e6 889 //Try again
Alexander_Zuest 6:a1fd0f1374e6 890 continue;
Alexander_Zuest 6:a1fd0f1374e6 891 } else {
Alexander_Zuest 6:a1fd0f1374e6 892 //A write error occured, get out
Alexander_Zuest 6:a1fd0f1374e6 893 break;
Alexander_Zuest 6:a1fd0f1374e6 894 }
Alexander_Zuest 6:a1fd0f1374e6 895 }
Alexander_Zuest 6:a1fd0f1374e6 896 } else {
Alexander_Zuest 6:a1fd0f1374e6 897 //The command failed, get out
Alexander_Zuest 6:a1fd0f1374e6 898 break;
Alexander_Zuest 6:a1fd0f1374e6 899 }
Alexander_Zuest 6:a1fd0f1374e6 900 }
Alexander_Zuest 6:a1fd0f1374e6 901
Alexander_Zuest 6:a1fd0f1374e6 902 //The multiple block write failed
Alexander_Zuest 6:a1fd0f1374e6 903 deselect();
Alexander_Zuest 6:a1fd0f1374e6 904 return false;
Alexander_Zuest 6:a1fd0f1374e6 905 }
Alexander_Zuest 6:a1fd0f1374e6 906
Alexander_Zuest 6:a1fd0f1374e6 907 bool SDFileSystem::enableHighSpeedMode()
Alexander_Zuest 6:a1fd0f1374e6 908 {
Alexander_Zuest 6:a1fd0f1374e6 909 //Try to issue CMD6 up to 3 times
Alexander_Zuest 6:a1fd0f1374e6 910 for (int f = 0; f < 3; f++) {
Alexander_Zuest 6:a1fd0f1374e6 911 //Select the card, and wait for ready
Alexander_Zuest 6:a1fd0f1374e6 912 if(!select())
Alexander_Zuest 6:a1fd0f1374e6 913 break;
Alexander_Zuest 6:a1fd0f1374e6 914
Alexander_Zuest 6:a1fd0f1374e6 915 //Send CMD6(0x80FFFFF1) to change the access mode to high speed
Alexander_Zuest 6:a1fd0f1374e6 916 if (writeCommand(CMD6, 0x80FFFFF1) == 0x00) {
Alexander_Zuest 6:a1fd0f1374e6 917 //Read the 64B status data block
Alexander_Zuest 6:a1fd0f1374e6 918 char status[64];
Alexander_Zuest 6:a1fd0f1374e6 919 bool success = readData(status, 64);
Alexander_Zuest 6:a1fd0f1374e6 920 deselect();
Alexander_Zuest 6:a1fd0f1374e6 921 if (success) {
Alexander_Zuest 6:a1fd0f1374e6 922 //Return whether or not the operation was successful
Alexander_Zuest 6:a1fd0f1374e6 923 return ((status[16] & 0x0F) == 0x1);
Alexander_Zuest 6:a1fd0f1374e6 924 }
Alexander_Zuest 6:a1fd0f1374e6 925 } else {
Alexander_Zuest 6:a1fd0f1374e6 926 //The command failed, get out
Alexander_Zuest 6:a1fd0f1374e6 927 break;
Alexander_Zuest 6:a1fd0f1374e6 928 }
Alexander_Zuest 6:a1fd0f1374e6 929 }
Alexander_Zuest 6:a1fd0f1374e6 930
Alexander_Zuest 6:a1fd0f1374e6 931 //The operation failed 3 times
Alexander_Zuest 6:a1fd0f1374e6 932 deselect();
Alexander_Zuest 6:a1fd0f1374e6 933 return false;
Alexander_Zuest 6:a1fd0f1374e6 934 }
Alexander_Zuest 6:a1fd0f1374e6 935