?? 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 + -