📄 fs_sdmmc_dev.c
字号:
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 + -