SDFileSystem for STM32F746NG DISCOVERY with 4bit SDMMC interface on fixed pins
Dependents: DISCO-F746NG_SDFileSystem uzairkhan DISCO-F746NG_Scope_copy
Fork of SDFileSystem by
Revision 23:c03ef1abef0e, committed 2016-03-31
- Comitter:
- DieterGraef
- Date:
- Thu Mar 31 17:39:48 2016 +0000
- Parent:
- 22:3fa5eaf48e81
- Child:
- 24:698affe9560c
- Commit message:
- For use with STM32F746NG Discovery with SDMMC 4Bit Bus on fixed Pins
Changed in this revision
--- 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; -}
--- a/SDFileSystem.h Wed Feb 24 17:46:31 2016 +0000 +++ b/SDFileSystem.h 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 @@ -18,6 +18,7 @@ #define SD_FILE_SYSTEM_H #include "mbed.h" +#include "stm32746g_discovery_sd.h" #include "FATFileSystem.h" /** SDFileSystem class. @@ -29,7 +30,7 @@ * #include "SDFileSystem.h" * * //Create an SDFileSystem object - * SDFileSystem sd(p5, p6, p7, p20, "sd"); + * SDFileSystem sd("sd"); * * int main() * { @@ -65,7 +66,11 @@ * sd.unmount(); * } * @endcode + */ + #define CMD59 (0x40 | 59) +using namespace mbed; + class SDFileSystem : public FATFileSystem { public: @@ -100,7 +105,7 @@ * @param cdtype The type of card detect switch. * @param hz The SPI bus frequency (defaults to 1MHz). */ - SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name, PinName cd = NC, SwitchType cdtype = SWITCH_NONE, int hz = 1000000); + SDFileSystem( const char* name); /** Determine whether or not a card is present * @@ -169,55 +174,21 @@ virtual uint32_t disk_sectors(); private: - //Commands - enum Command { - CMD0 = (0x40 | 0), /**< GO_IDLE_STATE */ - CMD1 = (0x40 | 1), /**< SEND_OP_COND */ - CMD8 = (0x40 | 8), /**< SEND_IF_COND */ - CMD9 = (0x40 | 9), /**< SEND_CSD */ - CMD12 = (0x40 | 12), /**< STOP_TRANSMISSION */ - CMD13 = (0x40 | 13), /**< SEND_STATUS */ - CMD16 = (0x40 | 16), /**< SET_BLOCKLEN */ - CMD17 = (0x40 | 17), /**< READ_SINGLE_BLOCK */ - CMD18 = (0x40 | 18), /**< READ_MULTIPLE_BLOCK */ - ACMD22 = (0x40 | 22), /**< SEND_NUM_WR_BLOCKS */ - ACMD23 = (0x40 | 23), /**< SET_WR_BLK_ERASE_COUNT */ - CMD24 = (0x40 | 24), /**< WRITE_BLOCK */ - CMD25 = (0x40 | 25), /**< WRITE_MULTIPLE_BLOCK */ - ACMD41 = (0x40 | 41), /**< SD_SEND_OP_COND */ - ACMD42 = (0x40 | 42), /**< SET_CLR_CARD_DETECT */ - CMD55 = (0x40 | 55), /**< APP_CMD */ - CMD58 = (0x40 | 58), /**< READ_OCR */ - CMD59 = (0x40 | 59) /**< CRC_ON_OFF */ - }; - - //Member variables Timer m_Timer; - SPI m_Spi; - DigitalOut m_Cs; InterruptIn m_Cd; int m_CdAssert; - const int m_FREQ; SDFileSystem::CardType m_CardType; bool m_Crc; bool m_LargeFrames; bool m_WriteValidation; int m_Status; - + HAL_SD_CardInfoTypedef m_CardInfo; //Internal methods void onCardRemoval(); void checkSocket(); - bool waitReady(int timeout); - bool select(); - void deselect(); - char commandTransaction(char cmd, unsigned int arg, unsigned int* resp = NULL); - char writeCommand(char cmd, unsigned int arg, unsigned int* resp = NULL); - bool readData(char* buffer, int length); - char writeData(const char* buffer, char token); - bool readBlock(char* buffer, unsigned int lba); - bool readBlocks(char* buffer, unsigned int lba, unsigned int count); - bool writeBlock(const char* buffer, unsigned int lba); - bool writeBlocks(const char* buffer, unsigned int lba, unsigned int count); + void DMA2_Stream3_IRQHandler(); + void DMA2_Stream6_IRQHandler(); + void SDMMC1_IRQHandler(); }; #endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SD_Helper.c Thu Mar 31 17:39:48 2016 +0000 @@ -0,0 +1,126 @@ +#include "SD_Helper.h" +#include "stm32746g_discovery_sd.h" + +#define _CCSIDR_LSSHIFT(x) (((x) & SCB_CCSIDR_LINESIZE_Msk) >> SCB_CCSIDR_LINESIZE_Pos) + +static SD_HandleTypeDef uSdHandle; +static int RX_Busy; +static int TX_Busy; + + + + +/* cache flush */ +void CPU_CACHE_Flush(uint32_t * buffer, uint32_t length) +{ + // SCB_InvalidateDCache_by_Addr(buffer,length); + uint32_t ccsidr; + uint32_t smask; + uint32_t sshift; + uint32_t ways; + uint32_t wshift; + uint32_t ssize; + uint32_t sets; + uint32_t sw; + uint32_t start; + uint32_t ende; + + start=(uint32_t)buffer; + ende=start+length; + /* Get the characteristics of the D-Cache */ + + ccsidr = SCB->CCSIDR; + smask = CCSIDR_SETS(ccsidr); /* (Number of sets) - 1 */ + sshift = _CCSIDR_LSSHIFT(ccsidr) + 4; /* log2(cache-line-size-in-bytes) */ + ways = CCSIDR_WAYS(ccsidr); /* (Number of ways) - 1 */ + + /* Calculate the bit offset for the way field in the DCCISW register by + * counting the number of leading zeroes. For example: + * + * Number of Value of ways Field + * Ways 'ways' Offset + * 2 1 31 + * 4 3 30 + * 8 7 29 + * ... + */ + + wshift = __CLZ(ways) & 0x1f; + + /* Clean and invalidate the D-Cache over the range of addresses */ + + ssize = (1 << sshift); + start &= ~(ssize - 1); + __DSB(); + + do + { + int32_t tmpways = ways; + + /* Isolate the cache line associated with this address. For example + * if the cache line size is 32 bytes and the cache size is 16KB, then + * + * sshift = 5 : Offset to the beginning of the set field + * smask = 0x007f : Mask of the set field + */ + + sets = ((uint32_t)start >> sshift) & smask; + + /* Clean and invalidate each way for this cacheline */ + + do + { + sw = ((tmpways << wshift) | (sets << sshift)); + SCB->DCCISW=sw; + + } + while (tmpways--); + + /* Increment the address by the size of one cache line. */ + + start += ssize; + } + while (start < ende); + + __DSB(); + __ISB(); +} + +void BSP_SD_CommandTransaction(char cmd, unsigned int arg) +{ + SDMMC_CmdInitTypeDef sdmmc_cmdinitstructure; + uSdHandle.Instance = SDMMC1; + sdmmc_cmdinitstructure.Argument = (uint32_t)arg; + sdmmc_cmdinitstructure.CmdIndex = cmd; + sdmmc_cmdinitstructure.Response = SDMMC_RESPONSE_SHORT; + sdmmc_cmdinitstructure.WaitForInterrupt = SDMMC_WAIT_NO; + sdmmc_cmdinitstructure.CPSM = SDMMC_CPSM_ENABLE; + SDMMC_SendCommand(uSdHandle.Instance, &sdmmc_cmdinitstructure); +} + + +void BSP_SD_Set_RX_Busy(void) +{ + RX_Busy=1; +} +void BSP_SD_Clear_RX_Busy(void) +{ + RX_Busy=0; +} +int BSP_SD_Get_RX_busy(void) +{ + return RX_Busy; +} + +void BSP_SD_Set_TX_Busy(void) +{ + TX_Busy=1; +} +void BSP_SD_Clear_TX_Busy(void) +{ + TX_Busy=0; +} +int BSP_SD_Get_TX_busy(void) +{ + return TX_Busy; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/SD_Helper.h Thu Mar 31 17:39:48 2016 +0000 @@ -0,0 +1,26 @@ + /* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef ___SD_Helper +#define ___SD_Helper + +#include "cmsis.h" + +#ifdef __cplusplus + extern "C" { +#endif + +void CPU_CACHE_Flush(uint32_t * buffer, uint32_t length); + +void BSP_SD_CommandTransaction(char cmd, unsigned int arg); + +void BSP_SD_Set_RX_Busy(void); +void BSP_SD_Clear_RX_Busy(void); +int BSP_SD_Get_RX_busy(void); +void BSP_SD_Set_TX_Busy(void); +void BSP_SD_Clear_TX_Busy(void); +int BSP_SD_Get_TX_busy(void); + +#ifdef __cplusplus +} +#endif + +#endif /* ___SD_Helper */