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

📄 fs_sdmmc_dev.c

📁 瑞星微公司RK27XX系列芯片的SDK开发包
💻 C
📖 第 1 页 / 共 3 页
字号:
    if (Sdmmc_send_cmd(SD_HC_SEND_IF_COND, 0x1aa) == 0)
    {
        rdata = ReadReg32(SDMMC_SD_RESA3);
        if ((rdata & 0x1aa) == 0x1aa)
        {
            for (i = 0;i < 1500;i++)
            {
                if ((error = Sdmmc_send_cmd(MMC_APP_CMD, 0x0)) != 0)  // CMD55(), Make ACMD
                {
                    if (SDMMC_CARD_RESP_TO_ERR == (error & SDMMC_CARD_RESP_TO_ERR))
                    {
                        goto MMC_IDENTIFICATION;
                    }
                    else
                    {
                        return (1);
                    }
                }

                if (Sdmmc_send_cmd(SD_APP_OP_COND, 0x40ff8000) != 0) // ACMD41
                {
                    return (2);
                }
                rdata = ReadReg32(SDMMC_SD_RESA3);
                if (rdata == 0xc0ff8000)
                {
                    SdmmcCardType = HC_SD_CARD; // Ver2.00 or later High Capacity SD Memory Card
                    goto IDENTITY_END;
                }
                else if (rdata == 0x80ff8000)
                {
                    SdmmcCardType = SD_CARD;  // Ver2.00 or later Standard Capacity SD Memory Card
                    goto IDENTITY_END;
                }

#if (SDMMC_ISR_PROC_EN == 0)
                Sdmmc_delay(100);
#endif
            }
            return (110);
        }
        else
        {
            SDCardInsert = FALSE;
            return 112;  // SDHC卡,但是硬件上电压不对,不是2.7-3.6V ;Added by xbw@2008-07-17
       	}
    }

    /***********************************************************************************************/
    /*2. Ver1.X SD Memory card*/
    i = 0;
    do
    {
#if (SDMMC_ISR_PROC_EN == 0)
        Sdmmc_delay(100);//10000
#endif
        if (i++ > 1000000)
        {
            return (2008); //SD Identity time out; added by xbw@2008-07-17
        }

        /* Send CMD55 */
        if ((error = Sdmmc_send_cmd(MMC_APP_CMD, 0x0)) != 0)
        {
            if (SDMMC_CARD_RESP_TO_ERR == (error & SDMMC_CARD_RESP_TO_ERR))
            {
                goto MMC_IDENTIFICATION;
            }
            else
            {
                return (1);
            }
        }

        /* Send ACMD41, host support VDD voltage is 0x00ff8000 */
        if (Sdmmc_send_cmd(SD_APP_OP_COND, 0x00ff8000))
            return (2);
        rdata = ReadReg32(SDMMC_SD_RESA3);
    }
    while (!(rdata & 0x80000000));
    SdmmcCardType = SD_CARD;
    goto IDENTITY_END;

    /***********************************************************************************************/
    /*3. MMC card*/

MMC_IDENTIFICATION:    //MMC 卡
    i = 0;
    do
    {
        if (i++ > 1000000)
        {
            return (3); //MMC Identity time out;
        }

        if (Sdmmc_send_cmd(MMC_SEND_OP_COND, 0x00ff8000))
            return (4);
        rdata = ReadReg32(SDMMC_SD_RESA3);
    }
    while (!(rdata & 0x80000000));
    SdmmcCardType = MMC_CARD;

IDENTITY_END:
    /* Send CMD2 */
    if (Sdmmc_send_cmd(MMC_ALL_SEND_CID, 0x00000000))
        return (5);


    /*动态改变SD/mmc的频率*/
    freq = Pll_get_apb_freq();
    if (freq <= 40000)
    {
        MMC_Divider = 0;
        SD_Divider  = 0;
    }
    else if (freq < 51000)
    {
        MMC_Divider = 1;
        SD_Divider  = 0;
    }
    else
    {
        MMC_Divider = 1;
        SD_Divider  = 1;
    }


    if (SdmmcCardType != MMC_CARD)
    {
        /* Send CMD3 */
        rdata = Sdmmc_send_cmd(MMC_SET_RELATIVE_ADDR, 0x00000000);
        if (rdata)
            return (6);

        /* Get card's relative address (RCA) */
        SdmmcCardRca = ReadReg32(SDMMC_SD_RESA3) & 0xffff0000;

        /* Change clock rate to enter the data transfer mode */
        WriteReg32(SDMMC_SD_CTRL,
                   SDMMC_CARD_POWER_CTRL_CPU |
                   SDMMC_CARD_DETECT_FUNC_MECH |
                   SDMMC_CARD_CLK_RUN |
                   SDMMC_CARD_CLK_DIVIDER(SD_Divider));
    }
    else
    {
        /* Send CMD3 */
        if (Sdmmc_send_cmd(MMC_SET_RELATIVE_ADDR, 0x00010000))
            return (61);

        /* Get MMC card's relative address (RCA) */
        SdmmcCardRca = 0x00010000;

        /* Change clock rate to enter the data transfer mode */
        WriteReg32(SDMMC_SD_CTRL,
                   SDMMC_CARD_POWER_CTRL_CPU |
                   SDMMC_CARD_DETECT_FUNC_MECH |
                   SDMMC_CARD_CLK_RUN |
                   SDMMC_CARD_CLK_DIVIDER(MMC_Divider));
    }

    // 2^(CLK_DIV+1)
    Sdmmc_delay(200); //2000
    SdmmcReadCsd(SdCsd);


#if 1
    /* Send CMD7 */
    if (Sdmmc_send_cmd(MMC_SELECT_CARD, SdmmcCardRca))
        return (7);

    /* Send CMD16 to set the block length */
    if (Sdmmc_send_cmd(MMC_SET_BLOCKLEN, 512))
        return (8);

    /* Initialize the MMU buffer pointer */
    WriteReg32(SDMMC_MMU_PNRI,  0x000001ff);
    WriteReg32(SDMMC_MMU_PNRII, 0x000001ff);
#endif
    if (MMC_CARD != SdmmcCardType)
    {
        /* Send CMD55 to indicate that the next command is an application specific command */
        if (Sdmmc_send_cmd(MMC_APP_CMD, SdmmcCardRca))
            return (9);

        /* Send ACMD6 to select given bus width */
        if (Sdmmc_send_cmd(SD_APP_SET_BUS_WIDTH, SD_BUS_WIDTH_1))
            return (11);
        WriteReg32(SDMMC_MMU_CTRL, SDMMC_MMU_DATA_WIDTH_WORD);
    }

    return SUCCEED;
}


void Sdmmc_mmu_swap(void)
{
    unsigned long val;
    unsigned long databuf_swap_val;
    unsigned long buf_2_tx_width;
    unsigned long buf_1_tx_width;

    val = ReadReg32(SDMMC_MMU_CTRL);

    databuf_swap_val = (val & SDMMC_DATABUF_SWAP_MASK) ^ SDMMC_DATABUF_SWAP_MASK;
    buf_1_tx_width = (val & SDMMC_DATABUF_2_TX_WIDTH_MASK) >> 4;
    buf_2_tx_width = (val & SDMMC_DATABUF_1_TX_WIDTH_MASK) << 4;
    val &= ~SDMMC_MMU_SWAP_MASK;
    //val |= SDMMC_BIG_ENDIAN_ACCESS;
    WriteReg32(SDMMC_MMU_CTRL,
               val |
               databuf_swap_val |
               SDMMC_DATABUF_2_POINTER_RST |
               SDMMC_DATABUF_2_POINTER_END_SIGNAL_LOW |
               buf_2_tx_width |
               SDMMC_DATABUF_1_POINTER_RST |
               SDMMC_DATABUF_1_POINTER_END_SIGNAL_LOW |
               buf_1_tx_width);
}

int Sdmmc_data_transfer_end(void)
{
    uint32 rdata = 0;
    uint32 Sdmmc_to_cnt;

    Sdmmc_to_cnt = 0;
#if (SDMMC_ISR_PROC_EN == 0)
    while (ReadReg32(SDMMC_SD_DATAT) & SDMMC_DATA_TX_SIGNAL_BEGIN)
    {

        if (ReadReg32(SDMMC_SD_DATAT) & SDMMC_DATA_TX_TO_ERR)
        {
            return -1;  // time out; moidified by XBW at 2008-02-20
        }

        if (Sdmmc_to_cnt > 0x1000000)
        {
            return -1; //time out
        }
        Sdmmc_to_cnt++;
    }
    Sdmmc_to_cnt = 0;

#if 0
    while (0 == (DATA_TX_INT & ReadReg32(SDMMC_SD_INT)))
    {
// while (SDMMC_DATA_TX_INT_STAT_YES != (SDMMC_DATA_TX_INT_STAT_YES & ReadReg32(SDMMC_SD_INT)))  {
        if (Sdmmc_to_cnt > 10000000)
        {
            //printf("Socle SD/MMC: data transfer is timeout\n");
            return -1;
        }
        Sdmmc_to_cnt++;
    }
#endif

    WriteReg32(SDMMC_SD_INT, (ReadReg32(SDMMC_SD_INT) & (~SDMMC_DATA_TX_INT_STAT_YES)));

#else
    while (0 == (DATA_TX_INT & CardIntStatus))
    {
        if (Sdmmc_to_cnt > 10000000)
        {
            return -1;
        }
        Sdmmc_to_cnt++;
    }
    CardIntStatus &= ~DATA_TX_INT;
#endif

#if 1

    rdata = ReadReg32(SDMMC_SD_DATAT);
    if (SDMMC_DATA_TX_STAT_ERR == (rdata & SDMMC_DATA_TX_STAT_ERR))
    {
        return ReadReg32(SDMMC_SD_DATAT);
    }

#endif
    return 0;
}



/**********************************************************************************************
函数描述:读SD卡数据(16bit)
入口参数:行地址,列地址,数据缓冲区,长度,宽度
出口参数:ERROR错误, SUCCEED正确
调用函数:
* History:
*         <author>      <time>              <version>       <desc>
*          LXS,FZF                             1.0
*
*         Xiebangwang   2008-03-28             2.0          按簇读卡上文件,修改cache管理方式
*
************************************************************************************************/
int SdmmcReadSec(uint32 LBA, uint32 SecCount, void *buf)
{
    int result = 0;

    if (((LBA&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))) == (SdmmcPrevPBA&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))))
            && (((LBA + SecCount - 1)&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))) == (SdmmcPrevPBA&(~(uint32)(SDMMC_READ_BUF_COUNT - 1)))))
    {
        //read data from cache
        memcpy(buf, &SdmmcReadBuf[LBA-SdmmcPrevPBA][0], SecCount << 9);

    }
    else
    {
        uint32 Start, Nums, Direction = 0;  //Direction=0表示正方向读,Direction=1表示反方向读
        if ((LBA&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))) == (SdmmcPrevPBA&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))))
        {
            //首扇区在cache,尾扇区不在cache,先从cache中读部分数据
            Nums = SDMMC_READ_BUF_COUNT - (LBA - SdmmcPrevPBA);
            memcpy(buf, &SdmmcReadBuf[LBA-SdmmcPrevPBA][0], Nums << 9);
            SecCount = SecCount - Nums;
            LBA = LBA + Nums;
            buf = (void *)((uint32)buf + (Nums << 9));
        }
        else if (((LBA + SecCount - 1)&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))) == (SdmmcPrevPBA&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))))
        {
            //首扇区不在cache,尾扇区在cache,先从cache中读部分数据,反方向读
            Start = (LBA + SecCount - 1) & (~(uint32)(SDMMC_READ_BUF_COUNT - 1));
            Nums = LBA + SecCount - Start;
            memcpy((void *)((uint32)buf + ((SecCount - Nums) << 9)), SdmmcReadBuf, Nums << 9);
            LBA = LBA - Nums;
            Direction = 1;
        }
        //当前LBA和LBA+SecCount-1都不在cache
        if ((LBA&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))) == ((LBA + SecCount - 1)&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))))
        {
            //要读的数据在同一个cache范围内
            if (OK == SdmmcReadMSecs((LBA&(~(uint32)(SDMMC_READ_BUF_COUNT - 1))), SDMMC_READ_BUF_COUNT, SdmmcReadBuf))
            {
                memcpy(buf, &SdmmcReadBuf[LBA&(SDMMC_READ_BUF_COUNT-1)][0], SecCount << 9);
                SdmmcPrevPBA = (LBA & (~(uint32)(SDMMC_READ_BUF_COUNT - 1)));
            }
            else
            {
                result = -1;
            }
        }
        else
        {
            //不在同一个cache范围内,先直接读SecCount个扇区
            if (OK == SdmmcReadMSecs(LBA, SecCount, buf))
            {
                Start = (LBA + SecCount) & (~(uint32)(SDMMC_READ_BUF_COUNT - 1));
                if ((Direction == 0) && ((Start + SDMMC_READ_BUF_COUNT) < SDTotSec))
                {
                    //正方向读,用(LBA+SecCount ) & (~(uint32)(SDMMC_READ_BUF_COUNT-1))开始的8扇区填充cache
                    Nums = LBA + SecCount - Start;  //在buf中的扇区数
                    // 从卡上读扇区
                    if (OK == SdmmcReadMSecs(LBA + SecCount, SDMMC_READ_BUF_COUNT - Nums, &SdmmcReadBuf[Nums][0]))
                    {
                        //用buf中的部分扇区填充
                        memcpy(SdmmcReadBuf, (void *)((uint32)buf + ((SecCount - Nums) << 9)), Nums << 9);
                        SdmmcPrevPBA = Start;
                    }
                }
                else if ((Direction == 1) && (LBA != 0))
                {
                    //反方向读,用(LBA -1) & (~(uint32)(SDMMC_READ_BUF_COUNT-1))开始的8扇区填充cache
                    //先用buf中的部分扇区填充
                    Start = (LBA - 1) & (~(uint32)(SDMMC_READ_BUF_COUNT - 1));
                    Nums = SDMMC_READ_BUF_COUNT - (LBA - Start); //在buf中的扇区数
                    // 从卡上读扇区
                    if (OK == SdmmcReadMSecs(Start, SDMMC_READ_BUF_COUNT - Nums, SdmmcReadBuf))
                    {
                        memcpy(&SdmmcReadBuf[SDMMC_READ_BUF_COUNT-Nums][0], buf, Nums << 9);
                        SdmmcPrevPBA = Start;
                    }
                }
            }
            else
            {
                result = -1;
            }
        }
    }

    return result;
}

/***************************************************************************
函数描述:写SD卡数据(16bit)
入口参数:行地址,列地址,数据缓冲区,长度,宽度
出口参数:ERROR错误, SUCCEED正确
调用函数:
注:目前 SecCount 只能为 1
***************************************************************************/
int SdmmcWriteSec(uint32 LBA, uint32 SecCount, void *buf)
{
    if ((LBA & (~(uint32)(SDMMC_READ_BUF_COUNT - 1))) == (SdmmcPrevPBA & (~(uint32)(SDMMC_READ_BUF_COUNT - 1))))
    {
        memcpy(&SdmmcReadBuf[LBA-SdmmcPrevPBA][0], buf, SecCount*512);
    }

    SdmmcWriteMSecs(LBA, SecCount, buf);
    return(0);
}

/********************************************************************************************************
* 函数名称: FS_sdmmc_send_cmd()
* 功能描述: sd mmc 卡命令发送
* 输   入: cmd_index: sd mmc 卡命令(参考相关的文档)
*           cmd_arg:   sd mmc 命令参数
* 输   出: 设备出错返回0
* 全局变量: ATA[THIS_DEVICE].ERRCODE,出错代码
*       ATA[THIS_DEVICE].ERRSECTOR,出错扇区号
* 调用模块: ATA_GetStatus(),读取状态函数
*
* History:
*         <author>      <time>              <version>       <desc>
*          LXS,FZF                             1.0          适用于 Specification Ver1.0 SD Memory Card
*
*         Xiebangwang   2008-02-18             2.0          增加对Ver2.00 or later SD Memory Card的兼容
*
**********************************************************************************************************/
int Sdmmc_send_cmd(unsigned long cmd_abbr, unsigned long arg)
{
    unsigned long rdata;
    unsigned long resp_tx_type;
    unsigned long Sdmmc_to_cnt;
    int no_resp = 0;

    switch (cmd_abbr)
    {
        case MMC_WRITE_SINGLE_BLOCK:
        case MMC_READ_SINGLE_BLOCK:
        case MMC_READ_MULTIPLE_BLOCK:
        case MMC_WRITE_MULTIPLE_BLOCK:

        case SD_SET_WR_BLK_ERASE_COUNT:

        case MMC_APP_CMD:
        case SD_APP_SET_BUS_WIDTH:
        case SD_APP_SEND_SCR:
        case MMC_SET_BLOCKLEN:
        case MMC_SEND_STATUS:
        case SD_ERASE_WR_BLK_START:
        case SD_ERASE_WR_BLK_END:
            resp_tx_type = SDMMC_RESP_TX_TYPE_R1;
            break;
        case MMC_SELECT_CARD:
        case MMC_STOP_TRANSMISSION:
        case MMC_SET_WRITE_PROT:
        case MMC_CLR_WRITE_PROT:
        case MMC_ERASE:
            resp_tx_type = SDMMC_RESP_TX_TYPE_R1B;
            break;
        case MMC_ALL_SEND_CID:
        case MMC_SEND_CSD:
        case MMC_SEND_CID:
            resp_tx_type = SDMMC_RESP_TX_TYPE_R2;
            break;
        case MMC_SEND_OP_COND:
        case SD_APP_OP_COND:
            resp_tx_type = SDMMC_RESP_TX_TYPE_R3;
            break;
        case MMC_SET_RELATIVE_ADDR:
            resp_tx_type = SDMMC_RESP_TX_TYPE_R6;
            break;

            /* CMD8 is definded to initialize SD Memory Cards compliant to Spec. Ver2.00 */
        case SD_HC_SEND_IF_COND:
            resp_tx_type = SDMMC_RESP_TX_TYPE_R7;
            break;

        case MMC_GO_IDLE_STATE:
        case MMC_GO_INACTIVE_STATE:
            no_resp = 1;
            break;
        default:
            //goto undefined_cmd;
            return -1;
    }

    WriteReg32(SDMMC_SD_CMD, arg);

    if (no_resp)
        WriteReg32(SDMMC_SD_CMDREST,
                   SDMMC_CMD_TX_SIGNAL_BEGIN |
                   SDMMC_RESP_TX_SIGNAL_END |
                   SDMMC_RESP_TX_TYPE_R1 |
                   SDMMC_CMD_RESP_TX_STAT_N_ERR |
                   SDMMC_CMD_INDEX(cmd_abbr));
    else
        WriteReg32(SDMMC_SD_CMDREST,
                   SDMMC_CMD_TX_SIGNAL_BEGIN |
                   SDMMC_RESP_TX_SIGNAL_BEGIN |
                   resp_tx_type |
                   SDMMC_CMD_RESP_TX_STAT_N_ERR |
                   SDMMC_CMD_INDEX(cmd_abbr));

    /* Do command transfer checking process */
    Sdmmc_to_cnt = 0;
#if (SDMMC_ISR_PROC_EN == 0)
    while (ReadReg32(SDMMC_SD_CMDRESA) & 0x0180)
    {
        if (Sdmmc_to_cnt > 0x1000000)
        {
            return -1;
        }

⌨️ 快捷键说明

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