⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fs_sdmmc_dev.c

📁 瑞星微公司RK27XX系列芯片的SDK开发包
💻 C
📖 第 1 页 / 共 3 页
字号:
/**********************************************************************************************
***********************************************************************************************
**   COPYRIGHT (c)   2004 BY ROCK-CHIP FUZHOU
**    --  ALL RIGHTS RESERVED  --
**
** File Name: fs_sdmmc_dev.c
** Author:  XUESHAN LIN
** Created:  29th SEP 2004
** Revision:  1.00
**
**-----------------------------------------------------------------------
** Modified:    Xiebangwang
** Description: 增加对Ver2.00 or later SD Memory Card 的兼容性,目前完全兼容MMC/SD/SDHC
** Revision: 2.00
** Date:  2008-02-16
**
**********************************************************************************************
**********************************************************************************************/
#include "arm.h"
#include "../inc/fs_comm.h"

#if defined(BOARD)
#if(SD_CARD_EN)


#define _IN_SD_
#include "fs_sdmmc_dev.h"

#define SDMMC_FAT_CACHE_COUNT       16
#define SDMMC_FDT_CACHE_COUNT       4
#define SDMMC_DATA_CACHE_COUNT      2

#define SD_DMA_TRAN_EN              0

#define READ_BLOCK_LEN_OFFSET       16
#define READ_BLOCK_LEN_MASK         0x000F0000
#define CSIZE_MULT_OFFSET           15
#define CSIZE_MULT_MASK             0x00038000

#define SDMMC_DATABUF_1_TX_WIDTH_MASK   0x3
#define SDMMC_DATABUF_2_TX_WIDTH_MASK   0x30
#define SDMMC_DATABUF_SWAP_MASK         0x300
#define SDMMC_MMU_SWAP_MASK             0x3FF


uint8 SdFatCacheBuf[SDMMC_FAT_CACHE_COUNT][512];
uint8 SdFdtCacheBuf[SDMMC_FDT_CACHE_COUNT][512];
uint8 SdDataCacheBuf[SDMMC_DATA_CACHE_COUNT][512];

FS_CACHE_DATA SD_FatCacheData[SDMMC_FAT_CACHE_COUNT];
FS_CACHE_DATA SD_FdtCacheData[SDMMC_FDT_CACHE_COUNT];
FS_CACHE_DATA SD_DataCacheData[SDMMC_DATA_CACHE_COUNT];

FS_CACHE    SdFatCache = {SD_FatCacheData, 0, SDMMC_FAT_CACHE_COUNT};
FS_CACHE    SdFdtCache = {SD_FdtCacheData, 0, SDMMC_FDT_CACHE_COUNT};
FS_CACHE    SdDataCache = {SD_DataCacheData, 0, SDMMC_DATA_CACHE_COUNT};

uint32 SDTotSec;     //SD卡总扇区数
uint32 SDBytsPerSec;     //SD卡每扇区字节数
uint32  SDCardInsert;     //SD卡每扇区字节数
uint32  SDCardChange;

uint32 SdmmcCardType;
uint32 SdmmcCardRca;
uint32 CardIntStatus;


uint32 MMC_Divider = 1;
uint32 SD_Divider = 0;
static uint32 prevMMC_Divider = 1;
static uint32 prevSD_Divider = 0;

int SdmmcGetStatus(void);
int SdmmcInit(void);
int SdmmcReadSec(uint32 LBA, uint32 SecCount, void *buf);
int SdmmcWriteSec(uint32 LBA, uint32 SecCount, void *buf);
int SdmmcIoCtl(uint32 cmd, uint32 arg, void *buf);
int SdmmcMediumInit(void);
int SdmmcReadMSecs(unsigned long LBA, unsigned int count, void *buf);
int Sdmmc_send_cmd(unsigned long cmd_abbr, unsigned long arg);
int SdmmcWriteMSecs(unsigned long LBA, unsigned int count, void *buf);
void SdmmcCacheInit(void);
int SdmmcChkInsert(void);
void SysSdmmcChkInsert(void* msg);

void  SdmmcSetFrequency(void);
int SdmmcInsertState(void);
int SdmmcChkBusy(void);


#define SDMMC_READ_BUF_COUNT    8

static uint32 SdmmcPrevPBA = 0xFFFFFFFF;
static uint32 SdmmcReadBuf[SDMMC_READ_BUF_COUNT][128];



const FS_DEVICE_TYPE FS_SdmmcDevice =
{
    "E:\\",
    "SD CARD",
    SdmmcGetStatus,
    SdmmcReadSec,
    SdmmcWriteSec,
    SdmmcIoCtl,
    SdmmcMediumInit,
    &SdFatCache,
    &SdFdtCache,
    &SdDataCache
};

void Sdmmc_delay(unsigned long count)
{
    int i;
    for (i = 0;i < count; i++)
    {
        ;
    }
}

/***************************************************************************
函数描述:延时
入口参数:
出口参数:
调用函数:
***************************************************************************/
void FS_Delay10cyc(uint32 count)
{
    uint16 i;

    while (count --)
        for (i = 0; i < 3; i++);
}

/*********************************************************************************
*  Copyright (C),2007, Fuzhou Rockchip Co.,Ltd.
*  Function name :  SdmmcIsr()
*  Author:          ZhenFu Fang
*  Description:     SD MMC 卡中断处理
*  Calls:
*  Input:
*  Return:
*  Remark:
*  History:
*           <author>      <time>              <version>       <desc>
*           FZF           2007-6-21 19:30      1.0              ORG
*
*********************************************************************************/
void SdmmcIsrProc(void)
{
    unsigned long rdata;

    rdata = ReadReg32(SDMMC_SD_INT);

    if (SDMMC_CMD_RESP_TX_INT_STAT_YES == (rdata & SDMMC_CMD_RESP_TX_INT_STAT_YES))
    {
        /* Clear corresponding interrupt flag */
        WriteReg32(SDMMC_SD_INT, (ReadReg32(SDMMC_SD_INT) & (~SDMMC_CMD_RESP_TX_INT_STAT_YES)));

        CardIntStatus |= CMD_RESP_INT;
    }

    if (SDMMC_DATA_TX_INT_STAT_YES == (rdata & SDMMC_DATA_TX_INT_STAT_YES))
    {
        /* Clear corresponding interrupt flag */
        WriteReg32(SDMMC_SD_INT, (ReadReg32(SDMMC_SD_INT) & (~SDMMC_DATA_TX_INT_STAT_YES)));
        CardIntStatus |= DATA_TX_INT;
    }

    if (SDMMC_HOST_CARD_DETECT_INT_STAT_YES == (rdata & SDMMC_HOST_CARD_DETECT_INT_STAT_YES))
    {
        //CardIntStatus |= CARD_DET_INT;
        CardIntStatus |= CARD_DET_INT;//modify by xbw @2008-02-16
        WriteReg32(SDMMC_SD_INT, ReadReg32(SDMMC_SD_INT) & (~SDMMC_HOST_CARD_DETECT_INT_STAT_YES));

        rdata = ReadReg32(SDMMC_SD_CARDA);
        if (rdata & SDMMC_CARD_DETECT_SIGNAL_HIGH)
        {
            SDCardInsert = FALSE;
            WriteReg32(SDMMC_SD_CARDA,
                       SDMMC_CARD_SEL_DIS |
                       SDMMC_CARD_POWER_CTRL_SIGNAL_DIS |
                       SDMMC_CARD_DETECT_INT_EN);
        }
        else
        {
            SDCardInsert = TRUE;
        }
    }

}

int SdmmcGetStatus(void)
{
    return(0);
}
int SdmmcIoCtl(uint32 cmd, uint32 arg, void *buf)
{
    uint32 *rbuf;
    rbuf = (uint32 *)buf;
    switch (cmd)
    {
        case IO_CTL_GET_CAPACITY:
            *rbuf = ((uint32)SDTotSec * SDBytsPerSec) >> 9;
            break;
        case IO_CTL_GET_MEDIUM_START_SEC:
            *rbuf = 0;
            break;
        case IO_CTL_GET_MEDIUM_STATUS:
            if (SdmmcChkInsert() == TRUE)
                *rbuf = MEDIUM_STATUS_RDY;
            else
                *rbuf = MEDIUM_STATUS_NOON;
            break;
        case IO_CTL_MEDIUM_CHANGE:
            SdmmcChkInsert();
            *rbuf = SDCardChange;
            SDCardChange = 0;
            break;
        case IO_CTL_FLUSH_CACHE:
            SdmmcCacheInit();
            break;
        default:
            break;
    }
    return(0);
}

void SdmmcCacheInit(void)
{
    uint32 i;
    FS_CACHE_DATA *pCache;

    pCache = SdFatCache.pCacheData;

    for (i = 0; i < SDMMC_FAT_CACHE_COUNT; i++)
    {
        pCache->flag     = 0;
        pCache->pBuffer  = &SdFatCacheBuf[i][0];
        pCache->SectorNo = 0xFFFFFFFF;
        pCache++;
    }

    pCache = SdFdtCache.pCacheData;

    for (i = 0; i < SDMMC_FDT_CACHE_COUNT; i++)
    {
        pCache->flag     = 0;
        pCache->pBuffer  = &SdFdtCacheBuf[i][0];
        pCache->SectorNo = 0xFFFFFFFF;
        pCache++;
    }

    pCache = SdDataCache.pCacheData;

    for (i = 0; i < SDMMC_DATA_CACHE_COUNT; i++)
    {
        pCache->flag     = 0;
        pCache->pBuffer  = &SdDataCacheBuf[i][0];
        pCache->SectorNo = 0xFFFFFFFF;
        pCache++;
    }
}

int SdmmcMediumInit(void)
{
    int err;

    IOMUX_SetSDPort(SD_SD_TYPE);
    SdmmcCacheInit();
    err = SdmmcInit();

    if (err != SUCCEED)
    {
        Scu_ClockDisable(SDMMC_CLOCK);
    }

    SDCardChange = 0;
    return(err);
}

/*******************************************************************************************
*函数描述:读SD卡CSD数据
*入口参数:无
*出口参数:buf=数据指针
*调用函数:无
* History:
*         <author>      <time>              <version>       <desc>
*          LXS,FZF                             1.0          适用于 SD Memory Card Ver1.0
*
*         Xiebangwang   2008-2-18              2.0          增加对SDHC的兼容
*
*********************************************************************************************/
void SdmmcReadCsd(unsigned long *buf)
{
    uint32 c_size_mult;
    uint32 mult;
    if (SUCCEED == Sdmmc_send_cmd(MMC_SEND_CSD, SdmmcCardRca))
    {
#if (SDMMC_ISR_PROC_EN == 0)
        Sdmmc_delay(10000);
#endif

        buf[3] = ReadReg32(SDMMC_SD_RESA3);
        buf[2] = ReadReg32(SDMMC_SD_RESA2);
        buf[1] = ReadReg32(SDMMC_SD_RESA1);
        buf[0] = ReadReg32(SDMMC_SD_RESA0);

        if (SdmmcCardType == HC_SD_CARD)
        {
            //计算SDHC 卡容量块长度和总块数
            SDBytsPerSec = 512;
            SDTotSec  = (((buf[1] & 0xffff0000)  >> 16) + 1) << 10;
        }
        else
        {
            //计算SD/MMC卡的块长度和总块数
            SDBytsPerSec = 1 << ((buf[2] & READ_BLOCK_LEN_MASK) >> READ_BLOCK_LEN_OFFSET);
            c_size_mult  = (buf[1] & CSIZE_MULT_MASK) >> CSIZE_MULT_OFFSET;
            mult   = 1 << (c_size_mult + 2);
            SDTotSec  = (((buf[2] & 0x3ff) << 2) + ((buf[1] & 0xc0000000) >> 30) + 1) * mult;
        }

    }
}


/**********************************************************************************************************
*函数描述:SD卡动态检测
*入口参数:无
*出口参数:SUCCEED成功, 其它值为失败
*调用函数:
* History:
*         <author>      <time>              <version>       <desc>
*          LXS,FZF                             1.0          插卡开机,静态检测卡。
*
*         Xiebangwang   2007-12-15             1.1          增加SD卡动态检测
*
*         Xiebangwang   2008-01-25             1.2          修改SD卡动态检测机制,改为加载与初始化分开
*
**********************************************************************************************************/
int SdmmcChkInsert(void)
{
    uint32 rdata;
    uint32 InsertState;
    FS_VOLUME *pVolume;

    rdata = GPIO_GetPinLevel(SD_DETECT_PIN);
    pVolume = (FS_VOLUME *)(FS_FindDeviceName(&FS_SdmmcDevice));  // 获取卷信息

#if (SDCheckInsetLevel == 0)
    if (rdata == 1)
#else
    if (rdata == 0)
#endif
    {
        InsertState = FALSE;
        SDTotSec = 0;
        pVolume->FatInfo.Valid = 0; //若SD卡拔出,把fatInfo标志请零

        //关闭SD卡Clock
        Scu_ClockDisable(SDMMC_CLOCK);
    }
    else
    {
        InsertState = TRUE;
    }

    if (InsertState != SDCardInsert)
    {
        SDCardInsert = InsertState;
        if (InsertState == TRUE)
        {
            SdmmcMediumInit();
            pVolume->FatInfo.Valid = 1;//若SD插入,把fatInfo标志设置为1
        }

        SDCardChange = 1;
    }

    return(SDCardInsert);
}


/***************************************************************************
函数描述:使用IO口(PA7),中断检测,对SD卡进行动态检测
入口参数:无
出口参数:SUCCEED成功, 其它值为失败
调用函数:
***************************************************************************/
void SysSdmmcChkInsert(void* msg)
{
    SdmmcChkInsert();
}


/*********************************************************************************************************
*函数描述:SD Memory Card初始化
*入口参数:无
*出口参数: 0--初始化成功; 1--失败
*调用函数:Scu_ModuleReset, Scu_ClockEnable, Sdmmc_delay , GPIO_SetPinDirection, GPIO_GetPinLevel,
          WriteReg32, ReadReg32 Sdmmc_send_cmd
*
* History:
*         <author>      <time>              <version>       <desc>
*          LXS,FZF                             1.0          适用于 SD Memory Card Ver1.0
*
*         Xiebangwang   2008-01-25             1.1          修改命令、响应以及数据三者间的延时长度
*
*         Xiebangwang   2008-02-18             2.0          增加对Ver2.00 or later SD Memory Card的兼容
*
*********************************************************************************************************/
int SdmmcInit(void)
{
    int i;
    unsigned long rdata;
    unsigned long error;
    unsigned long SdCsd[4];

    UINT32 freq;
    UINT32 identify_divider;

    Scu_ModuleReset(SDMMC_RESET, TRUE);
    Sdmmc_delay(100);//10000
    Scu_ModuleReset(SDMMC_RESET, FALSE);

    Scu_ClockEnable(SDMMC_CLOCK);

    SdmmcPrevPBA = 0xFFFFFFFF;

#if (SDMMC_ISR_PROC_EN == 0)
    Sdmmc_delay(100);
#endif


    GPIO_SetPinDirection(SD_DETECT_PIN, GPIO_IN);

    rdata = GPIO_GetPinLevel(SD_DETECT_PIN);

#if (SDCheckInsetLevel == 0)
    if (rdata == 1)
#else
    if (rdata == 0)
#endif
    {
        SDCardInsert = FALSE;
        return(1);
    }
    else
    {
        SDCardInsert = TRUE;
    }

    freq = Pll_get_apb_freq();
    if (freq >= 60000)
    {
        identify_divider = 0xA6; //最高66Mhz
    }
    else if (freq >= 50000)
    {
        identify_divider = 0x96;
    }
    else if (freq >= 30000)
    {
        identify_divider = 0x80;
    }
    else
    {
        identify_divider = 0x50;
    }

    WriteReg32(SDMMC_SD_CTRL, (SDMMC_CARD_POWER_CTRL_CPU |
                               SDMMC_CARD_DETECT_FUNC_MECH |
                               SDMMC_CARD_CLK_RUN |
                               SDMMC_CARD_CLK_DIVIDER(identify_divider))); //the frequency range of 100KHz-400KHz

    WriteReg32(SDMMC_SD_CARDA, (SDMMC_CARD_SEL_EN |
                                SDMMC_CARD_POWER_CTRL_SIGNAL_EN |
                                SDMMC_CARD_DETECT_INT_EN));

    WriteReg32(SDMMC_SD_INT, (SDMMC_CMD_RESP_TX_INT_STAT_NO |
                              SDMMC_DATA_TX_INT_STAT_NO |
                              SDMMC_HOST_CARD_DETECT_INT_STAT_NO |
                              SDMMC_CMD_RESP_TX_INT_EN |
                              SDMMC_DATA_TX_INT_EN |
                              SDMMC_HOST_CARD_DETECT_INT_EN));

    /* Delay */
#if (SDMMC_ISR_PROC_EN == 0)
    Sdmmc_delay(100);
#endif

    //确保使用CMD8前,卡处于Idle state
    if (Sdmmc_send_cmd(MMC_GO_IDLE_STATE, 0x0000))
        return (111);

#if (SDMMC_ISR_PROC_EN == 0)
    Sdmmc_delay(100);
#endif

    /***********************************************************************************************/
    /*1. Ver2.00 or later SD Memory Card*/

    /* Send CMD8 to check High Capacity SD CARD */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -