aaa

Dependencies:   FATFileSystem

Dependents:   AutoFlight2017_now2 AutoFlight2018_Control sbus_test_2018 Autoflight2018_sbusread ... more

Committer:
TUATBM
Date:
Sat Aug 26 16:30:14 2017 +0000
Revision:
0:85fbe134acff
forSkipper

Who changed what in which revision?

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