📄 sdcmd.c
字号:
/****************************************Copyright (c)**************************************************
** Guangzhou ZLG-MCU Development Co.,LTD.
** graduate school
** http://www.zlgmcu.com
**
**--------------File Info-------------------------------------------------------------------------------
** File name: sdcmd.c
** Last modified Date: 2007-5-19
** Last Version: V2.0
** Descriptions: SD/MMC 软件包: SD/MMC卡SPI模式和SD模式支持的命令
**
**
**------------------------------------------------------------------------------------------------------
** Created by: Ming Yuan Zheng
** Created date: 2005-1-6
** Version: V1.0
** Descriptions: SD/MMC 读写模块: 物理层 ---- SD卡SPI模式支持的命令
**
**------------------------------------------------------------------------------------------------------
** Modified by: Ming Yuan Zheng
** Modified date: 2005-3-11
** Version: V2.0
** Descriptions: 增加了对MMC卡的支持,并使用本模块既可以运行于前后台系统,也可运行于uCOS-II中.
**
**------------------------------------------------------------------------------------------------------
** Modified by: Ming Yuan Zheng
** Modified date: 2007-5-19
** Version: V3.0
** Descriptions: 1. 对原来SPI模式下的函数名进行修改, 改为以 SpiCmd_ 为开头, 数据流函数以 SdSpi_ 为开头
**
** 2. 增加了对SD总线模式的支持, 函数名以 SdCmd_ 为开头
**
********************************************************************************************************/
#include "sdconfig.h"
/*********************************************
本文件实现 SD/MMC 卡 SD模式下的各 CMD 和 ACMD
**********************************************/
#if SDBUS_MODE_EN
static void word_to_byte(INT32U value, INT8U *pdst);
#define OCR_WITHOUT_BUSY 0x00FF8000
#define OCR_WITH_BUSY 0x80000000
/*************
CMD 0
*************/
/*******************************************************************************************************************
** 函数名称: SdCmd_Go_Idle_State()
**
** 功能描述: CMD0, 复位所有卡, 使卡进入Idle状态
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdCmd_Go_Idle_State(sd_struct *sds)
{
return (SdHal_SendCmd(sds, CMD0, 0, CMD0_R, 0, 0)); /* 发送 CMD0 并取得响应 */
}
/*************
CMD 1
*************/
/*******************************************************************************************************************
** 函数名称: SdCmd_Send_OP_Cond()
**
** 功能描述: CMD1(仅用于MMC卡), 使卡退出Idle状态, 进入Ready状态(通过判断MMC卡的OCR寄存器值)
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
********************************************************************************************************************/
INT8U SdCmd_Send_OP_Cond(sd_struct *sds)
{
INT32U OCRVal;
INT8U ret;
INT32U count = 0;
do
{
ret = SdHal_SendCmd(sds, CMD1, OCR_WITHOUT_BUSY, CMD1_R, &OCRVal, 1); /* 发送 CMD1 并取得响应 */
if (ret != SD_NO_ERR)
return ret;
if (count >= SD_IDLE_WAIT_MAX)
return SD_ERR_TIMEOUT_WAITIDLE; /* 超时,返回错误码 */
count ++;
}while ((OCRVal & OCR_WITH_BUSY) == 0x00000000);
if ((OCRVal & MSK_OCR_33) != MSK_OCR_33)
return SD_ERR_VOL_NOTSUSP; /* 卡不支3.2V ~ 3.3V电压 */
return SD_NO_ERR;
}
/*************
CMD 55
*************/
/*******************************************************************************************************************
** 函数名称: SdCmd_Send_ACMD()
**
** 功能描述: CMD55(仅用于SD卡), 在发送所有 ACMDxx 命令之前, 必须先发送本命令
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
**
** 注 意: 在未使用 Set_Relative_Addr 命令取得卡的RCA地址之前, sds->RCA为0.
********************************************************************************************************************/
INT8U SdCmd_Send_ACMD(sd_struct *sds)
{
INT32U argument;
INT32U devstatus = 0;
INT8U ret;
if (sds->card_type == CARDTYPE_SD) /* 根据卡型取不同的参数 */
argument = sds->RCA;
else
argument = 0x00000000;
ret = SdHal_SendCmd(sds, CMD55, argument, CMD55_R, &devstatus, 1); /* 发送 CMD55 并取得响应 */
if (ret != SD_NO_ERR)
return ret;
if (devstatus & CARD_STATUS_ACMD_ENABLE)
return SD_NO_ERR; /* 支持 CMD55 命令 */
return SD_ERR_CMD_NOTSUSP; /* 不支持该命令 */
}
/*************
ACMD 41
*************/
/*******************************************************************************************************************
** 函数名称: SdCmd_SD_App_OP_Cond()
**
** 功能描述: ACMD41(仅用于SD卡), 使卡退出Idle状态, 并进入Ready状态(通过判断SD卡的OCR寄存器值)
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
**
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
**
** 注 意: 在未使用 Set_Relative_Addr 命令取得卡的RCA地址之前, sds->RCA为0.
********************************************************************************************************************/
INT8U SdCmd_SD_App_OP_Cond(sd_struct *sds)
{
INT8U ret;
INT32U OCRVal, count = 0;
do
{
ret = SdCmd_Send_ACMD(sds); /* 先发送 CMD55 命令 */
if (ret != SD_NO_ERR)
return ret;
ret = SdHal_SendCmd(sds, ACMD41, OCR_WITHOUT_BUSY, ACMD41_R, &OCRVal, 1); /* 发送 ACMD41 并取得响应 */
if (ret != SD_NO_ERR)
return ret;
if (count >= SD_IDLE_WAIT_MAX)
return SD_ERR_TIMEOUT_WAITIDLE; /* 超时,返回错误码 */
count ++;
}while ((OCRVal & OCR_WITH_BUSY) == 0x00000000);
if ((OCRVal & MSK_OCR_33) != MSK_OCR_33)
return SD_ERR_VOL_NOTSUSP; /* 卡不支3.2V ~ 3.3V电压 */
return SD_NO_ERR;
}
/*************
CMD 2
*************/
/*******************************************************************************************************************
** 函数名称: SdCmd_All_Send_CID()
**
** 功能描述: 获取所有卡的CID寄存器内容
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
** INT8U cidlen : CID 寄存器长度, 固定为16字节
**
** 输 出: INT8U *cidbuf : CID 寄存器内容, 长度为16字节
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
**
** 注 意: 该命令的Argument域不必关心
********************************************************************************************************************/
INT8U SdCmd_All_Send_CID(sd_struct *sds, INT8U cidlen, INT8U *cidbuf)
{
INT8U ret;
INT32U resp[4];
if ((cidlen < 16) || (cidbuf == 0))
return SD_ERR_USER_PARAM;
ret = SdHal_SendCmd(sds, CMD2, 0, CMD2_R, resp, 4);
if (ret != SD_NO_ERR)
return ret;
word_to_byte(*resp, cidbuf); /* 从响应内容中取得CID寄存器内容 */
word_to_byte(*(resp + 1), cidbuf + 4);
word_to_byte(*(resp + 2), cidbuf + 8);
word_to_byte(*(resp + 3), cidbuf + 12);
return SD_NO_ERR;
}
/*****************************
CMD 3: 设置卡的地址 RCA
******************************/
/*******************************************************************************************************************
** 函数名称: SdCmd_Set_Relative_Addr()
**
** 功能描述: CMD3, 获取卡的RCA地址, 然后保存到sds结构体中
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
**
** 注 意: 该函数将给 sds->RCA 成员赋值
********************************************************************************************************************/
INT8U SdCmd_Set_Relative_Addr(sd_struct *sds)
{
INT32U argument;
INT32U resp;
INT8U ret;
/* 如果是一张SD卡, 使用SET_RELATIVE_ADDR用于从卡获取地址并在RCA中使用该值,
如果是一张MMC卡, 使用默认的RCA地址 0x00010000. */
if (sds->card_type == CARDTYPE_SD)
{
argument = 0;
}
else
{ /* 如果是未知的或MMC卡, 固定RCA地址 */
argument = 0x00010000;
}
ret = SdHal_SendCmd(sds, CMD3, argument, CMD3_R, &resp, 1);
if (ret != 0)
return ret;
if (sds->card_type == CARDTYPE_SD)
{
/* 卡应处于 IDENT 状态 */
if ((resp & CARD_STATUS_CURRENT_STATE) == CARD_STATUS_IDENT)
sds->RCA = resp & 0xFFFF0000;
else
return SD_ERR_CURRENT_STATE;
}
else
sds->RCA = argument;
return SD_NO_ERR;
}
/********************************************
CMD 9, 仅在CMD3发送后才可发送, 获取 CSD
*********************************************/
/*******************************************************************************************************************
** 函数名称: SdCmd_Send_CSD()
**
** 功能描述: CMD9, 获取卡的CSD寄存器值
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
** INT8U csdlen : CSD 寄存器长度
**
** 输 出: INT8U *csdbuf : CSD寄存器内容, bit127 在csdbuf[0]
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
**
** 注 意: 该命令需要 sds->RCA 作为命令参数
********************************************************************************************************************/
INT8U SdCmd_Send_CSD(sd_struct *sds, INT8U csdlen, INT8U *csdbuf)
{
INT8U ret;
INT32U resp[4];
if ((csdlen < 16) || (csdbuf == 0))
return SD_ERR_USER_PARAM;
ret = SdHal_SendCmd(sds, CMD9, sds->RCA, CMD9_R, resp, 4);
if (ret != SD_NO_ERR)
return ret;
word_to_byte(*resp, csdbuf); /* 从响应内容中取得CSD寄存器内容 */
word_to_byte(*(resp + 1), csdbuf + 4);
word_to_byte(*(resp + 2), csdbuf + 8);
word_to_byte(*(resp + 3), csdbuf + 12);
return SD_NO_ERR;
}
/**********************************************************
CMD 7: 选择卡, 使卡在 Stand-by 与 Transfer 之间切换
***********************************************************/
/*******************************************************************************************************************
** 函数名称: SdCmd_Select_Card()
**
** 功能描述: CMD7, 使卡在 Stand-by 与 Transfer 之间切换
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
**
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
**
** 注 意: 该命令需要 sds->RCA 作为命令参数
********************************************************************************************************************/
INT8U SdCmd_Select_Card(sd_struct *sds)
{
INT32U resp;
INT8U ret;
ret = SdHal_SendCmd(sds, CMD7, sds->RCA, CMD7_R, &resp, 1);
if (ret != SD_NO_ERR)
return ret;
return SD_NO_ERR;
}
/**********************************************************
CMD 7: 取消选择卡, 使卡在 Stand-by 与 Transfer 之间切换
***********************************************************/
/*******************************************************************************************************************
** 函数名称: SdCmd_Select_Card()
**
** 功能描述: CMD7, 使卡在 Stand-by 与 Transfer 之间切换
**
** 输 入: sd_struct *sds : SD/MMC卡信息结构体
** INT32U RCA : 卡的RCA地址
** 输 出: 无
**
** 返 回 值: 0: 正确 >0: 错误码, 见 sddriver.h 文件
**
** 注 意: 该命令的命令参数为RCA, 取值为0
********************************************************************************************************************/
INT8U SdCmd_Deselect_Card(sd_struct *sds, INT32U RCA)
{
INT32U resp;
INT8U ret;
ret = SdHal_SendCmd(sds, CMD7, RCA, CMD0_R, &resp, 1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -