📄 mc_operations.c
字号:
#include "config.h"
const UWORD32 time_unit[8] = {1000000000,100000000,10000000,/* 超时时间单位表(单位:0.000000001ns) */
1000000,100000,10000,1000,100};
const UWORD8 time_value[16] = {0,10,12,13,15,20,25,30, /* 超时时间表 */
35,40,45,50,55,60,70,80};
const UWORD8 r2w_fator[8] = {1,2,4,8,16,32,64,128}; /* 超时时间因数表 */
/*********************************************************************************************************
** 函数名称: mc_hadware_init
** 功能描述: MMC/SD硬件接口初始化
**
** 参 数: None
**
** 返 回 值: None
**
** 作 者: 罗辉联
** 日 期: 2006年6月29日
**-------------------------------------------------------------------------------------------------------
** 修 改 人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
void mc_hadware_init(void)
{
MC_WRITE_PROTECTED_CFG(); /* 配置MC的WP管脚GPIO1_14为输入模式 */
MC_CARD_INSERTED_CFG(); /* 配置MC的INSERT管脚GPIO1_15为输入模式 */
MC_MISO_PIN_CONFIG(); /* 配置SPI接口 */
MC_MISO_PIN_LOW();
MC_MOSI_PIN_CONFIG();
MC_MOSI_PIN_LOW();
MC_SCLK_PIN_CONFIG();
MC_SCLK_PIN_LOW();
MC_CS_CFG(); /* 配置MC的CS管脚为推拉输出 */
MC_CLK_400K(); /* 配置BSPI波特率为400k */
mc_port_init(); /* 初始化SPI接口 */
}
/*********************************************************************************************************
** 函数名称: mc_software_active
** 功能描述: MMC/SD软件激活
**
** 参 数: None
**
** 返 回 值: error type
**
** 作 者: 罗辉联
** 日 期: 2006年6月29日
**-------------------------------------------------------------------------------------------------------
** 修 改 人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
UWORD8 mc_software_active(void)
{
UWORD8 param[4] = {0,0,0,0},resp[5] = {0,0,0,0,0},ret = 0;
UWORD32 i = 0;
do
{ /* 发出CMD1, 查询卡的状态 */
ret = mc_send_command(CMD1, param, CMD1_R, resp);
if (ret != MC_SUCCESS)
{
MC_SEND_TRACE("mc_send_command CMD1 return value fail: %d", ret);
goto MC_SOFTWARE_ACTIVE_END;
}
// else
;//MC_SEND_TRACE("mc_send_command CMD1 return value success, CMD1 send times:%d ", i);
i ++;
/* 如果响应R1的最低位Idle位为1,则继续循环 */
}while (((resp[0] & MSK_IDLE) == MSK_IDLE) && (i <= MC_IDLE_WAIT_MAX));
if (i >= MC_IDLE_WAIT_MAX)
{
MC_SEND_TRACE("CMD1 resposne timeout error: %d", i);
ret = MC_ERR_TIMEOUT_WAITIDLE; /* 超时,返回错误 */
goto MC_SOFTWARE_ACTIVE_END;
}
ret = mc_send_command(CMD55, param, CMD55_R, resp); /* 通知SD/MMC下面将发送应用命令*/
if (ret != MC_SUCCESS)
goto MC_SOFTWARE_ACTIVE_END;
ret = mc_send_command(ACMD41, param, ACMD41_R, resp); /* 激活内部初始化命令 */
if (ret != MC_SUCCESS)
{
MC_SEND_TRACE("CMD41 resposne value: %d", ret);
ret = MC_ERR_UNKNOWN_CARD;
goto MC_SOFTWARE_ACTIVE_END;
}
if ((resp[0] & 0xFE) == 0)
{
mc_info.card_type = SD_CARD; /* 是SD卡 */
}
else
{
mc_info.card_type = MMC_CARD; /* 是MMC卡 */
}
MC_SOFTWARE_ACTIVE_END:
MC_SEND_TRACE("mc_software_active return value: %d", ret);
return ret;
}
/*********************************************************************************************************
** 函数名称: mc_cal_time_out
** 功能描述: MMC/SD操作超时计算
**
** 参 数: None
**
** 返 回 值: error type
**
** 作 者: 罗辉联
** 日 期: 2006年6月29日
**-------------------------------------------------------------------------------------------------------
** 修 改 人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
MC_RESULT_T mc_cal_time_out(UWORD8 *csdbuf)
{
UWORD32 tmp;
UWORD8 time_u,time_v,fator;
mc_info.timeout_read = READ_TIMEOUT_100MS; /* 默认读超时为100ms */
mc_info.timeout_write = WRITE_TIMEOUT_250MS; /* 默认写超时为250ms */
mc_info.timeout_erase = WRITE_TIMEOUT_250MS;
time_u = (csdbuf[TAAC_POS] & TAAC_MSK); /* 读超时时间单位 */
time_v = (csdbuf[TAAC_POS] & NSAC_MSK) >> 3; /* 读超时时间值 */
fator = (csdbuf[R2WFACTOR_POS] & R2WFACTOR_MSK) >> 2; /* 读超时时间因数 */
if(time_v == 0)
return MC_ERR_CARD_PARAM; /* 卡参数有错误 */
tmp = SPI_CLOCK * time_value[time_v] / 10 / time_unit[time_u]; /* TACC * f (单位 unit: clock) */
tmp = tmp + csdbuf[NSAC_POS] * 100; /* TACC * f + NSAC * 100 (单位 unit: clock) */
/* 计算得到的超时值 */
mc_info.timeout_read = tmp;
mc_info.timeout_write = tmp * r2w_fator[fator]; /* (TACC * f + NSAC * 100) * R2WFACTOR (单位 unit:clock)*/
if (mc_info.card_type == SD_CARD)
{
mc_info.timeout_read = mc_info.timeout_read * 100 / 8; /* 实际值为计算值的100倍 */
mc_info.timeout_write = mc_info.timeout_write * 100 / 8;
if (mc_info.timeout_read > READ_TIMEOUT_100MS) /* 取计算值与默认值中的最小值 */
mc_info.timeout_read = READ_TIMEOUT_100MS;
if (mc_info.timeout_write > WRITE_TIMEOUT_250MS)
mc_info.timeout_write = WRITE_TIMEOUT_250MS;
}
else
{
mc_info.timeout_read = mc_info.timeout_read * 10 / 8; /* 实际值为计算值的10倍 */
mc_info.timeout_write = mc_info.timeout_write * 10 / 8;
}
mc_info.timeout_erase = mc_info.timeout_write;
return MC_SUCCESS;
}
/*********************************************************************************************************
** 函数名称: mc_get_card_info
** 功能描述: 获得MMC/SD相关信息
**
** 参 数: None
**
** 返 回 值: error type
**
** 作 者: 罗辉联
** 日 期: 2006年6月29日
**-------------------------------------------------------------------------------------------------------
** 修 改 人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
MC_RESULT_T mc_get_card_info(void)
{
UWORD32 tmp;
UWORD8 csdbuf[16],ret;
ret = mc_read_csd(16, csdbuf); /* 读CSD寄存器 */
if (ret != MC_SUCCESS)
return ret;
mc_cal_time_out(csdbuf); /* 计算超时时间值 */
mc_info.block_len = 1 << (csdbuf[READ_BL_LEN_POS] & READ_BL_LEN_MSK);/* 计算块的最大长度 */
/* 计算卡中块的个数 */
mc_info.block_num = ((csdbuf[C_SIZE_POS1] & C_SIZE_MSK1) << 10) +
(csdbuf[C_SIZE_POS2] << 2) +
((csdbuf[C_SIZE_POS3] & C_SIZE_MSK3) >> 6) + 1; /* (C_SIZE + 1)*/
tmp = ((csdbuf[C_SIZE_MULT_POS1] & C_SIZE_MULT_MSK1) << 1) +
((csdbuf[C_SIZE_MULT_POS2] & C_SIZE_MULT_MSK2) >> 7) + 2; /* (C_SIZE_MULT + 2) */
/* 获得卡中块的数量 */
mc_info.block_num = mc_info.block_num * (1 << tmp); /* (C_SIZE + 1) * 2 ^ (C_SIZE_MULT + 2) */
/* 计算擦除的单位(单位: 块) */
if (mc_info.card_type == MMC_CARD)
{
tmp = ((csdbuf[ERASE_GRP_SIZE_POS] & ERASE_GRP_SIZE_MSK) >> 2) + 1; /* (ERASE_GRP_SIZE + 1) */
tmp *= ((csdbuf[ERASE_GRP_MULTI_POS1] & ERASE_GRP_MULTI_MSK1) << 3) +
((csdbuf[ERASE_GRP_MULTI_POS2] & ERASE_GRP_MULTI_MSK2) >> 5) + 1;
}
else /*calculate the size of sector */
tmp = ((csdbuf[SECTOR_SIZE_POS1] & SECTOR_SIZE_MSK1) << 1) +
((csdbuf[SECTOR_SIZE_POS2] & SECTOR_SIZE_MSK2) >> 7) + 1; /* SD: SECTOR_SIZE */
mc_info.erase_unit = tmp; /* 擦除单位(块) */
return MC_SUCCESS; /* 返回执行成功 */
}
/*********************************************************************************************************
** 函数名称: mc_initialize
** 功能描述: MMC/SD总的初始化
**
** 参 数: None
**
** 返 回 值: error type
**
** 作 者: 罗辉联
** 日 期: 2006年6月29日
**-------------------------------------------------------------------------------------------------------
** 修 改 人:
** 日 期:
**-------------------------------------------------------------------------------------------------------
*********************************************************************************************************/
UWORD8 mc_initialize(void)
{
WORD8 ret = 0;
UWORD8 recbuf[4] = {0};
mc_hadware_init(); /* MMC/SD硬件接口初始化 */
if (MC_CARD_INSERTED_STATUS() != 1) /* 检查卡是否插入 */
{
ret = MC_ERR_NO_CARD;
goto MC_SD_ERR;
}
/* MC SD初始化步骤 */
MC_CS_ENABLE(); /* 1.置CS为低 */
mc_delay(200); /* 2.至少延时CLK 此处延时320 CLK */
MC_CS_DISABLE(); /* 3.置CS为高 */
mc_delay(4); /* 4.延时4(8 clock) */
ms_sleep(100); /* 5.等待一定的时间后在操作SD/MMC */
ret = mc_reset(); /* 6.发出CMDO命令复位SD卡 */
if (ret != MC_SUCCESS)
goto MC_SD_ERR;
ret =mc_software_active(); /* 7.激活卡进入初始化过程. */
if(ret != MC_SUCCESS)
goto MC_SD_ERR;
mc_read_ocr(4,recbuf); /* 8.读OCR寄存器,查询卡支持的电压值 */
// MC_SEND_TRACE("among SD_ReadOCR, after send CMD58, recbuf[0] value:%d",recbuf[0]);
// MC_SEND_TRACE("among SD_ReadOCR, after send CMD58, recbuf[1] value:%d",recbuf[1]);
// MC_SEND_TRACE("among SD_ReadOCR, after send CMD58, recbuf[2] value:%d",recbuf[2]);
// MC_SEND_TRACE("among SD_ReadOCR, after send CMD58, recbuf[3] value:%d",recbuf[3]);
if((recbuf[1] & MSK_OCR_33) != MSK_OCR_33)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -