This demo reads a bitmap from a FAT formatted SD-card, copies it to flash and displays it on the screen. The demo is based on the following project: https://os.mbed.com/users/DieterGraef/code/DISCO-F746NG_SDFileSystem/

Dependencies:   LCD_DISCO_F746NG TS_DISCO_F746NG mbed FATFileSystem

Fork of DISCO-F746NG_SDFileSystem by Dieter Graef

SDFileSystem/SDFileSystem.cpp

Committer:
Lightsource
Date:
2018-04-19
Revision:
4:95e30a911d97

File content as of revision 4:95e30a911d97:

/* 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();
}