Ben Evans University Second Year Project. Game Called Defender.

Dependencies:   mbed

https://os.mbed.com/media/uploads/evanso/84bc1a30759fd6a1e3f1fd1fae3e97c2.png

Hello, soldier, you have been specially selected as the defender of planet earth.

Your mission, if you choose to accept it. Fly around the planet and pulverise invading alien ships for as long as you can. Stop the aliens abducting the innocent people on the ground. Be warned if an alien ship manages to abduct a person and take them to top of the screen, they will no longer move randomly and will begin to hunt you down. This sounds like a challenge you were trained for.

But don’t worry soldier you’re not going into battle empty-handed. Your ship is equipped with a state of the art laser beam that has unlimited ammo and four smart bombs that will destroy anything on the screen. The ship also has three lives so use them wisely.

As time goes on more alien ships will arrive on planet earth increasing the difficulty of your mission. And remember the landscape bellow loops around so if you continually fly in the same direction you go to your original position. Good luck soldier.

Committer:
evanso
Date:
Wed May 27 02:06:05 2020 +0000
Revision:
87:832ca78426b5
Parent:
48:e308067cfea5
Final Submission. I have read and agreed with Statement of Academic Integrity.

Who changed what in which revision?

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