Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: FATFileSystem
Diff: SDFileSystem.cpp
- Revision:
- 23:c03ef1abef0e
- Parent:
- 22:3fa5eaf48e81
- Child:
- 24:698affe9560c
--- a/SDFileSystem.cpp Wed Feb 24 17:46:31 2016 +0000 +++ b/SDFileSystem.cpp Thu Mar 31 17:39:48 2016 +0000 @@ -1,6 +1,6 @@ /* SD/MMC File System Library * Copyright (c) 2016 Neil Thiessen - * + * Modified for the use with STM32F746 Discovery (C) 2016 Dieter Greaf * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at @@ -16,49 +16,39 @@ #include "SDFileSystem.h" #include "diskio.h" -#include "pinmap.h" #include "SDCRC.h" +//for cache flush function +#include "SD_Helper.h" -SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd, SwitchType cdtype, int hz) - : FATFileSystem(name), - m_Spi(mosi, miso, sclk), - m_Cs(cs, 1), - m_Cd(cd), - m_FREQ(hz) +SDFileSystem::SDFileSystem( const char* name) + : FATFileSystem(name), m_Cd(PC_13) { //Initialize the member variables + uint8_t initstat; + void* h; m_CardType = CARD_NONE; m_Crc = true; m_LargeFrames = false; m_WriteValidation = true; m_Status = STA_NOINIT; - - //Enable the internal pull-up resistor on MISO - pin_mode(miso, PullUp); - - //Configure the SPI bus - m_Spi.format(8, 0); - - //Configure the card detect pin - if (cdtype == SWITCH_POS_NO) { - m_Cd.mode(PullDown); - m_CdAssert = 1; - m_Cd.fall(this, &SDFileSystem::onCardRemoval); - } else if (cdtype == SWITCH_POS_NC) { - m_Cd.mode(PullDown); - m_CdAssert = 0; - m_Cd.rise(this, &SDFileSystem::onCardRemoval); - } else if (cdtype == SWITCH_NEG_NO) { - m_Cd.mode(PullUp); - m_CdAssert = 0; - m_Cd.rise(this, &SDFileSystem::onCardRemoval); - } else if (cdtype == SWITCH_NEG_NC) { - m_Cd.mode(PullUp); - m_CdAssert = 1; - m_Cd.fall(this, &SDFileSystem::onCardRemoval); - } else { - m_CdAssert = -1; - } + m_Cd.mode(PullUp); + m_CdAssert = 0; + m_Cd.rise(this, &SDFileSystem::onCardRemoval); + h=(void*)&SDFileSystem::DMA2_Stream3_IRQHandler; + NVIC_SetVector(DMA2_Stream3_IRQn,(uint32_t)h); + h=(void*)&SDFileSystem::DMA2_Stream6_IRQHandler; + NVIC_SetVector(DMA2_Stream6_IRQn,(uint32_t)h); + h=(void*)&SDFileSystem::SDMMC1_IRQHandler; + NVIC_SetVector(SDMMC1_IRQn,(uint32_t)h); + initstat=BSP_SD_Init(); + if (initstat!=MSD_OK) + { + m_Status |= STA_NOINIT; + } + else + { + m_Status &= ~STA_NOINIT; + } } bool SDFileSystem::card_present() @@ -100,10 +90,10 @@ if (enabled && !m_Crc) { //Send CMD59(0x00000001) to enable CRC m_Crc = true; - commandTransaction(CMD59, 0x00000001); + BSP_SD_CommandTransaction(CMD59, 0x00000001); } else if (!enabled && m_Crc) { - //Send CMD59(0x00000000) to disable CRC - commandTransaction(CMD59, 0x00000000); + //Send CMD59(0x00000000) to disableAPP/MBED/targets/hal/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG CRC + BSP_SD_CommandTransaction(CMD59, 0x00000000); m_Crc = false; } } @@ -147,163 +137,43 @@ int SDFileSystem::disk_initialize() { - char token; - unsigned int resp; //Make sure there's a card in the socket before proceeding checkSocket(); if (m_Status & STA_NODISK) return m_Status; - - //Make sure we're not already initialized before proceeding - if (!(m_Status & STA_NOINIT)) - return m_Status; - - //Set the SPI frequency to 400kHz for initialization - m_Spi.frequency(400000); - - //Send 80 dummy clocks with /CS deasserted and DI held high - m_Cs = 1; - for (int i = 0; i < 10; i++) - m_Spi.write(0xFF); - - //Send CMD0(0x00000000) to reset the card - if (commandTransaction(CMD0, 0x00000000) != 0x01) { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - - //Send CMD59(0x00000001) to enable CRC if necessary - if (m_Crc) { - if (commandTransaction(CMD59, 0x00000001) != 0x01) { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - } - - //Send CMD8(0x000001AA) to see if this is an SDCv2 card - if (commandTransaction(CMD8, 0x000001AA, &resp) == 0x01) { - //This is an SDCv2 card, get the 32-bit return value and verify the voltage range/check pattern - if ((resp & 0xFFF) != 0x1AA) { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - - //Send CMD58(0x00000000) to read the OCR, and verify that the card supports 3.2-3.3V - if (commandTransaction(CMD58, 0x00000000, &resp) != 0x01 || !(resp & (1 << 20))) { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - - //Try to initialize the card using ACMD41(0x00100000) - for (int i = 0; i < 1000; i++) { - token = commandTransaction(ACMD41, 0x40100000); - if (token != 0x01) { - break; - } - } - - //Check if the card initialized - if (token != 0x00) { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - - //Send CMD58(0x00000000) to read the OCR - if (commandTransaction(CMD58, 0x00000000, &resp) == 0x00) { - //Check the CCS bit to determine if this is a high capacity card - if (resp & (1 << 30)) - m_CardType = CARD_SDHC; - else - m_CardType = CARD_SD; + BSP_SD_GetCardInfo(&m_CardInfo); - //Increase the SPI frequency to full speed (up to 25MHz for SDCv2) - if (m_FREQ > 25000000) - m_Spi.frequency(25000000); - else - m_Spi.frequency(m_FREQ); - } else { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - } else { - //Didn't respond or illegal command, this is either an SDCv1 or MMC card - //Send CMD58(0x00000000) to read the OCR, and verify that the card supports 3.2-3.3V - if (commandTransaction(CMD58, 0x00000000, &resp) != 0x01 || !(resp & (1 << 20))) { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - - //Try to initialize the card using ACMD41(0x00100000) - for (int i = 0; i < 1000; i++) { - token = commandTransaction(ACMD41, 0x40100000); - if (token != 0x01) { - break; - } - } - - //Check if the card initialized - if (token == 0x00) { - //This is an SDCv1 standard capacity card - m_CardType = CARD_SD; - - //Increase the SPI frequency to full speed (up to 25MHz for SDCv1) - if (m_FREQ > 25000000) - m_Spi.frequency(25000000); - else - m_Spi.frequency(m_FREQ); - } else { - //Try to initialize the card using CMD1(0x00100000) - for (int i = 0; i < 1000; i++) { - token = commandTransaction(CMD1, 0x00100000); - if (token != 0x01) { - break; - } - } - - //Check if the card initialized - if (token == 0x00) { - //This is an MMCv3 card - m_CardType = CARD_MMC; - - //Increase the SPI frequency to full speed (up to 20MHz for MMCv3) - if (m_FREQ > 20000000) - m_Spi.frequency(20000000); - else - m_Spi.frequency(m_FREQ); - } else { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - } - } - - //Send ACMD42(0x00000000) to disconnect the internal pull-up resistor on pin 1 if necessary - if (m_CardType != CARD_MMC) { - if (commandTransaction(ACMD42, 0x00000000) != 0x00) { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - } - - //Send CMD16(0x00000200) to force the block size to 512B if necessary - if (m_CardType != CARD_SDHC) { - if (commandTransaction(CMD16, 0x00000200) != 0x00) { - //Initialization failed - m_CardType = CARD_UNKNOWN; - return m_Status; - } - } - + switch(m_CardInfo.CardType) + { + case STD_CAPACITY_SD_CARD_V1_1: + { m_CardType = CARD_SD; + break; } + case STD_CAPACITY_SD_CARD_V2_0: + { m_CardType = CARD_SD; + break; } + case HIGH_CAPACITY_SD_CARD: + { m_CardType = CARD_SDHC; + break; } + case MULTIMEDIA_CARD: + { m_CardType = CARD_MMC; + break; } + case SECURE_DIGITAL_IO_CARD: + { m_CardType = CARD_SD; + break; } + case HIGH_SPEED_MULTIMEDIA_CARD: + { m_CardType = CARD_MMC; + break; } + case SECURE_DIGITAL_IO_COMBO_CARD: + { m_CardType = CARD_SD; + break; } + case HIGH_CAPACITY_MMC_CARD: + { m_CardType = CARD_MMC; + break; } + default: + {m_CardType = CARD_UNKNOWN; + return m_Status;} + } //The card is now initialized m_Status &= ~STA_NOINIT; @@ -322,20 +192,30 @@ int SDFileSystem::disk_read(uint8_t* buffer, uint32_t sector, uint32_t count) { + int retval; //Make sure the card is initialized before proceeding if (m_Status & STA_NOINIT) return RES_NOTRDY; //Read a single block, or multiple blocks if (count > 1) { - return readBlocks((char*)buffer, sector, count) ? RES_OK : RES_ERROR; + BSP_SD_Set_RX_Busy(); + retval=BSP_SD_ReadBlocks_DMA((uint32_t *)buffer, (uint64_t) (sector * 512),512, count); + while(BSP_SD_Get_RX_busy()==1){;} + CPU_CACHE_Flush((uint32_t *)buffer,(512*count)); + return (retval ? RES_ERROR : RES_OK); } else { - return readBlock((char*)buffer, sector) ? RES_OK : RES_ERROR; + BSP_SD_Set_RX_Busy(); + retval= BSP_SD_ReadBlocks_DMA((uint32_t *)buffer, (uint64_t) (sector * 512), 512, 1); + while(BSP_SD_Get_RX_busy()==1){;} + CPU_CACHE_Flush((uint32_t *)buffer,(512)); + return (retval ? RES_ERROR : RES_OK); } } int SDFileSystem::disk_write(const uint8_t* buffer, uint32_t sector, uint32_t count) { + int retval; //Make sure the card is initialized before proceeding if (m_Status & STA_NOINIT) return RES_NOTRDY; @@ -346,17 +226,27 @@ //Write a single block, or multiple blocks if (count > 1) { - return writeBlocks((const char*)buffer, sector, count) ? RES_OK : RES_ERROR; + CPU_CACHE_Flush((uint32_t *)buffer,(512*count)); + BSP_SD_Set_TX_Busy(); + retval= BSP_SD_WriteBlocks_DMA((uint32_t *)buffer, (uint64_t) (sector * 512), 512, count); + while(BSP_SD_Get_TX_busy()==1){;} + return (retval? RES_ERROR : RES_OK); } else { - return writeBlock((const char*)buffer, sector) ? RES_OK : RES_ERROR; + CPU_CACHE_Flush((uint32_t *)buffer,(512)); + BSP_SD_Set_TX_Busy(); + retval= BSP_SD_WriteBlocks_DMA((uint32_t *)buffer, (uint64_t) (sector * 512), 512, 1); + while(BSP_SD_Get_TX_busy()==1){;} + return (retval? RES_ERROR : RES_OK); + } } int SDFileSystem::disk_sync() { //Select the card so we're forced to wait for the end of any internal write processes - if (select()) { - deselect(); + while(BSP_SD_GetStatus()==SD_TRANSFER_BUSY){;} + if(BSP_SD_GetStatus()==SD_TRANSFER_OK) + { return RES_OK; } else { return RES_ERROR; @@ -365,45 +255,13 @@ uint32_t SDFileSystem::disk_sectors() { + uint32_t sectors=0; //Make sure the card is initialized before proceeding if (m_Status & STA_NOINIT) return 0; - - //Try to read the CSD register up to 3 times - for (int f = 0; f < 3; f++) { - //Select the card, and wait for ready - if(!select()) - break; - - //Send CMD9(0x00000000) to read the CSD register - if (writeCommand(CMD9, 0x00000000) == 0x00) { - //Read the 16B CSD data block - char csd[16]; - bool success = readData(csd, 16); - deselect(); - if (success) { - //Calculate the sector count based on the card type - if ((csd[0] >> 6) == 0x01) { - //Calculate the sector count for a high capacity card - unsigned int size = (((csd[7] & 0x3F) << 16) | (csd[8] << 8) | csd[9]) + 1; - return size << 10; - } else { - //Calculate the sector count for a standard capacity card - unsigned int size = (((csd[6] & 0x03) << 10) | (csd[7] << 2) | ((csd[8] & 0xC0) >> 6)) + 1; - size <<= ((((csd[9] & 0x03) << 1) | ((csd[10] & 0x80) >> 7)) + 2); - size <<= (csd[5] & 0x0F); - return size >> 9; - } - } - } else { - //The command failed, get out - break; - } - } - - //The read operation failed 3 times - deselect(); - return 0; + BSP_SD_GetCardInfo(&m_CardInfo); + sectors=m_CardInfo.CardCapacity>>9; + return sectors; } void SDFileSystem::onCardRemoval() @@ -432,454 +290,39 @@ } } -inline bool SDFileSystem::waitReady(int timeout) -{ - char resp; - //Keep sending dummy clocks with DI held high until the card releases the DO line - m_Timer.start(); - do { - resp = m_Spi.write(0xFF); - } while (resp == 0x00 && m_Timer.read_ms() < timeout); - m_Timer.stop(); - m_Timer.reset(); - - //Return success/failure - return (resp > 0x00); -} - -inline bool SDFileSystem::select() -{ - //Assert /CS - m_Cs = 0; - - //Send 8 dummy clocks with DI held high to enable DO - m_Spi.write(0xFF); - - //Wait for up to 500ms for the card to become ready - if (waitReady(500)) { - return true; - } else { - //We timed out, deselect and return false - deselect(); - return false; - } -} - -inline void SDFileSystem::deselect() -{ - //Deassert /CS - m_Cs = 1; - - //Send 8 dummy clocks with DI held high to disable DO - m_Spi.write(0xFF); -} - -inline char SDFileSystem::commandTransaction(char cmd, unsigned int arg, unsigned int* resp) -{ - //Select the card, and wait for ready - if(!select()) - return 0xFF; - - //Perform the command transaction - char token = writeCommand(cmd, arg, resp); - - //Deselect the card, and return the R1 response token - deselect(); - return token; -} - -char SDFileSystem::writeCommand(char cmd, unsigned int arg, unsigned int* resp) +/*interrupthandlers */ +/** + * @brief This function handles DMA2 Stream 3 interrupt request. + * @param None + * @retval None + */ +void SDFileSystem::DMA2_Stream3_IRQHandler(void) { - char token; - - //Try to send the command up to 3 times - for (int f = 0; f < 3; f++) { - //Send CMD55(0x00000000) prior to an application specific command - if (cmd == ACMD22 || cmd == ACMD23 || cmd == ACMD41 || cmd == ACMD42) { - token = writeCommand(CMD55, 0x00000000); - if (token > 0x01) - return token; - - //Deselect and reselect the card between CMD55 and an ACMD - deselect(); - if(!select()) - return 0xFF; - } - - //Prepare the command packet - char cmdPacket[6]; - cmdPacket[0] = cmd; - cmdPacket[1] = arg >> 24; - cmdPacket[2] = arg >> 16; - cmdPacket[3] = arg >> 8; - cmdPacket[4] = arg; - if (m_Crc || cmd == CMD0 || cmd == CMD8) - cmdPacket[5] = (SDCRC::crc7(cmdPacket, 5) << 1) | 0x01; - else - cmdPacket[5] = 0x01; - - //Send the command packet - for (int i = 0; i < 6; i++) - m_Spi.write(cmdPacket[i]); - - //Discard the stuff byte immediately following CMD12 - if (cmd == CMD12) - m_Spi.write(0xFF); - - //Allow up to 8 bytes of delay for the R1 response token - for (int i = 0; i < 9; i++) { - token = m_Spi.write(0xFF); - if (!(token & 0x80)) - break; - } - - //Verify the R1 response token - if (token == 0xFF) { - //No data was received, get out early - break; - } else if (token & (1 << 3)) { - //There was a CRC error, try again - continue; - } else if (token > 0x01) { - //An error occured, get out early - break; - } - - //Handle R2 and R3/R7 response tokens - if (cmd == CMD13 && resp != NULL) { - //Read the R2 response value - *resp = m_Spi.write(0xFF); - } else if ((cmd == CMD8 || cmd == CMD58) && resp != NULL) { - //Read the R3/R7 response value - *resp = (m_Spi.write(0xFF) << 24); - *resp |= (m_Spi.write(0xFF) << 16); - *resp |= (m_Spi.write(0xFF) << 8); - *resp |= m_Spi.write(0xFF); - } - - //The command was successful - break; - } - - //Return the R1 response token - return token; -} - -bool SDFileSystem::readData(char* buffer, int length) -{ - char token; - unsigned short crc; - - //Wait for up to 500ms for a token to arrive - m_Timer.start(); - do { - token = m_Spi.write(0xFF); - } while (token == 0xFF && m_Timer.read_ms() < 500); - m_Timer.stop(); - m_Timer.reset(); - - //Check if a valid start block token was received - if (token != 0xFE) - return false; - - //Check if large frames are enabled or not - if (m_LargeFrames) { - //Switch to 16-bit frames for better performance - m_Spi.format(16, 0); - - //Read the data block into the buffer - unsigned short dataWord; - for (int i = 0; i < length; i += 2) { - dataWord = m_Spi.write(0xFFFF); - buffer[i] = dataWord >> 8; - buffer[i + 1] = dataWord; - } - - //Read the CRC16 checksum for the data block - crc = m_Spi.write(0xFFFF); - - //Switch back to 8-bit frames - m_Spi.format(8, 0); - } else { - //Read the data into the buffer - for (int i = 0; i < length; i++) - buffer[i] = m_Spi.write(0xFF); - - //Read the CRC16 checksum for the data block - crc = (m_Spi.write(0xFF) << 8); - crc |= m_Spi.write(0xFF); - } - - //Return the validity of the CRC16 checksum (if enabled) - return (!m_Crc || crc == SDCRC::crc16(buffer, length)); -} - -char SDFileSystem::writeData(const char* buffer, char token) -{ - //Calculate the CRC16 checksum for the data block (if enabled) - unsigned short crc = (m_Crc) ? SDCRC::crc16(buffer, 512) : 0xFFFF; - - //Wait for up to 500ms for the card to become ready - if (!waitReady(500)) - return false; - - //Send the start block token - m_Spi.write(token); - - //Check if large frames are enabled or not - if (m_LargeFrames) { - //Switch to 16-bit frames for better performance - m_Spi.format(16, 0); - - //Write the data block from the buffer - for (int i = 0; i < 512; i += 2) - m_Spi.write((buffer[i] << 8) | buffer[i + 1]); - - //Send the CRC16 checksum for the data block - m_Spi.write(crc); - - //Switch back to 8-bit frames - m_Spi.format(8, 0); - } else { - //Write the data block from the buffer - for (int i = 0; i < 512; i++) - m_Spi.write(buffer[i]); - - //Send the CRC16 checksum for the data block - m_Spi.write(crc >> 8); - m_Spi.write(crc); - } - - //Return the data response token - return (m_Spi.write(0xFF) & 0x1F); + BSP_SD_DMA_Rx_IRQHandler(); + BSP_SD_Clear_RX_Busy(); } -inline bool SDFileSystem::readBlock(char* buffer, unsigned int lba) -{ - //Try to read the block up to 3 times - for (int f = 0; f < 3; f++) { - //Select the card, and wait for ready - if(!select()) - break; - - //Send CMD17(block) to read a single block - if (writeCommand(CMD17, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) { - //Try to read the block, and deselect the card - bool success = readData(buffer, 512); - deselect(); - - //Return if successful - if (success) - return true; - } else { - //The command failed, get out - break; - } - } - - //The single block read failed - deselect(); - return false; -} - -inline bool SDFileSystem::readBlocks(char* buffer, unsigned int lba, unsigned int count) +/** + * @brief This function handles DMA2 Stream 6 interrupt request. + * @param None + * @retval None + */ +void SDFileSystem::DMA2_Stream6_IRQHandler(void) { - //Try to read each block up to 3 times - for (int f = 0; f < 3;) { - //Select the card, and wait for ready - if(!select()) - break; - - //Send CMD18(block) to read multiple blocks - if (writeCommand(CMD18, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) { - //Try to read all of the data blocks - do { - //Read the next block, and break on errors - if (!readData(buffer, 512)) { - f++; - break; - } - - //Update the variables - lba++; - buffer += 512; - f = 0; - } while (--count); - - //Send CMD12(0x00000000) to stop the transmission - if (writeCommand(CMD12, 0x00000000) != 0x00) { - //The command failed, get out - break; - } - - //Deselect the card, and return if successful - deselect(); - if (count == 0) - return true; - } else { - //The command failed, get out - break; - } - } - - //The multiple block read failed - deselect(); - return false; + BSP_SD_DMA_Tx_IRQHandler(); + BSP_SD_Clear_TX_Busy(); } -inline bool SDFileSystem::writeBlock(const char* buffer, unsigned int lba) +/** + * @brief This function handles SDIO interrupt request. + * @param None + * @retval None + */ +void SDFileSystem::SDMMC1_IRQHandler(void) { - //Try to write the block up to 3 times - for (int f = 0; f < 3; f++) { - //Select the card, and wait for ready - if(!select()) - break; - - //Send CMD24(block) to write a single block - if (writeCommand(CMD24, (m_CardType == CARD_SDHC) ? lba : lba << 9) == 0x00) { - //Try to write the block, and deselect the card - char token = writeData(buffer, 0xFE); - deselect(); - - //Check the data response token - if (token == 0x0A) { - //A CRC error occured, try again - continue; - } else if (token == 0x0C) { - //A write error occured, get out - break; - } - - //Send CMD13(0x00000000) to verify that the programming was successful if enabled - if (m_WriteValidation) { - unsigned int resp; - if (commandTransaction(CMD13, 0x00000000, &resp) != 0x00 || resp != 0x00) { - //Some manner of unrecoverable write error occured during programming, get out - break; - } - } - - //The data was written successfully - return true; - } else { - //The command failed, get out - break; - } - } - - //The single block write failed - deselect(); - return false; + BSP_SD_IRQHandler(); } -inline bool SDFileSystem::writeBlocks(const char* buffer, unsigned int lba, unsigned int count) -{ - char token; - const char* currentBuffer = buffer; - unsigned int currentLba = lba; - int currentCount = count; - - //Try to write each block up to 3 times - for (int f = 0; f < 3;) { - //If this is an SD card, send ACMD23(count) to set the number of blocks to pre-erase - if (m_CardType != CARD_MMC) { - if (commandTransaction(ACMD23, currentCount) != 0x00) { - //The command failed, get out - break; - } - } - - //Select the card, and wait for ready - if(!select()) - break; - - //Send CMD25(block) to write multiple blocks - if (writeCommand(CMD25, (m_CardType == CARD_SDHC) ? currentLba : currentLba << 9) == 0x00) { - //Try to write all of the data blocks - do { - //Write the next block and break on errors - token = writeData(currentBuffer, 0xFC); - if (token != 0x05) { - f++; - break; - } - - //Update the variables - currentBuffer += 512; - f = 0; - } while (--currentCount); - - //Wait for up to 500ms for the card to finish processing the last block - if (!waitReady(500)) - break; - - //Finalize the transmission - if (currentCount == 0) { - //Send the stop tran token, and deselect the card - m_Spi.write(0xFD); - deselect(); - //Send CMD13(0x00000000) to verify that the programming was successful if enabled - if (m_WriteValidation) { - unsigned int resp; - if (commandTransaction(CMD13, 0x00000000, &resp) != 0x00 || resp != 0x00) { - //Some manner of unrecoverable write error occured during programming, get out - break; - } - } - //The data was written successfully - return true; - } else { - //Send CMD12(0x00000000) to abort the transmission - if (writeCommand(CMD12, 0x00000000) != 0x00) { - //The command failed, get out - break; - } - - //Deselect the card - deselect(); - - //Check the error token - if (token == 0x0A) { - //Determine the number of well written blocks if possible - unsigned int writtenBlocks = 0; - if (m_CardType != CARD_MMC && select()) { - //Send ACMD22(0x00000000) to get the number of well written blocks - if (writeCommand(ACMD22, 0x00000000) == 0x00) { - //Read the data - char acmdData[4]; - if (readData(acmdData, 4)) { - //Extract the number of well written blocks - writtenBlocks = acmdData[0] << 24; - writtenBlocks |= acmdData[1] << 16; - writtenBlocks |= acmdData[2] << 8; - writtenBlocks |= acmdData[3]; - } - } - deselect(); - } - - //Roll back the variables based on the number of well written blocks - currentBuffer = buffer + (writtenBlocks << 9); - currentLba = lba + writtenBlocks; - currentCount = count - writtenBlocks; - - //Try again - continue; - } else { - //A write error occured, get out - break; - } - } - } else { - //The command failed, get out - break; - } - } - - //The multiple block write failed - deselect(); - return false; -}