Kaif Kutchwala 201267448 ELEC2645 Project

Dependencies:   mbed

Committer:
KaifK
Date:
Tue May 26 15:50:46 2020 +0000
Revision:
31:e1f80d181779
Parent:
21:d5b1160f349f
Final Submission. I have read and agreed with Statement of Academic Integrity.

Who changed what in which revision?

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