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
SDFileSystem.cpp
- Committer:
- DieterGraef
- Date:
- 2016-04-13
- Revision:
- 26:8f15aa3b052b
- Parent:
- 25:391eade4ef85
- Child:
- 27:8d192c180436
File content as of revision 26:8f15aa3b052b:
/* 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
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "SDFileSystem.h"
#include "diskio.h"
#include "SDCRC.h"
//for cache flush function
#include "SD_Helper.h"
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;
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);
BSP_SD_Clear_Busy();
initstat=BSP_SD_Init();
if (initstat!=MSD_OK)
{
m_Status |= STA_NOINIT;
}
else
{
m_Status &= ~STA_NOINIT;
}
}
bool SDFileSystem::card_present()
{
//Check the card socket
checkSocket();
//Return whether or not a card is present
return !(m_Status & STA_NODISK);
}
SDFileSystem::CardType SDFileSystem::card_type()
{
//Check the card socket
checkSocket();
//Return the card type
return m_CardType;
}
bool SDFileSystem::crc()
{
//Return whether or not CRC is enabled
return m_Crc;
}
void SDFileSystem::crc(bool enabled)
{
//Check the card socket
checkSocket();
//Just update the member variable if the card isn't initialized
if (m_Status & STA_NOINIT) {
m_Crc = enabled;
return;
}
//Enable or disable CRC
if (enabled && !m_Crc) {
//Send CMD59(0x00000001) to enable CRC
m_Crc = true;
BSP_SD_CommandTransaction(CMD59, 0x00000001);
} else if (!enabled && m_Crc) {
//Send CMD59(0x00000000) to disableAPP/MBED/targets/hal/TARGET_STM/TARGET_STM32F7/TARGET_DISCO_F746NG CRC
BSP_SD_CommandTransaction(CMD59, 0x00000000);
m_Crc = false;
}
}
bool SDFileSystem::large_frames()
{
//Return whether or not 16-bit frames are enabled
return m_LargeFrames;
}
void SDFileSystem::large_frames(bool enabled)
{
//Set whether or not 16-bit frames are enabled
m_LargeFrames = enabled;
}
bool SDFileSystem::write_validation()
{
//Return whether or not write validation is enabled
return m_WriteValidation;
}
void SDFileSystem::write_validation(bool enabled)
{
//Set whether or not write validation is enabled
m_WriteValidation = enabled;
}
int SDFileSystem::unmount()
{
//Unmount the filesystem
FATFileSystem::unmount();
//Change the status to not initialized, and the card type to unknown
m_Status |= STA_NOINIT;
m_CardType = CARD_UNKNOWN;
//Always succeeds
return 0;
}
int SDFileSystem::disk_initialize()
{
//Make sure there's a card in the socket before proceeding
checkSocket();
if (m_Status & STA_NODISK)
return m_Status;
BSP_SD_GetCardInfo(&m_CardInfo);
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;
//Return the disk status
return m_Status;
}
int SDFileSystem::disk_status()
{
//Check the card socket
checkSocket();
//Return the disk status
return m_Status;
}
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;
__DSB();
__ISB();
while(BSP_SD_Get_Busy()==1){;}
BSP_SD_Set_Busy();
//Read a single block, or multiple blocks
if (count > 1) {
BSP_SD_Set_RX_Busy();
SCB_InvalidateDCache_by_Addr((uint32_t *)buffer,(512*count));
retval=BSP_SD_ReadBlocks_DMA((uint32_t *)buffer, (uint64_t) (sector * 512),512, count);
while((BSP_SD_Get_RX_Busy()==1)&&(retval==MSD_OK)){;}
CPU_CACHE_Flush((uint32_t *)buffer,(512*count));
BSP_SD_Clear_Busy();
return (retval ? RES_ERROR : RES_OK);
} else {
BSP_SD_Set_RX_Busy();
SCB_InvalidateDCache_by_Addr((uint32_t *)buffer,(512));
retval= BSP_SD_ReadBlocks_DMA((uint32_t *)buffer, (uint64_t) (sector * 512), 512, 1);
while((BSP_SD_Get_RX_Busy()==1)&&(retval==MSD_OK)){;}
CPU_CACHE_Flush((uint32_t *)buffer,(512));
BSP_SD_Clear_Busy();
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;
__DSB();
__ISB();
while(BSP_SD_Get_Busy()==1){;}
BSP_SD_Set_Busy();
//Make sure the card isn't write protected before proceeding
if (m_Status & STA_PROTECT)
{
BSP_SD_Clear_Busy();
return RES_WRPRT;
}
//Write a single block, or multiple blocks
if (count > 1) {
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)&&(retval==MSD_OK)){;}
BSP_SD_Clear_Busy();
return (retval? RES_ERROR : RES_OK);
} else {
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)&&(retval==MSD_OK)){;}
BSP_SD_Clear_Busy();
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
__DSB();
__ISB();
while(BSP_SD_Get_Busy()==1){;}
BSP_SD_Set_Busy();
while(BSP_SD_GetStatus()==SD_TRANSFER_BUSY){;}
if(BSP_SD_GetStatus()==SD_TRANSFER_OK)
{
BSP_SD_Clear_Busy();
return RES_OK;
} else {
BSP_SD_Clear_Busy();
return RES_ERROR;
}
}
uint32_t SDFileSystem::disk_sectors()
{
uint32_t sectors=0;
//Make sure the card is initialized before proceeding
if (m_Status & STA_NOINIT)
return 0;
__DSB();
__ISB();
while(BSP_SD_Get_Busy()==1){;}
BSP_SD_Set_Busy();
BSP_SD_GetCardInfo(&m_CardInfo);
sectors=m_CardInfo.CardCapacity>>9;
BSP_SD_Clear_Busy();
return sectors;
}
void SDFileSystem::onCardRemoval()
{
//Check the card socket
checkSocket();
}
inline void SDFileSystem::checkSocket()
{
//Use the card detect switch (if available) to determine if the socket is occupied
if (m_CdAssert != -1) {
if (m_Status & STA_NODISK) {
if (m_Cd == m_CdAssert) {
//The socket is now occupied
m_Status &= ~STA_NODISK;
m_CardType = CARD_UNKNOWN;
}
} else {
if (m_Cd != m_CdAssert) {
//The socket is now empty
m_Status |= (STA_NODISK | STA_NOINIT);
m_CardType = CARD_NONE;
}
}
}
}
/*interrupthandlers */
/**
* @brief This function handles DMA2 Stream 3 interrupt request.
* @param None
* @retval None
*/
void SDFileSystem::DMA2_Stream3_IRQHandler(void)
{
BSP_SD_DMA_Rx_IRQHandler();
BSP_SD_Clear_RX_Busy();
}
/**
* @brief This function handles DMA2 Stream 6 interrupt request.
* @param None
* @retval None
*/
void SDFileSystem::DMA2_Stream6_IRQHandler(void)
{
BSP_SD_DMA_Tx_IRQHandler();
BSP_SD_Clear_TX_Busy();
}
/**
* @brief This function handles SDIO interrupt request.
* @param None
* @retval None
*/
void SDFileSystem::SDMMC1_IRQHandler(void)
{
BSP_SD_IRQHandler();
}