打印
[牛人杂谈]

NUC970 SD卡驱动(SDIO)

[复制链接]
楼主: nawu
手机看帖
扫描二维码
随时随地手机跟帖
21
nawu|  楼主 | 2021-6-7 19:07 | 只看该作者 |只看大图 回帖奖励 |倒序浏览
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SDIO_CmdResp7Error(void)
* 功能                        :        获取指令执行状态(R7)
* 参数                        :        无
* 返回                        :        SDIO_Error
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         R7命令优先处理响应成功,后处理CRC错误
*************************************************************************************************************************/
SDIO_Error SDIO_CmdResp7Error(void)
{
        SDIO_Error Status = SDIO_OK;
        u32 timeout=SDIO_TIMEOUT_US;
       
        while (timeout)
        {
                timeout--;
                if(SDIO->INTSTS &(SDIO_INT_STATUS_RITO | SDIO_INT_STATUS_CRC)) break;//CRC错误/命令响应超时
                if((SDIO->CTL & SDIO_CTL_RIEN_Msk) == 0) break;                                                 //收到响应了
                Delay_US(1);
        }
        if(timeout==0)                                        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                //正常程序不应该执行到此处,如果到了此处请检查原因
                DEBUG("程序不应该执行到此处(0x%X)\r\n", SDIO->INTSTS);
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        if(SDIO->INTSTS & SDIO_INT_STATUS_RITO)                                                                        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
       
        //命令响应成功
        if((SDIO->CTL & SDIO_CTL_RIEN_Msk) == 0)
        {
                /* Card is SD V2.0 compliant */
                Status = SDIO_OK;
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
                  
                return Status;
        }

        //SDIO_STA_CCRCFAIL 错误                                                          
        Status = SDIO_CMD_CRC_FAIL;
        //清除所有标志
        SDIO->INTSTS = SDIO->INTSTS;                                                                                        //清除所有标志

        return Status;
}       



使用特权

评论回复
22
nawu|  楼主 | 2021-6-7 19:08 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SDIO_CmdResp1Error(void)
* 功能                        :        指令执行状态(R1)
* 参数                        :        无
* 返回                        :        SDIO_Error
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         此命令超时设置为1分钟,必须增加超时,防止程序假死在此处
                                        如果响应不包含 CRC(CMD1 响应),则设备驱动程序必须忽略 CRC 失败状态。
*************************************************************************************************************************/
SDIO_Error SDIO_CmdResp1Error(void)
{          
           SDIO_Error Status = SDIO_OK;
        u32 timeout=SDIO_TIMEOUT_US/1;       
        u32 response_r1;
               
        while (timeout)
        {
                timeout--;
                if(SDIO->INTSTS &(SDIO_INT_STATUS_RITO | SDIO_INT_STATUS_CRC)) break;//CRC错误/命令响应超时
                if((SDIO->CTL & SDIO_CTL_RIEN_Msk) == 0) break;                                                 //收到响应了
                Delay_US(1);
        }
        if(timeout==0)                                        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                //正常程序不应该执行到此处,如果到了此处请检查原因
                DEBUG("程序不应该执行到此处(0x%X)\r\n", SDIO->INTSTS);
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        if(SDIO->INTSTS & SDIO_INT_STATUS_RITO)        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        //SDIO_STA_CCRCFAIL 错误
        if(SDIO->INTSTS & SDIO_INT_STATUS_CRC)                                                                        //命令校验错误
        {                                                                  
                Status = SDIO_CMD_CRC_FAIL;
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }

        //清除所有标志
        SDIO->INTSTS = SDIO->INTSTS;                                                                                        //清除所有标志
        //命令执行成功,获取R1响应结果
        response_r1 = SDIO_GetResp1CardStatu();                                                                        //返回的响应
       
        if ((response_r1 & SDIO_OCR_ERRORBITS) == 0)                                                        //没有错误响应
        {
                return Status;
        }
       

        if (response_r1 & SDIO_OCR_ADDR_OUT_OF_RANGE)
        {
                return (SDIO_ADDR_OUT_OF_RANGE);
        }

        if (response_r1 & SDIO_OCR_ADDR_MISALIGNED)
        {
                return (SDIO_ADDR_MISALIGNED);
        }

        if (response_r1 & SDIO_OCR_BLOCK_LEN_ERR)
        {
                return (SDIO_BLOCK_LEN_ERR);
        }

        if (response_r1 & SDIO_OCR_ERASE_SEQ_ERR)
        {
                return (SDIO_ERASE_SEQ_ERR);
        }

        if (response_r1 & SDIO_OCR_BAD_ERASE_PARAM)
        {
                return (SDIO_BAD_ERASE_PARAM);
        }

        if (response_r1 & SDIO_OCR_WRITE_PROT_VIOLATION)
        {
                return (SDIO_WRITE_PROT_VIOLATION);
        }

        if (response_r1 & SDIO_OCR_LOCK_UNLOCK_FAILED)
        {
                return (SDIO_LOCK_UNLOCK_FAILED);
        }

        if (response_r1 & SDIO_OCR_COM_CRC_FAILED)
        {
                return (SDIO_COM_CRC_FAILED);
        }

        if (response_r1 & SDIO_OCR_ILLEGAL_CMD)
        {
                return (SDIO_ILLEGAL_CMD);
        }

        if (response_r1 & SDIO_OCR_CARD_ECC_FAILED)
        {
                return (SDIO_CARD_ECC_FAILED);
        }

        if (response_r1 & SDIO_OCR_CC_ERROR)
        {
                return (SDIO_CC_ERROR);
        }

        if (response_r1 & SDIO_OCR_GENERAL_UNKNOWN_ERROR)
        {
                return (SDIO_GENERAL_UNKNOWN_ERROR);
        }

        if (response_r1 & SDIO_OCR_STREAM_READ_UNDERRUN)
        {
                return (SDIO_STREAM_READ_UNDERRUN);
        }

        if (response_r1 & SDIO_OCR_STREAM_WRITE_OVERRUN)
        {
                return (SDIO_STREAM_WRITE_OVERRUN);
        }

        if (response_r1 & SDIO_OCR_CID_CSD_OVERWRIETE)
        {
                return (SDIO_CID_CSD_OVERWRITE);
        }

        if (response_r1 & SDIO_OCR_WP_ERASE_SKIP)
        {
                return (SDIO_WP_ERASE_SKIP);
        }

        if (response_r1 & SDIO_OCR_CARD_ECC_DISABLED)
        {
                return (SDIO_CARD_ECC_DISABLED);
        }

        if (response_r1 & SDIO_OCR_ERASE_RESET)
        {
                return (SDIO_ERASE_RESET);
        }

        if (response_r1 & SDIO_OCR_AKE_SEQ_ERROR)
        {
                return (SDIO_AKE_SEQ_ERROR);
        }
        return Status;
}


使用特权

评论回复
23
nawu|  楼主 | 2021-6-7 19:10 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SDIO_CmdResp3Error(void)
* 功能                        :        指令执行状态(R3,OCR)
* 参数                        :        无
* 返回                        :        SDIO_Error
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         优先处理CRC错误
*************************************************************************************************************************/
SDIO_Error SDIO_CmdResp3Error(void)
{
        SDIO_Error Status = SDIO_OK;
        u32 timeout=SDIO_TIMEOUT_US;
       
        while (timeout)
        {
                timeout--;
                if(SDIO->INTSTS &(SDIO_INT_STATUS_RITO | SDIO_INT_STATUS_CRC)) break;//CRC错误/命令响应超时
                if((SDIO->CTL & SDIO_CTL_RIEN_Msk) == 0) break;                                                 //收到响应了
                Delay_US(1);
        }
        if(timeout==0)                                        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                //正常程序不应该执行到此处,如果到了此处请检查原因
                DEBUG("程序不应该执行到此处(0x%X)\r\n", SDIO->INTSTS);
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        if(SDIO->INTSTS & SDIO_INT_STATUS_RITO)        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        //SDIO_STA_CCRCFAIL 错误       
        if(SDIO->INTSTS & SDIO_INT_STATUS_CRC)                                                                        //命令校验错误
        {                                                                                                                                                                    
                Status = SDIO_CMD_CRC_FAIL;
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        //清除所有标志
        SDIO->INTSTS = SDIO->INTSTS;                                                                                        //清除所有标志

        return Status;
}



使用特权

评论回复
24
nawu|  楼主 | 2021-6-7 19:14 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SDIO_CmdResp2Error(void)
* 功能                        :        指令执行状态(R2,CID or CSD)
* 参数                        :        无
* 返回                        :        SDIO_Error
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         R2响应跟R3响应处理完全一致
*************************************************************************************************************************/
SDIO_Error SDIO_CmdResp2Error(void)
{
        SDIO_Error Status = SDIO_OK;
        u32 timeout=SDIO_TIMEOUT_US;
       
        while (timeout)
        {
                timeout--;
                if(SDIO->INTSTS &(SDIO_INT_STATUS_RITO | SDIO_INT_STATUS_CRC)) break;//CRC错误/命令响应超时
                if((SDIO->CTL & SDIO_CTL_R2IEN_Msk) == 0) break;                                         //收到r2响应了
                Delay_US(1);
        }
        if(timeout==0)                                        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                //正常程序不应该执行到此处,如果到了此处请检查原因
                DEBUG("程序不应该执行到此处(0x%X)\r\n", SDIO->INTSTS);
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        if(SDIO->INTSTS & SDIO_INT_STATUS_RITO)        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        //SDIO_STA_CCRCFAIL 错误       
        if(SDIO->INTSTS & SDIO_INT_STATUS_CRC)                                                                        //命令校验错误
        {                                                                                                                                                                    
                Status = SDIO_CMD_CRC_FAIL;
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        //清除所有标志
        SDIO->INTSTS = SDIO->INTSTS;                                                                                        //清除所有标志       

        return Status;
}


使用特权

评论回复
25
nawu|  楼主 | 2021-6-7 19:15 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        SDIO_Error SDIO_CmdResp6Error(u16*prca)
* 功能                        :        指令执行状态(R6,RCA)
* 参数                        :        prca:RCA缓冲区指针
* 返回                        :        SDIO_Error
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :        
*************************************************************************************************************************/
SDIO_Error SDIO_CmdResp6Error(u16*prca)
{
        SDIO_Error Status = SDIO_OK;                                    
        u32 response_r1;
        u32 timeout=SDIO_TIMEOUT_US/1;
       

        while (timeout)
        {
                timeout--;
                if(SDIO->INTSTS &(SDIO_INT_STATUS_RITO | SDIO_INT_STATUS_CRC)) break;//CRC错误/命令响应超时
                if((SDIO->CTL & SDIO_CTL_RIEN_Msk) == 0) break;                                                 //收到响应了
                Delay_US(1);
        }
        if(timeout==0)                                        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                //正常程序不应该执行到此处,如果到了此处请检查原因
                DEBUG("程序不应该执行到此处(0x%X)\r\n", SDIO->INTSTS);
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        if(SDIO->INTSTS & SDIO_INT_STATUS_RITO)        //响应超时
        {                                                                                                                                                                    
                Status = SDIO_CMD_RSP_TIMEOUT;       
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        //SDIO_STA_CCRCFAIL 错误       
        if(SDIO->INTSTS & SDIO_INT_STATUS_CRC)                                                                        //命令校验错误
        {                                                                                                                                                                    
                Status = SDIO_CMD_CRC_FAIL;
                SDIO->INTSTS = SDIO->INTSTS;                                                                                //清除所有标志
               
                return Status;
        }
        //清除所有标志
        SDIO->INTSTS = SDIO->INTSTS;                                                                                        //清除所有标志
            
        //We have received response, retrieve it.
        response_r1 = SDIO_GetResp1CardStatu();
        if (0 == (response_r1 & (SDIO_R6_GENERAL_UNKNOWN_ERROR | SDIO_R6_ILLEGAL_CMD | SDIO_R6_COM_CRC_FAILED)))
        {
                *prca = (u16) (response_r1 >> 16);
                return Status;
        }

        if (response_r1 & SDIO_R6_GENERAL_UNKNOWN_ERROR)
        {
                return (SDIO_GENERAL_UNKNOWN_ERROR);
        }

        if (response_r1 & SDIO_R6_ILLEGAL_CMD)
        {
                return (SDIO_ILLEGAL_CMD);
        }

        if (response_r1 & SDIO_R6_COM_CRC_FAILED)
        {
                return(SDIO_COM_CRC_FAILED);
        }
       
        return Status;
}


使用特权

评论回复
26
nawu|  楼主 | 2021-6-7 19:23 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        SDIO_Error SDIO_WaitTransComplete(bool isEnableReadData, u32 *pDataLen, u32 TimeOutMs)
* 功能                        :        SDIO等待传输完成(等待读取或写入数据完成)
* 参数                        :        isEnableReadData:是否为读取数据;pDataLen:返回实际传输的数据长度;TimeOutMs:超时时间,毫秒
* 返回                        :        SDIO_Error
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :        
*************************************************************************************************************************/
SDIO_Error SDIO_WaitTransComplete(bool isEnableReadData, u32 *pDataLen, u32 TimeOutMs)
{
        SDIO_Error Status = SDIO_OK;       
        u32 timeout=TimeOutMs*1000/10+1;
        u32 cnt= ((SDIO->BLEN&0x7FF)+1) * ((SDIO->CTL>>16)&0xFF);                                        //获取DMA要传输的数据长度,块大小*块数量       
        *pDataLen = 0;                                                                                                                                //初始化接收数量为0

        //等待读取完成
        while (timeout)
        {
                timeout--;

                if(SDIO_DMA->INTSTS & 0x03) break;                                                                                //传输出错
                if(SDIO->INTSTS & (SDIO_INT_STATUS_CRC | SDIO_INT_STATUS_BLKD)) break;        //传输完成或者CRC校验
                SDIO_DelayUS(1);       
        }
       
        if(timeout == 0)        //读取超时
        {
                Status = SDIO_DATA_TIMEOUT;       
                //正常程序不应该执行到此处,如果到了此处请检查原因
                DEBUG("传输超时(0x%X)\r\n", SDIO->INTSTS);
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                        //复位SDIO控制器
                SDIO_DMA->CTL |= BIT1;                                                                                                        //复位SDIO DMA
                SDIO->INTSTS = SDIO->INTSTS;                                                                                        //清除所有标志
                SDIO_DMA->INTSTS = SDIO_DMA->INTSTS;                                                                        //清除DMA中断标志
               
                goto _error;
        }
        if((SDIO_DMA->INTSTS & 0x03) || (SDIO_DMA->CTL & BIT9))                                                //传输出错,或者DMA还在忙
        {
                Status = SDIO_INTERNAL_ERROR;       
                //正常程序不应该执行到此处,如果到了此处请检查原因
                DEBUG("传输出错(0x%X)\r\n", SDIO->INTSTS);
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                        //复位SDIO控制器
                SDIO_DMA->CTL |= BIT1;                                                                                                        //复位SDIO DMA
                SDIO->INTSTS = SDIO->INTSTS;                                                                                        //清除所有标志
                SDIO_DMA->INTSTS = SDIO_DMA->INTSTS;                                                                        //清除DMA中断标志
               
                goto _error;
        }
       
        if(SDIO->INTSTS & SDIO_INT_STATUS_CRC)                                                                                //数据校验错误
        {
                Status = SDIO_DATA_CRC_FAIL;       
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                        //复位SDIO控制器
                SDIO->INTSTS = SDIO->INTSTS;                                                                                        //清除所有标志
               
                goto _error;
        }
       
        if(SDIO->INTSTS & SDIO_INT_STATUS_BLKD)                                                                                //传输完成
        {
                Status = SDIO_OK;
                SDIO->INTSTS = SDIO->INTSTS;                                                                                        //清除所有标志

                goto _error;
        }

        Status = SDIO_UNSUPPORTED_FEATURE;       
        SDIO->CTL |= SDIO_CTL_SW_RST;                                                                                                //复位SDIO控制器
        SDIO->INTSTS = SDIO->INTSTS;                                                                                                //清除所有标志
       
_error:       

        *pDataLen = cnt-SDIO_DMA->BCNT;                                                                                                //计算实际传输的数据量
        return Status;
}



使用特权

评论回复
27
nawu|  楼主 | 2021-6-7 19:24 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        u32 SDIO_GetResp1CardStatu(void)
* 功能                        :        获取R1响应的卡状态数据
* 参数                        :        无
* 返回                        :        响应数据的[39:8],也就是卡状态数据
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-09
* 最后修改时间         :         2020-09-09
* 说明                        :         响应数据的[39:8]
*************************************************************************************************************************/
__inline u32 SDIO_GetResp1CardStatu(void)
{
        u32 temp;
       
        temp = SDIO->RESP0;//响应数据的[47:16],只取出[39:16]
        temp <<= 8;
        temp |= SDIO->RESP1 & 0xFF;//响应数据的[15:8]
       
        return temp;
}


使用特权

评论回复
28
nawu|  楼主 | 2021-6-7 19:32 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        u32 SDIO_GetResp1CardStatu(void)
* 功能                        :        获取R1响应的卡状态数据
* 参数                        :        无
* 返回                        :        响应数据的[39:8],也就是卡状态数据
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-09
* 最后修改时间         :         2020-09-09
* 说明                        :         响应数据的[39:8]
*************************************************************************************************************************/
__inline u32 SDIO_GetResp1CardStatu(void)
{
        u32 temp;
       
        temp = SDIO->RESP0;//响应数据的[47:16],只取出[39:16]
        temp <<= 8;
        temp |= SDIO->RESP1 & 0xFF;//响应数据的[15:8]
       
        return temp;
}


使用特权

评论回复
29
nawu|  楼主 | 2021-6-7 19:33 | 只看该作者
//SDIO_CONST.H

/*************************************************************************************************************
* 文件名                :        sdio_const.h
* 功能                        :        SDIO相关常量与状态定义
* 作者                        :        cp1300@139.com
* 创建时间                :        2018-03-26
* 最后修改时间        :        2018-03-26
* 详细:                       
*************************************************************************************************************/
#ifndef _SDIO_CONST_H_
#define _SDIO_CONST_H_                                                                                                                                                                  
#include "system.h"


//SDIO块大小
typedef enum
{
        SDIO_DataBlockSize_1B                =        0,
        SDIO_DataBlockSize_2B         =        1,            
        SDIO_DataBlockSize_4B         =        3,            
        SDIO_DataBlockSize_8B         =        7,           
        SDIO_DataBlockSize_16B        =        15,         
        SDIO_DataBlockSize_32B        =        31,         
        SDIO_DataBlockSize_64B        =        63,   
        SDIO_DataBlockSize_128B       =        127,      
        SDIO_DataBlockSize_256B       =        255,      
        SDIO_DataBlockSize_512B       =        511,      
        SDIO_DataBlockSize_1024B      =        1023,        
        SDIO_DataBlockSize_2048B      =        2047,        
}SDIO_DataBlockSize;



//SDIO命令响应定义
typedef enum
{
        SDIO_Response_No                    =        0,        //无应答
        SDIO_Response_Short             =        1,        //短应答48bit
        SDIO_Response_Long                     =        3,        //长应答136bit
}SDIO_WAIT_RESP;


//SDIO总线宽度定义
typedef enum
{       
        SDIO_BusWide_1b    =   0,        //1BIT
        SDIO_BusWide_4b    =   1,        //4BIT
}SDIO_BUS_WIDE;


//SDIO 各种错误枚举定义
typedef enum
{         
        //特殊错误定义
        SDIO_CMD_CRC_FAIL                    = (1), /*!< Command response received (but CRC check failed) */
        SDIO_DATA_CRC_FAIL                   = (2), /*!< Data bock sent/received (CRC check Failed) */
        SDIO_CMD_RSP_TIMEOUT                 = (3), /*!< Command response timeout */
        SDIO_DATA_TIMEOUT                    = (4), /*!< Data time out */
        SDIO_TX_UNDERRUN                     = (5), /*!< Transmit FIFO under-run */
        SDIO_RX_OVERRUN                      = (6), /*!< Receive FIFO over-run */
        SDIO_START_BIT_ERR                   = (7), /*!< Start bit not detected on all data signals in widE bus mode */
        SDIO_CMD_OUT_OF_RANGE                = (8), /*!< CMD's argument was out of range.*/
        SDIO_ADDR_MISALIGNED                 = (9), /*!< Misaligned address */
        SDIO_BLOCK_LEN_ERR                   = (10), /*!< Transferred block length is not allowed for the card or the number of transferred bytes does not match the block length */
        SDIO_ERASE_SEQ_ERR                   = (11), /*!< An error in the sequence of erase command occurs.*/
        SDIO_BAD_ERASE_PARAM                 = (12), /*!< An Invalid selection for erase groups */
        SDIO_WRITE_PROT_VIOLATION            = (13), /*!< Attempt to program a write protect block */
        SDIO_LOCK_UNLOCK_FAILED              = (14), /*!< Sequence or password error has been detected in unlock command or if there was an attempt to access a locked card */
        SDIO_COM_CRC_FAILED                  = (15), /*!< CRC check of the previous command failed */
        SDIO_ILLEGAL_CMD                     = (16), /*!< Command is not legal for the card state */
        SDIO_CARD_ECC_FAILED                 = (17), /*!< Card internal ECC was applied but failed to correct the data */
        SDIO_CC_ERROR                        = (18), /*!< Internal card controller error */
        SDIO_GENERAL_UNKNOWN_ERROR           = (19), /*!< General or Unknown error */
        SDIO_STREAM_READ_UNDERRUN            = (20), /*!< The card could not sustain data transfer in stream read operation. */
        SDIO_STREAM_WRITE_OVERRUN            = (21), /*!< The card could not sustain data programming in stream mode */
        SDIO_CID_CSD_OVERWRITE               = (22), /*!< CID/CSD overwrite error */
        SDIO_WP_ERASE_SKIP                   = (23), /*!< only partial address space was erased */
        SDIO_CARD_ECC_DISABLED               = (24), /*!< Command has been executed without using internal ECC */
        SDIO_ERASE_RESET                     = (25), /*!< Erase sequence was cleared before executing because an out of erase sequence command was received */
        SDIO_AKE_SEQ_ERROR                   = (26), /*!< Error in sequence of authentication. */
        SDIO_INVALID_VOLTRANGE               = (27),
        SDIO_ADDR_OUT_OF_RANGE               = (28),
        SDIO_SWITCH_ERROR                    = (29),
        SDIO_SDIO_DISABLED                   = (30),
        SDIO_SDIO_FUNCTION_BUSY              = (31),
        SDIO_SDIO_FUNCTION_FAILED            = (32),
        SDIO_SDIO_UNKNOWN_FUNCTION           = (33),
        //标准错误定义
        SDIO_INTERNAL_ERROR,
        SDIO_NOT_CONFIGURED,
        SDIO_REQUEST_PENDING,
        SDIO_REQUEST_NOT_APPLICABLE,
        SDIO_INVALID_PARAMETER,  
        SDIO_UNSUPPORTED_FEATURE,  
        SDIO_UNSUPPORTED_HW,  
        SDIO_ERROR,  
        SDIO_OK = 0
} SDIO_Error;       

//SDIO响应获取定义
typedef enum
{
        SDIO_RESP_Short= 0,        //获取段响应中的32bit,命令索引数据 u32[0]  卡状态 [31:0]
        SDIO_RESP_Long = 1,        //获取长响应CID或CSD(包括内部CRC7) u32[0] 卡状态 [127:96];[1]:卡状态 [95:64];[2]:卡状态 [63:32];[3]:卡状态 [31:1]0b
}SDIO_RESP_TYPE;


//Masks for R6 Response
#define SDIO_R6_GENERAL_UNKNOWN_ERROR     ((u32)0x00002000)
#define SDIO_R6_ILLEGAL_CMD               ((u32)0x00004000)
#define SDIO_R6_COM_CRC_FAILED            ((u32)0x00008000)


//Mask for errors Card Status R1 (OCR Register)  
#define SDIO_OCR_ADDR_OUT_OF_RANGE        ((u32)0x80000000)
#define SDIO_OCR_ADDR_MISALIGNED          ((u32)0x40000000)
#define SDIO_OCR_BLOCK_LEN_ERR            ((u32)0x20000000)
#define SDIO_OCR_ERASE_SEQ_ERR            ((u32)0x10000000)
#define SDIO_OCR_BAD_ERASE_PARAM          ((u32)0x08000000)
#define SDIO_OCR_WRITE_PROT_VIOLATION     ((u32)0x04000000)
#define SDIO_OCR_LOCK_UNLOCK_FAILED       ((u32)0x01000000)
#define SDIO_OCR_COM_CRC_FAILED           ((u32)0x00800000)
#define SDIO_OCR_ILLEGAL_CMD              ((u32)0x00400000)
#define SDIO_OCR_CARD_ECC_FAILED          ((u32)0x00200000)
#define SDIO_OCR_CC_ERROR                 ((u32)0x00100000)
#define SDIO_OCR_GENERAL_UNKNOWN_ERROR    ((u32)0x00080000)
#define SDIO_OCR_STREAM_READ_UNDERRUN     ((u32)0x00040000)
#define SDIO_OCR_STREAM_WRITE_OVERRUN     ((u32)0x00020000)
#define SDIO_OCR_CID_CSD_OVERWRIETE             ((u32)0x00010000)
#define SDIO_OCR_WP_ERASE_SKIP            ((u32)0x00008000)
#define SDIO_OCR_CARD_ECC_DISABLED        ((u32)0x00004000)
#define SDIO_OCR_ERASE_RESET              ((u32)0x00002000)
#define SDIO_OCR_AKE_SEQ_ERROR            ((u32)0x00000008)
#define SDIO_OCR_ERRORBITS                ((u32)0xFDFFE008)



//SDIO 指令集
#define SDIO_CMD_GO_IDLE_STATE                       ((u8)0)
#define SDIO_CMD_SEND_OP_COND                        ((u8)1)
#define SDIO_CMD_ALL_SEND_CID                        ((u8)2)
#define SDIO_CMD_SET_REL_ADDR                        ((u8)3) /*!< SDIO_SEND_REL_ADDR for SD Card */
#define SDIO_CMD_SET_DSR                             ((u8)4)
#define SDIO_CMD_SDIO_SEN_OP_COND                    ((u8)5)
#define SDIO_CMD_HS_SWITCH                           ((u8)6)
#define SDIO_CMD_SEL_DESEL_CARD                      ((u8)7)
#define SDIO_CMD_HS_SEND_EXT_CSD                     ((u8)8)
#define SDIO_CMD_SEND_CSD                            ((u8)9)
#define SDIO_CMD_SEND_CID                            ((u8)10)
#define SDIO_CMD_READ_DAT_UNTIL_STOP                 ((u8)11) /*!< SD Card doesn't support it */
#define SDIO_CMD_STOP_TRANSMISSION                   ((u8)12)
#define SDIO_CMD_SEND_STATUS                         ((u8)13)
#define SDIO_CMD_HS_BUSTEST_READ                     ((u8)14)
#define SDIO_CMD_GO_INACTIVE_STATE                   ((u8)15)
#define SDIO_CMD_SET_BLOCKLEN                        ((u8)16)
#define SDIO_CMD_READ_SINGLE_BLOCK                   ((u8)17)
#define SDIO_CMD_READ_MULT_BLOCK                     ((u8)18)
#define SDIO_CMD_HS_BUSTEST_WRITE                    ((u8)19)
#define SDIO_CMD_WRITE_DAT_UNTIL_STOP                ((u8)20)
#define SDIO_CMD_SET_BLOCK_COUNT                     ((u8)23)
#define SDIO_CMD_WRITE_SINGLE_BLOCK                  ((u8)24)
#define SDIO_CMD_WRITE_MULT_BLOCK                    ((u8)25)
#define SDIO_CMD_PROG_CID                            ((u8)26)
#define SDIO_CMD_PROG_CSD                            ((u8)27)
#define SDIO_CMD_SET_WRITE_PROT                      ((u8)28)
#define SDIO_CMD_CLR_WRITE_PROT                      ((u8)29)
#define SDIO_CMD_SEND_WRITE_PROT                     ((u8)30)
#define SDIO_CMD_SDIO_ERASE_GRP_START                  ((u8)32) /*!< To set the address of the first write
                                                                  block to be erased. (For SD card only) */
#define SDIO_CMD_SDIO_ERASE_GRP_END                    ((u8)33) /*!< To set the address of the last write block of the
                                                                  continuous range to be erased. (For SD card only) */
#define SDIO_CMD_ERASE_GRP_START                     ((u8)35) /*!< To set the address of the first write block to be erased.
                                                                  (For MMC card only spec 3.31) */

#define SDIO_CMD_ERASE_GRP_END                       ((u8)36) /*!< To set the address of the last write block of the
                                                                  continuous range to be erased. (For MMC card only spec 3.31) */

#define SDIO_CMD_ERASE                               ((u8)38)
#define SDIO_CMD_FAST_IO                             ((u8)39) /*!< SD Card doesn't support it */
#define SDIO_CMD_GO_IRQ_STATE                        ((u8)40) /*!< SD Card doesn't support it */
#define SDIO_CMD_LOCK_UNLOCK                         ((u8)42)
#define SDIO_CMD_APP_CMD                             ((u8)55)
#define SDIO_CMD_GEN_CMD                             ((u8)56)
#define SDIO_CMD_NO_CMD                              ((u8)64)

/**
  * @brief Following commands are SD Card Specific commands.
  *        SDIO_APP_CMD :CMD55 should be sent before sending these commands.
  */
#define SDIO_CMD_APP_SDIO_SET_BUSWIDTH                 ((u8)6)  /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_STAUS                        ((u8)13) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_SEND_NUM_WRITE_BLOCKS        ((u8)22) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_OP_COND                      ((u8)41) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_SET_CLR_CARD_DETECT          ((u8)42) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_SEND_SCR                     ((u8)51) /*!< For SD Card only */
#define SDIO_CMD_SDIO_RW_DIRECT                      ((u8)52) /*!< For SD I/O Card only */
#define SDIO_CMD_SDIO_RW_EXTENDED                    ((u8)53) /*!< For SD I/O Card only */

/**
  * @brief Following commands are SD Card Specific security commands.
  *        SDIO_APP_CMD should be sent before sending these commands.
  */
#define SDIO_CMD_SDIO_APP_GET_MKB                      ((u8)43) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_GET_MID                      ((u8)44) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_SET_CER_RN1                  ((u8)45) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_GET_CER_RN2                  ((u8)46) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_SET_CER_RES2                 ((u8)47) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_GET_CER_RES1                 ((u8)48) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_SECURE_READ_MULTIPLE_BLOCK   ((u8)18) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_SECURE_WRITE_MULTIPLE_BLOCK  ((u8)25) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_SECURE_ERASE                 ((u8)38) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_CHANGE_SECURE_AREA           ((u8)49) /*!< For SD Card only */
#define SDIO_CMD_SDIO_APP_SECURE_WRITE_MKB             ((u8)48) /*!< For SD Card only */
                            



#define SD_VOLTAGE_WINDOW_SD            ((u32)0x80100000)
#define SD_HIGH_CAPACITY                ((u32)0x40000000)
#define SD_STD_CAPACITY                 ((u32)0x00000000)
#define SD_CHECK_PATTERN                ((u32)0x000001AA)
#define SD_VOLTAGE_WINDOW_MMC           ((u32)0x80FF8000)

#define SD_MAX_VOLT_TRIAL               ((u32)0x0000FFFF)
#define SD_ALLZERO                      ((u32)0x00000000)

#define SD_WIDE_BUS_SUPPORT             ((u32)0x00040000)
#define SD_SINGLE_BUS_SUPPORT           ((u32)0x00010000)
#define SD_CARD_LOCKED                  ((u32)0x02000000)
#define SD_CARD_PROGRAMMING             ((u32)0x00000007)
#define SD_CARD_RECEIVING               ((u32)0x00000006)
#define SD_DATATIMEOUT                  ((u32)0xFFFFFFFF)
#define SD_0TO7BITS                     ((u32)0x000000FF)
#define SD_8TO15BITS                    ((u32)0x0000FF00)
#define SD_16TO23BITS                   ((u32)0x00FF0000)
#define SD_24TO31BITS                   ((u32)0xFF000000)
#define SD_MAX_DATA_LENGTH              ((u32)0x01FFFFFF)

#define SD_HALFFIFO                     ((u32)0x00000008)
#define SD_HALFFIFOBYTES                ((u32)0x00000020)

//Command Class Supported  
#define SD_CCCC_LOCK_UNLOCK             ((u32)0x00000080)
#define SD_CCCC_WRITE_PROT              ((u32)0x00000040)
#define SD_CCCC_ERASE                   ((u32)0x00000020)
                                                                                                                                         
//CMD8指令
#define SDIO_SEND_IF_COND               ((u32)0x00000008)





#endif  //_SDIO_CONST_H_



使用特权

评论回复
30
nawu|  楼主 | 2021-6-7 19:34 | 只看该作者
//SDIO_SDCARD.C

/*************************************************************************************************************
* 文件名                        :        sdio_sdcard.c
* 功能                                :        SDIO接口SD卡驱动
* 作者                                :        cp1300@139.com
* 创建时间                        :        2018-03-27
* 最后修改时间                :        2018-03-27
* 详细                                :        源程序借鉴了意法STM32F103X库函数
                                                分离了底层SDIO接口,但是依赖一些数据定义,在sdio_const中,去掉了MMC卡支持,没遇到过MMC卡
                                                异常情况:如果先将卡设置为高速模式,然后再设置为4线模式,之后读取多块超时后会出现CMD12响应3,并且卡不断电情况下无法恢复通讯,所有命令均响应超时。
                                                        出现了这种异常情况后,必须对卡进行重新断电才能恢复,就算单片机复位都不行。
                                                2018-03-29:删除了SCR状态读取,这个状态唯一的作用就是获取卡是否支持4线模式(很少有不支持的,就算不支持,设置失败了也会还原为单线模式),SD卡上电默认必须为单线模式
                                                2018-03-30:如果SD卡在读取或者写入数据过程中突然中断(程序复位),但是SD卡没有断电,下次可能会初始化失败,并且必须断电才能恢复。
                                                2018-03-30:读取入1-3个扇区时间均为3m,写入1个扇区为4ms,由于通信内部使用了系统延时1ms导致,此时提高系统时钟,SDIO时钟均无效,但是增加这个1ms延时可以有效防止系统卡死,提高OS运行效率
                                                2018-03-30:测试写入3个扇区时间为5ms,写入10个扇区为7ms
                                                2019-10-31:修复初始化时判断大容量卡时&写成了&=,导致判断错误
                                                2020-02-03:修改一次最大的读写限制为65535字节,FAT文件系统一次最大只会读取32KB数据
                                                2020-02-21:修改可以设置SD卡块大小,同步修改SDIO块大小,SDHC卡不支持修改块大小,去掉了读写时卡锁定检查(没啥用)
                                                2020-09-13:增加获取最大传输块数量功能,修改读写扇区是,检查并清理传输错误,修改响应数据读取接口
*************************************************************************************************************/
#include "sdio_sdcard.h"
#include "system.h"
#include "sdio_const.h"
#include "string.h"


// SD卡指令表            
#define CMD0    0       //复位所有的卡到idle状态
#define CMD1    1               
#define CMD2    2                //通知所有卡通过CMD线返回CID值。
#define CMD3    3                //通知所有卡发布新RCA
#define ACMD6        6                //设置宽总线模式
#define CMD7    7                //选择/取消选择RCA地址卡。
#define CMD8    8                //发送SD卡接口条件,包含主机支持的电压信息,并询问卡是否支持。
#define CMD9    9       //命令9 ,读CSD数据
#define CMD10   10      //命令10,读CID数据
#define CMD12   12      //命令12,停止数据传输
#define CMD13   13      //命令13,选定卡通过CMD线发送它状态寄存器
#define CMD16   16      //命令16,设置SectorSize 应返回0x00
#define CMD17   17      //命令17,读sector
#define CMD18   18      //命令18,读Multi sector
#define ACMD23  23      //命令23,设置多sector写入前预先擦除N个block
#define CMD24   24      //命令24,写sector
#define CMD25   25      //命令25,写Multi sector
#define CMD32        32                //设置擦除的起始块地址
#define CMD33        33                //设置擦除的结束块地址
#define CMD38        38                //擦除预先选定的块

#define ACMD41  41      //命令41,主机要求卡发送它的支持信息(HCS)和OCR寄存器内容。
#define CMD55   55      //命令55,指定下个命令为特定应用命令,不是标准命令
#define CMD58   58      //命令58,读OCR信息
#define CMD59   59      //命令59,使能/禁止CRC,应返回0x0


#define SD_VOLTAGE_WINDOW_SD            ((u32)0x80100000)
#define SD_HIGH_CAPACITY                ((u32)0x40000000)
#define SD_STD_CAPACITY                 ((u32)0x00000000)
#define SD_CHECK_PATTERN                ((u32)0x000001AA)

#define SD_MAX_VOLT_TRIAL               ((u32)0x0000FFFF)
#define SD_ALLZERO                      ((u32)0x00000000)

#define SD_WIDE_BUS_SUPPORT             ((u32)0x00040000)
#define SD_SINGLE_BUS_SUPPORT           ((u32)0x00010000)
#define SD_CARD_LOCKED                  ((u32)0x02000000)
#define SD_CARD_PROGRAMMING             ((u32)0x00000007)
#define SD_CARD_RECEIVING               ((u32)0x00000006)

#define SD_0TO7BITS                     ((u32)0x000000FF)
#define SD_8TO15BITS                    ((u32)0x0000FF00)
#define SD_16TO23BITS                   ((u32)0x00FF0000)
#define SD_24TO31BITS                   ((u32)0xFF000000)
#define SD_MAX_DATA_LENGTH              ((u32)0x01FFFFFF)

#define SD_HALFFIFO                     ((u32)0x00000008)
#define SD_HALFFIFOBYTES                ((u32)0x00000020)

/* Command Class Supported */
#define SD_CCCC_LOCK_UNLOCK             ((u32)0x00000080)
#define SD_CCCC_WRITE_PROT              ((u32)0x00000040)
#define SD_CCCC_ERASE                   ((u32)0x00000020)

/* Following commands are SD Card Specific commands.
   SDIO_APP_CMD should be sent before sending these commands. */
#define SDIO_SEND_IF_COND               ((u32)0x00000008)



//调试开关
#define SDCARD_DBUG                 1
#if SDCARD_DBUG
        #include "system.h"
        #define sdcard_debug(format,...)        uart_printf(format,##__VA_ARGS__)
#else
        #define sdcard_debug(format,...)        /\
/

#endif        //SDCARD_DBUG



SDIO_Error SD_SetIdleSta(SDIO_SD_HANDLE *pHandle);                                                                        //SD卡上电进入空闲模式,并识别卡
SDIO_Error SD_InitializeCards(SDIO_SD_HANDLE *pHandle);                                                                //将所有的卡进行初始化配置
static SDIO_Error SDEnableWideBus(SDIO_SD_HANDLE *pHandle, bool isEnableWideBus);        //设置SD卡宽总线模式
SDIO_Error SD_SetBlockSize(SDIO_SD_HANDLE *pHandle, u16 BlockSize);                                        //设置SD卡块大小
SDIO_Error SD_EnableWideBusMode(SDIO_SD_HANDLE *pHandle, bool isEnable4BusWide);        //使能4bit DAT线模式,如果失败将保持原来模式
SDIO_Error SD_SelectDeselect(SDIO_SD_HANDLE *pHandle, u32 addr);                                        //选中一个卡,并处于传输状态
SDIO_Error SD_GetCardInfo(SDIO_SD_HANDLE *pHandle, SD_CardInfo *cardinfo);                        //获取卡的细节信息
SDIO_Error SD_WaitProgrammingFinish(SDIO_SD_HANDLE *pHandle, u32 TimeOutMs);                //等待编程完成
SDIO_Error SD_GetSDSCR(SDIO_SD_HANDLE *pHandle, u32 pSCR[2]);                                                //获取SCR信息



使用特权

评论回复
31
nawu|  楼主 | 2021-6-7 19:35 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        void SD_InterfaceInit(SDIO_SD_HANDLE *pHandle,const SDIO_SD_INTERFACE *pInterface)
* 功能                        :        SD卡底层接口初始化
* 参数                        :        pHandle:句柄;pInterface:通信接口
* 返回                        :        无
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        2018-03-27
* 最后修改时间         :         2018-03-27
* 说明                        :         初始化SD卡
*************************************************************************************************************************/
void SD_InterfaceInit(SDIO_SD_HANDLE *pHandle, const SDIO_SD_INTERFACE *pInterface)
{
        pHandle->pInterface = pInterface;        //初始化通信接口
}


使用特权

评论回复
32
nawu|  楼主 | 2021-6-7 19:37 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        SDIO_Error SD_ReadStatus(SDIO_SD_HANDLE *pHandle, u32 *pSCR)
* 功能                        :        读取SD卡状态寄存器
* 参数                        :        pHandle:句柄;pSCR:状态寄存器的值
* 返回                        :        SDIO_Error
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        2018-03-29
* 最后修改时间         :         2018-03-29
* 说明                        :         必须在初始化SD卡成功后才能调用,因为需要SD卡的RCA地址
**************************************************************************************************************************/
SDIO_Error SD_ReadStatus(SDIO_SD_HANDLE *pHandle, u32 *pSCR)
{
        SDIO_Error errorstatus = SDIO_OK;

        //发送CMD13,SDIO_SEND_STATUS,读 Card_Status 寄存器,参数,RCA地址,短返回,R1;
        pHandle->pInterface->SDIO_SendCommand(CMD13, (u32) pHandle->RCA << 16, SDIO_Response_Short);
        errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();                                                //获取回复
        if (errorstatus != SDIO_OK)                                                                                                                //命令发送错误,返回
        {
                pHandle->pInterface->SDIO_ClearDataTrans();                                                                        //清除数据传输
                DEBUG("CMD13 error (%d)!\r\n",errorstatus);
                return(errorstatus);
        }
        pHandle->pInterface->SDIO_GetResponse(SDIO_RESP_Short, pSCR);                                        //获取响应的状态

        return(errorstatus);
}



使用特权

评论回复
33
nawu|  楼主 | 2021-6-7 19:38 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SD_Init(SDIO_SD_HANDLE *pHandle)
* 功能                        :        SD卡初始化
* 参数                        :        pHandle:句柄
* 返回                        :        SDIO_Error
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        2018-03-27
* 最后修改时间         :         2018-03-27
* 说明                        :         初始化SD卡,需要提前初始化通信接口,调用:SD_InterfaceInit
*************************************************************************************************************************/
SDIO_Error SD_Init(SDIO_SD_HANDLE *pHandle)
{
        SDIO_Error errorstatus = SDIO_OK;
       
        if(pHandle == NULL || pHandle->pInterface == NULL)
        {
                DEBUG("SDIO 接口无效!\n");                        //调试,打印错误
                return SDIO_ERROR;
        }
        //初始化相关变量
        memset(&pHandle->SDCardInfo, 0, sizeof(SD_CardInfo));
       
        pHandle->SDIO_BlockSize = SDIO_DataBlockSize_512B;                        //设置默认的SDIO传输块大小:512字节
        pHandle->pInterface->SDIO_Init();                                                        //SDIO硬件初始化
        pHandle->MaxTransBlockCount = pHandle->pInterface->SDIO_GetMaxTransBlockCount();//从SDIO驱动层获取一次最大传输块数量
        errorstatus = SD_SetIdleSta(pHandle);                                                //SD卡上电
        if (errorstatus != SDIO_OK)                                                                        //卡上电发送错误
        {
                DEBUG("SD power up error:(%d)!\n",errorstatus);                        //调试,打印错误
                return (errorstatus);        //返回错误
        }

        errorstatus = SD_InitializeCards(pHandle);
        if (errorstatus != SDIO_OK)
        {
                DEBUG("SD initialize error(%d)!\r\n",errorstatus);                //调试,打印错误
                return (errorstatus);
        }
        //更新卡信息
        SD_GetCardInfo(pHandle, &pHandle->SDCardInfo);                                //获取卡信息
        uart_printf("SD卡容量:%llu\r\n",  pHandle->SDCardInfo.CardCapacity);
        return (errorstatus);
}



使用特权

评论回复
34
nawu|  楼主 | 2021-6-7 19:39 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        SDIO_Error SD_Reset(SDIO_SD_HANDLE *pHandle)
* 功能                        :        复位并检查卡,不支持MMC卡
* 参数                        :        pHandle:接口句柄
* 返回                        :        SDIO_Error
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        2018-03-29
* 最后修改时间         :         2018-03-29
* 说明                        :   SD卡上电进入空闲模式(不带响应),并使用CMD55检查卡是否通讯正常
*************************************************************************************************************************/
SDIO_Error SD_Reset(SDIO_SD_HANDLE *pHandle)
{
        SDIO_Error errorstatus = SDIO_OK;
        u32 i;
       
        //循环发生发送CMD0,无响应,无返回,让SD卡进入空闲模式-无响应,无返回,多发送几次
          for(i = 0; i < 10; i ++)
          {
                  pHandle->pInterface->SDIO_SendCommand(CMD0, 0, SDIO_Response_No);                        //发送命令               
                pHandle->pInterface->SDIO_CmdError();                                                                                //判断命令是否执行成功,此命令只要初始化了SDIO就会执行成功
                SYS_DelayMS(1);
                //发送CMD55
                pHandle->pInterface->SDIO_SendCommand(CMD55, 0, SDIO_Response_Short);                //发送命令
                errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();                                       
                if(errorstatus == SDIO_OK)                                                                                                         //卡检测成功后再发送一次CMD0,否则后面的CMD8将不会响应
                {
                        pHandle->pInterface->SDIO_SendCommand(CMD0, 0, SDIO_Response_No);                //发送命令               
                        pHandle->pInterface->SDIO_CmdError();                                                                        //判断命令是否执行成功,此命令只要初始化了SDIO就会执行成功
                        return SDIO_OK;//SD卡
                }
                else if(errorstatus == SDIO_CMD_CRC_FAIL)                 //我的一个v1.1的卡在此处会返回校验错误
                {
                        pHandle->pInterface->SDIO_SendCommand(CMD0, 0, SDIO_Response_No);                //发送命令               
                        pHandle->pInterface->SDIO_CmdError();                                                                        //判断命令是否执行成功,此命令只要初始化了SDIO就会执行成功
                        return SDIO_OK;//SD卡
                }
          }
       
       
        DEBUG("没有检测到SD卡(错误:%d)\r\n", errorstatus);
       
        return errorstatus;
}


使用特权

评论回复
35
nawu|  楼主 | 2021-6-7 19:39 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SD_SetIdleSta(SDIO_SD_HANDLE *pHandle)
* 功能                        :        SD卡上电进入空闲模式,并识别卡
* 参数                        :        pHandle:接口句柄
* 返回                        :        SDIO_Error
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        20120516
* 最后修改时间         :         2018-03-28
* 说明                        :   SD卡上电进入空闲模式
*************************************************************************************************************************/
SDIO_Error SD_SetIdleSta(SDIO_SD_HANDLE *pHandle)
{
        SDIO_Error errorstatus = SDIO_OK;
        u32 response = 0, count = 0;
        bool validvoltage = FALSE;
        u32 SDType = SD_STD_CAPACITY;

        pHandle->pInterface->SDIO_SetLowSpeedClock();                //设置为低速时钟
        //发送至少74个时钟,等待SD卡上电成功并同步,要求SDIO一直输出时钟
        SYS_DelayMS(5);
        errorstatus = SD_Reset(pHandle);                                        //复位并检查卡
        if(errorstatus != SDIO_OK) return errorstatus;
         
        //发送CMD8之前一定要发送一个CMD0-此处为重复发送(保险起见),因为在SD_Reset中已经发送
        pHandle->pInterface->SDIO_SendCommand(CMD0, 0, SDIO_Response_No);                //发送命令               
        pHandle->pInterface->SDIO_CmdError();                                                                        //判断命令是否执行成功,此命令只要初始化了SDIO就会执行成功
         
        //发送CMD8:SEND_IF_COND;短响应,命令参数:SD_CHECK_PATTERN;返回响应R7
          //识别卡版本
        pHandle->pInterface->SDIO_SendCommand(CMD8, SD_CHECK_PATTERN, SDIO_Response_Short);        //发送命令
        errorstatus = pHandle->pInterface->SDIO_CmdResp7Error();                                        //获取响应R7
        if (errorstatus == SDIO_OK)                                                                                                        //返回成功;说明卡为SD Card 2.0 V2.0
        {
                pHandle->CardType = SD_STD_CAPACITY_SD_CARD_V2_0;                                                //SD Card 2.0
                SDType = SD_HIGH_CAPACITY;       
                sdcard_debug("SD_STD_CAPACITY_SD_CARD_V2_0!\r\n");
        }
        else        //V1.0 V1.1
        {
                pHandle->CardType = SD_STD_CAPACITY_SD_CARD_V1_1;                                                 //V1.0 V1.1
                sdcard_debug("SD Card V1.1!\r\n");                                                                                //调试,打印信息
               
                pHandle->pInterface->SDIO_SendCommand(CMD55, 0, SDIO_Response_Short);        //发送命令
                errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();       
        }
        //发送CMD55
        pHandle->pInterface->SDIO_SendCommand(CMD55, 0, SDIO_Response_Short);                //发送命令
        errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();                                       
        if(errorstatus == SDIO_OK) //SD卡
        {
                do
                {
                        //发送CMD55
                        pHandle->pInterface->SDIO_SendCommand(CMD55, 0, SDIO_Response_Short);        //发送命令
                        errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();
                        if(errorstatus != SDIO_OK) //SD卡
                        {
                                DEBUG("CMD55 error(%d)!\r\n",errorstatus);                                                        //调试,打印错误信息
                                return(errorstatus);
                        }
                       
                        //发送ACMD41命令;命令参数:SD_APP_OP_COND(0x80100000);短响应.响应为R3,返回操作条件寄存器RCA-注意,这个命令的响应是不带CRC的,会报CRC错误,忽略即可
                        pHandle->pInterface->SDIO_SendCommand(ACMD41, SD_VOLTAGE_WINDOW_SD | SDType, SDIO_Response_Short);
                        errorstatus = pHandle->pInterface->SDIO_CmdResp3Error();
                        if (errorstatus != SDIO_OK && errorstatus != SDIO_CMD_CRC_FAIL)                //CMD CRC错误也是正常的,ACM41不响应CRC       
                        {
                                DEBUG("ACM41 error(%d)!\r\n",errorstatus);                                                //调试,打印错误信息
                                return(errorstatus);
                        }
                        errorstatus = SDIO_OK;
                        pHandle->pInterface->SDIO_GetResponse(SDIO_RESP_Short, &response);  //获取响应,RESE1
                        validvoltage = (bool) (((response >> 31) == 1) ? 1 : 0);
                        count++;
                }
                while((!validvoltage) && (count < SD_MAX_VOLT_TRIAL));                                        //循环初始化,直到返回成功或者超时

                if (count >= SD_MAX_VOLT_TRIAL)                                                                                        //重试次数超出
                {
                        errorstatus = SDIO_INVALID_VOLTRANGE;
                        return (errorstatus);
                }

                if (response & SD_HIGH_CAPACITY)                                                                                //大容量卡,超过4G以上
                {
                        uart_printf("SD卡是大容量卡!\r\n");
                        pHandle->CardType = SD_HIGH_CAPACITY_SD_CARD;
                }
        }

        return(errorstatus);
}


使用特权

评论回复
36
nawu|  楼主 | 2021-6-7 19:41 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SD_InitializeCards(SDIO_SD_HANDLE *pHandle)
* 功能                        :        将所有的卡进行初始化配置
* 参数                        :        pHandle:句柄
* 返回                        :        SDIO_Error
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        20120516
* 最后修改时间         :         2018-03-28
* 说明                        :         将所有的卡进行初始化配置
*************************************************************************************************************************/
SDIO_Error SD_InitializeCards(SDIO_SD_HANDLE *pHandle)
{
        SDIO_Error errorstatus = SDIO_OK;
        u16 rca = 0x01;

       
        if(SD_SECURE_DIGITAL_IO_CARD != pHandle->CardType)        //非SECURE_DIGITAL_IO_CARD
        {
                //发送CMD2 SDIO_ALL_SEND_CID命令,命令参数:0;长回复,R2
                pHandle->pInterface->SDIO_SendCommand(CMD2, 0, SDIO_Response_Long);
                errorstatus = pHandle->pInterface->SDIO_CmdResp2Error();                                //获取响应R2
                if (errorstatus != SDIO_OK)
                {
                        DEBUG("CMD2 error!(%d)\r\n",errorstatus);                                                        //调试,打印错误信息
                        return (errorstatus);
                }
               
                //到每个卡以获取每个卡的唯一标识CID
                pHandle->pInterface->SDIO_GetResponse(SDIO_RESP_Long, pHandle->CID_Tab);       
        }
        if((SD_STD_CAPACITY_SD_CARD_V1_1 == pHandle->CardType)||(SD_STD_CAPACITY_SD_CARD_V2_0 == pHandle->CardType)||(SD_SECURE_DIGITAL_IO_COMBO_CARD == pHandle->CardType)||(SD_HIGH_CAPACITY_SD_CARD == pHandle->CardType))//判断卡类型
        {
                //发送CMD3,短响应R6
                pHandle->pInterface->SDIO_SendCommand(CMD3, 0, SDIO_Response_Short);
                errorstatus = pHandle->pInterface->SDIO_CmdResp6Error(&rca);                                //获取响应R6
                if (errorstatus != SDIO_OK)
                {
                        DEBUG("CMD3 error!(%d)\r\n",errorstatus);                                                                //调试,打印错误信息
                        return (errorstatus);
                }            
        }   
    if (SD_MULTIMEDIA_CARD == pHandle->CardType)
    {
                //发送CMD3,短响应R2
                pHandle->pInterface->SDIO_SendCommand(CMD3, (u32)(rca<<16), SDIO_Response_Short);
                errorstatus = pHandle->pInterface->SDIO_CmdResp2Error();                                //获取响应R2
                if (errorstatus != SDIO_OK)
                {
                        DEBUG("CMD3 error!(%d)\r\n",errorstatus);                                                                //调试,打印错误信息
                        return (errorstatus);
                }         
    }
        if (SD_SECURE_DIGITAL_IO_CARD != pHandle->CardType)                        //非SECURE_DIGITAL_IO_CARD
        {
                //发送CMD9+卡RCA,取得CSD,长响应 R2;给卡发送一个新的RCA,主要是用来设置卡地址的
                pHandle->pInterface->SDIO_SendCommand(CMD9, (u32)(rca<<16), SDIO_Response_Long);
                errorstatus = pHandle->pInterface->SDIO_CmdResp2Error();                                //获取响应R2
                if (errorstatus != SDIO_OK)
                {
                        DEBUG("CMD3 error!(%d)\r\n",errorstatus);                                                                //调试,打印错误信息
                        return (errorstatus);
                }          
                pHandle->pInterface->SDIO_GetResponse(SDIO_RESP_Long, pHandle->CSD_Tab);                    
        }
        pHandle->RCA = rca;                                                                                                                //存储卡地址
       

    //选中卡,并激活
        errorstatus = SD_SelectDeselect(pHandle, (u32)pHandle->RCA << 16);
        if(errorstatus != SDIO_OK)
        {
                DEBUG("SelectDeselect error!(%d)!\r\n",errorstatus);                                        //调试,打印错误信息
                return(errorstatus);
        }

        //先设置为4线模式,然后再设置为高速时钟
       
        //设置宽总线模式-一定要使用低速时钟,否则会出现卡不响应,并且不可恢复,必须对卡进行重新上电
        errorstatus = SDIO_OK; /* All cards get intialized */
        errorstatus = SD_EnableWideBusMode(pHandle, TRUE);                                                //配置SD卡为4线模式
        if(errorstatus == SDIO_OK)       
        {
                sdcard_debug("SD SDIO 4BIT OK\r\n");
        }
        else //设置失败了,还原为1线模式
        {
                errorstatus = SD_EnableWideBusMode(pHandle, FALSE);                                        //还原为1线模式
                DEBUG("SD SDIO 4BIT ERROR (%d)\r\n",errorstatus);
        }
       
        //提高时钟速度-必须放到最后,否则会出现卡各种不响应,必须对卡重新上电
        pHandle->pInterface->SDIO_SetHighpeedClock();                                                        //设置高速时钟
        //读取SD卡SCR信息,第一次使用数据线通信
        errorstatus = SD_GetSDSCR(pHandle, pHandle->SCR_Tab);                                        //获取SCR信息
        //配置SD卡的块大小,之后不要再修改了,固定块大小进行传输
        errorstatus = SD_SetBlockSize(pHandle, SD_BLOCK_SIZE);                                        //配置SD卡块大小       
        if (errorstatus != SDIO_OK)
        {
                DEBUG("SD SetBlockSize error(%d)!\r\n",errorstatus);
                return(errorstatus);
        }

        return(errorstatus);
}



使用特权

评论回复
37
nawu|  楼主 | 2021-6-7 19:42 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        SDIO_Error SD_SelectDeselect(SDIO_SD_HANDLE *pHandle, u32 addr)
* 功能                        :        选中一个卡,并处于传输状态
* 参数                        :        pHandle:句柄;addr:卡地址
* 返回                        :        SDIO_Error
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        20120516
* 最后修改时间         :         2018-03-28
* 说明                        :         选择一个卡并将它置于传输状态(Transfer state)
                                        CMD7用来选定和取消指定的卡,卡在待机状态下还不能进行数据通信,因为总线上可能有多个卡都是出于待机状态,
                                        必须选择一个RCA地址目标卡使其进入传输状态才可以进行数据通信。同时通过CMD7命令也可以让已经被选择的目标卡返回到待机状态。
*************************************************************************************************************************/
SDIO_Error SD_SelectDeselect(SDIO_SD_HANDLE *pHandle, u32 addr)
{
        SDIO_Error errorstatus = SDIO_OK;

        //CMD7用来选择一个卡并将它置于传输状态(Transfer state),在任何时间只能有一个卡处于传输状态
        pHandle->pInterface->SDIO_SendCommand(CMD7, addr, SDIO_Response_Short);
        errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();

        return(errorstatus);
}


使用特权

评论回复
38
nawu|  楼主 | 2021-6-7 19:42 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SD_GetCardInfo(SDIO_SD_HANDLE *pHandle, SD_CardInfo *cardinfo)
* 功能                        :        获取卡的细节信息
* 参数                        :        pHandle:句柄;cardinfo:卡信息结构指针,指向信息存放缓冲区地址
* 返回                        :        SDIO_Error
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        20120516
* 最后修改时间         :         2018-03-28
* 说明                        :         获取卡的信息,通过CSD信息得到
*************************************************************************************************************************/
SDIO_Error SD_GetCardInfo(SDIO_SD_HANDLE *pHandle, SD_CardInfo *cardinfo)
{
        SDIO_Error errorstatus = SDIO_OK;
        u8 tmp=0;          
       
        cardinfo->CardType=(u8)pHandle->CardType;                                                 //卡类型
        cardinfo->RCA=(u16)pHandle->RCA;                                                                //卡RCA值
        tmp=(u8)((pHandle->CSD_Tab[0]&0xFF000000)>>24);
        cardinfo->SD_csd.CSDStruct=(tmp&0xC0)>>6;                                                //CSD结构
        cardinfo->SD_csd.SysSpecVersion=(tmp&0x3C)>>2;                                        //2.0协议还没定义这部分(为保留),应该是后续协议定义的
        cardinfo->SD_csd.Reserved1=tmp&0x03;                                                        //2个保留位  
        tmp=(u8)((pHandle->CSD_Tab[0]&0x00FF0000)>>16);                                        //第1个字节
        cardinfo->SD_csd.TAAC=tmp;                                                                                   //数据读时间1
        tmp=(u8)((pHandle->CSD_Tab[0]&0x0000FF00)>>8);                                          //第2个字节
        cardinfo->SD_csd.NSAC=tmp;                                                                                  //数据读时间2
        tmp=(u8)(pHandle->CSD_Tab[0]&0x000000FF);                                                //第3个字节
        cardinfo->SD_csd.MaxBusClkFrec=tmp;                                                                  //传输速度          
        tmp=(u8)((pHandle->CSD_Tab[1]&0xFF000000)>>24);                                        //第4个字节
        cardinfo->SD_csd.CardComdClasses=tmp<<4;                                            //卡指令类高四位
        tmp=(u8)((pHandle->CSD_Tab[1]&0x00FF0000)>>16);                                         //第5个字节
        cardinfo->SD_csd.CardComdClasses|=(tmp&0xF0)>>4;                                //卡指令类低四位
        cardinfo->SD_csd.RdBlockLen=tmp&0x0F;                                                    //最大读取数据长度
        tmp=(u8)((pHandle->CSD_Tab[1]&0x0000FF00)>>8);                                        //第6个字节
        cardinfo->SD_csd.PartBlockRead=(tmp&0x80)>>7;                                        //允许分块读
        cardinfo->SD_csd.WrBlockMisalign=(tmp&0x40)>>6;                                        //写块错位
        cardinfo->SD_csd.RdBlockMisalign=(tmp&0x20)>>5;                                        //读块错位
        cardinfo->SD_csd.DSRImpl=(tmp&0x10)>>4;
        cardinfo->SD_csd.Reserved2=0;                                                                         //保留
        if((pHandle->CardType==SD_STD_CAPACITY_SD_CARD_V1_1)||(pHandle->CardType==SD_STD_CAPACITY_SD_CARD_V2_0)||(pHandle->CardType == SD_MULTIMEDIA_CARD))//标准1.1/2.0卡/MMC卡
        {
                cardinfo->SD_csd.DeviceSize=(tmp&0x03)<<10;                                        //C_SIZE(12位)
                 tmp=(u8)(pHandle->CSD_Tab[1]&0x000000FF);                                         //第7个字节       
                cardinfo->SD_csd.DeviceSize|=(tmp)<<2;
                tmp=(u8)((pHandle->CSD_Tab[2]&0xFF000000)>>24);                                //第8个字节       
                cardinfo->SD_csd.DeviceSize|=(tmp&0xC0)>>6;
                cardinfo->SD_csd.MaxRdCurrentVDDMin=(tmp&0x38)>>3;
                cardinfo->SD_csd.MaxRdCurrentVDDMax=(tmp&0x07);
                tmp=(u8)((pHandle->CSD_Tab[2]&0x00FF0000)>>16);                                //第9个字节       
                cardinfo->SD_csd.MaxWrCurrentVDDMin=(tmp&0xE0)>>5;
                cardinfo->SD_csd.MaxWrCurrentVDDMax=(tmp&0x1C)>>2;
                cardinfo->SD_csd.DeviceSizeMul=(tmp&0x03)<<1;                                //C_SIZE_MULT
                tmp=(u8)((pHandle->CSD_Tab[2]&0x0000FF00)>>8);                                  //第10个字节       
                cardinfo->SD_csd.DeviceSizeMul|=(tmp&0x80)>>7;
                cardinfo->CardCapacity=(cardinfo->SD_csd.DeviceSize+1);                //计算卡容量
                cardinfo->CardCapacity*=(1<<(cardinfo->SD_csd.DeviceSizeMul+2));
                cardinfo->CardBlockSize=1<<(cardinfo->SD_csd.RdBlockLen);        //块大小
                cardinfo->CardCapacity*=cardinfo->CardBlockSize;
        }else if(pHandle->CardType==SD_HIGH_CAPACITY_SD_CARD)                        //高容量卡
        {
                tmp=(u8)(pHandle->CSD_Tab[1]&0x000000FF);                 //第7个字节       
                cardinfo->SD_csd.DeviceSize=(tmp&0x3F)<<16;//C_SIZE
                tmp=(u8)((pHandle->CSD_Tab[2]&0xFF000000)>>24); //第8个字节       
                cardinfo->SD_csd.DeviceSize|=(tmp<<8);
                tmp=(u8)((pHandle->CSD_Tab[2]&0x00FF0000)>>16);        //第9个字节       
                cardinfo->SD_csd.DeviceSize|=(tmp);
                tmp=(u8)((pHandle->CSD_Tab[2]&0x0000FF00)>>8);         //第10个字节       
                cardinfo->CardCapacity=(u64)(cardinfo->SD_csd.DeviceSize+1)*512*1024;//计算卡容量
                cardinfo->CardBlockSize=512;                                         //块大小固定为512字节
        }          
        cardinfo->SD_csd.EraseGrSize=(tmp&0x40)>>6;
        cardinfo->SD_csd.EraseGrMul=(tmp&0x3F)<<1;          
        tmp=(u8)(pHandle->CSD_Tab[2]&0x000000FF);                        //第11个字节       
        cardinfo->SD_csd.EraseGrMul|=(tmp&0x80)>>7;
        cardinfo->SD_csd.WrProtectGrSize=(tmp&0x7F);
        tmp=(u8)((pHandle->CSD_Tab[3]&0xFF000000)>>24);                //第12个字节       
        cardinfo->SD_csd.WrProtectGrEnable=(tmp&0x80)>>7;
        cardinfo->SD_csd.ManDeflECC=(tmp&0x60)>>5;
        cardinfo->SD_csd.WrSpeedFact=(tmp&0x1C)>>2;
        cardinfo->SD_csd.MaxWrBlockLen=(tmp&0x03)<<2;         
        tmp=(u8)((pHandle->CSD_Tab[3]&0x00FF0000)>>16);                //第13个字节
        cardinfo->SD_csd.MaxWrBlockLen|=(tmp&0xC0)>>6;
        cardinfo->SD_csd.WriteBlockPaPartial=(tmp&0x20)>>5;
        cardinfo->SD_csd.Reserved3=0;
        cardinfo->SD_csd.ContentProtectAppli=(tmp&0x01);  
        tmp=(u8)((pHandle->CSD_Tab[3]&0x0000FF00)>>8);                //第14个字节
        cardinfo->SD_csd.FileFormatGrouop=(tmp&0x80)>>7;
        cardinfo->SD_csd.CopyFlag=(tmp&0x40)>>6;
        cardinfo->SD_csd.PermWrProtect=(tmp&0x20)>>5;
        cardinfo->SD_csd.TempWrProtect=(tmp&0x10)>>4;
        cardinfo->SD_csd.FileFormat=(tmp&0x0C)>>2;
        cardinfo->SD_csd.ECC=(tmp&0x03);  
        tmp=(u8)(pHandle->CSD_Tab[3]&0x000000FF);                        //第15个字节
        cardinfo->SD_csd.CSD_CRC=(tmp&0xFE)>>1;
        cardinfo->SD_csd.Reserved4=1;                 
        tmp=(u8)((pHandle->CID_Tab[0]&0xFF000000)>>24);                //第0个字节
        cardinfo->SD_cid.ManufacturerID=tmp;                    
        tmp=(u8)((pHandle->CID_Tab[0]&0x00FF0000)>>16);                //第1个字节
        cardinfo->SD_cid.OEM_AppliID=tmp<<8;          
        tmp=(u8)((pHandle->CID_Tab[0]&0x000000FF00)>>8);        //第2个字节
        cardinfo->SD_cid.OEM_AppliID|=tmp;            
        tmp=(u8)(pHandle->CID_Tab[0]&0x000000FF);                        //第3个字节       
        cardinfo->SD_cid.ProdName1=tmp<<24;                                  
        tmp=(u8)((pHandle->CID_Tab[1]&0xFF000000)>>24);         //第4个字节
        cardinfo->SD_cid.ProdName1|=tmp<<16;          
        tmp=(u8)((pHandle->CID_Tab[1]&0x00FF0000)>>16);                   //第5个字节
        cardinfo->SD_cid.ProdName1|=tmp<<8;                 
        tmp=(u8)((pHandle->CID_Tab[1]&0x0000FF00)>>8);                //第6个字节
        cardinfo->SD_cid.ProdName1|=tmp;                  
        tmp=(u8)(pHandle->CID_Tab[1]&0x000000FF);                          //第7个字节
        cardinfo->SD_cid.ProdName2=tmp;                          
        tmp=(u8)((pHandle->CID_Tab[2]&0xFF000000)>>24);         //第8个字节
        cardinfo->SD_cid.ProdRev=tmp;                 
        tmp=(u8)((pHandle->CID_Tab[2]&0x00FF0000)>>16);                //第9个字节
        cardinfo->SD_cid.ProdSN=tmp<<24;          
        tmp=(u8)((pHandle->CID_Tab[2]&0x0000FF00)>>8);                 //第10个字节
        cardinfo->SD_cid.ProdSN|=tmp<<16;          
        tmp=(u8)(pHandle->CID_Tab[2]&0x000000FF);                   //第11个字节
        cardinfo->SD_cid.ProdSN|=tmp<<8;                  
        tmp=(u8)((pHandle->CID_Tab[3]&0xFF000000)>>24);         //第12个字节
        cardinfo->SD_cid.ProdSN|=tmp;                             
        tmp=(u8)((pHandle->CID_Tab[3]&0x00FF0000)>>16);                 //第13个字节
        cardinfo->SD_cid.Reserved1|=(tmp&0xF0)>>4;
        cardinfo->SD_cid.ManufactDate=(tmp&0x0F)<<8;   
        tmp=(u8)((pHandle->CID_Tab[3]&0x0000FF00)>>8);                //第14个字节
        cardinfo->SD_cid.ManufactDate|=tmp;                           
        tmp=(u8)(pHandle->CID_Tab[3]&0x000000FF);                        //第15个字节
        cardinfo->SD_cid.CID_CRC=(tmp&0xFE)>>1;
        cardinfo->SD_cid.Reserved2=1;       
       
        return errorstatus;
}



使用特权

评论回复
39
nawu|  楼主 | 2021-6-7 19:43 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SD_EnableWideBusMode(SDIO_SD_HANDLE *pHandle, bool isEnable4BusWide)
* 功能                        :        使能4bit DAT线模式,如果失败将保持原来模式
* 参数                        :        pHandle:服务器句柄;Enable:4bit模式;Disable:1bit模式
* 返回                        :        SDIO_Error
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        20120516
* 最后修改时间         :         2018-03-28
* 说明                        :         设置卡和控制器为4bit总线模式,线设置开启4线模式再开启高速时钟,必须先激活选中卡
*************************************************************************************************************************/
SDIO_Error SD_EnableWideBusMode(SDIO_SD_HANDLE *pHandle, bool isEnable4BusWide)
{
        SDIO_Error errorstatus = SDIO_OK;
       
        //SD卡不支持设置
        if (pHandle->CardType == SD_MULTIMEDIA_CARD)
        {
                errorstatus = SDIO_UNSUPPORTED_FEATURE;
                return(errorstatus);
        }
        else //SD卡
        {
                if (isEnable4BusWide)        //4BIT模式
                {
                    errorstatus = SDEnableWideBus(pHandle, TRUE);        //设置SD卡为4bit总线模式
                    if (errorstatus == SDIO_OK)                                                //设置SD卡成功
                        {
                                pHandle->pInterface->SDIO_Set4BitBusWide();        //设置SDIO控制器为4线模式
                        }       
                  }
                  else
                  {
                          errorstatus = SDEnableWideBus(pHandle, FALSE);        //设置SD卡为1bit总线模式
                    if (errorstatus == SDIO_OK)                                                //设置SD卡成功
                        {
                                pHandle->pInterface->SDIO_Set1BitBusWide();        //设置SDIO控制器为1线模式
                        }
                  }
          }       
        return (errorstatus);
}



使用特权

评论回复
40
nawu|  楼主 | 2021-6-7 19:58 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        static SDIO_Error SDEnableWideBus(SDIO_SD_HANDLE *pHandle, bool isEnableWideBus)
* 功能                        :        设置SD卡宽总线模式
* 参数                        :        pHandle:服务器句柄;isEnableWideBus:4bit模式;Disable:1bit模式
* 返回                        :        SDIO_Error
* 依赖                        :        底层寄存器操作函数
* 作者                        :        cp1300@139.com
* 时间                        :        20120516
* 最后修改时间         :         2018-03-28
* 说明                        :         设置SD卡宽总线模式-需要先读取RCA
*************************************************************************************************************************/
static SDIO_Error SDEnableWideBus(SDIO_SD_HANDLE *pHandle, bool isEnableWideBus)
{
        SDIO_Error errorstatus = SDIO_OK;
        u32 temp;

        pHandle->pInterface->SDIO_GetResponse(SDIO_RESP_Short, &temp);        //获取响应
        if (temp & SD_CARD_LOCKED) //锁了
        {
                errorstatus = SDIO_LOCK_UNLOCK_FAILED;
                return(errorstatus);
        }

        if (isEnableWideBus)        //使能4bit dat
        {
                //发送CMD55,SDIO_APP_CMD,激活卡
                //发送CMD55 SDIO_APP_CMD;命令参数:RCA;返回响应R1,设置RCA为0,短响应
                pHandle->pInterface->SDIO_SendCommand(CMD55, (u32)pHandle->RCA << 16, SDIO_Response_Short);
                errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();
                if (errorstatus != SDIO_OK)
                {
                        DEBUG("CMD55 error(%d)!\r\n",errorstatus);        //调试,打印错误信息
                        return (errorstatus);
                }
                //发送ACMD6,SDIO_APP_SD_SET_BUSWIDTH,设置宽总线模式,参数0x2,短响应,R1
                pHandle->pInterface->SDIO_SendCommand(ACMD6, 0x2, SDIO_Response_Short);
                errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();
                if (errorstatus != SDIO_OK)
                {
                        DEBUG("ACMD6 error(%d)!\r\n",errorstatus);        //调试,打印错误信息
                        return (errorstatus);
                }
                return (errorstatus);
        }   
        else        //设置为单线模式
          {
                //发送CMD55 SDIO_APP_CMD;命令参数:RCA;返回响应R1,设置RCA为0,短响应
                pHandle->pInterface->SDIO_SendCommand(CMD55, (u32)pHandle->RCA << 16, SDIO_Response_Short);
                errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();
                if (errorstatus != SDIO_OK)
                {
                        DEBUG("CMD55 error(%d)!\r\n",errorstatus);        //调试,打印错误信息
                        return (errorstatus);
                }
                //发送ACMD6,SDIO_APP_SD_SET_BUSWIDTH,设置宽总线模式,参数0x0,短响应,R1
                pHandle->pInterface->SDIO_SendCommand(ACMD6, 0x0, SDIO_Response_Short);
                errorstatus = pHandle->pInterface->SDIO_CmdResp1Error();
                if (errorstatus != SDIO_OK)
                {
                        DEBUG("ACMD6 error(%d)!\r\n",errorstatus);        //调试,打印错误信息
                        return (errorstatus);
                }
                return(errorstatus);
        }
}



使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则