打印
[牛人杂谈]

NUC970 SD卡驱动(SDIO)

[复制链接]
1829|53
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
nawu|  楼主 | 2021-6-7 18:47 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
在读取SD卡的R2长响应折腾了不少时间,原因是必须开启DMA,不开启DMA,R2响应将不会传输到SDIO的FIFO中,将SDIO接口与STM32保持一致,并兼容应用层SDIO_SDCARD驱动。

寄存器地址


//SDIO========================================================================================================
#define SDIO_BUFF_BASE                       (0xB000C000)                      //寄存器基址
#define SDIO_DMA_BASE                       (0xB000C000+0x400)      //寄存器基址
#define SDIO_BASE                               (0xB000C000+0x800)      //寄存器基址


typedef struct
{
        vu8 Buff[128];                                                                //SD主机嵌入式缓冲区
}SDIO_BUFF_TypeDef;

typedef struct
{
        vu32 CTL;                                                                        //SD主机DMA控制和状态寄存器
        u32 Reserved1;
        vu32 SA;                                                                        //SD主机DMA传输起始地址寄存器
        vu32 BCNT;                                                                        //SD主机DMA传输字节计数寄存器
        vu32 INTEN;                                                                        //SD主机DMA中断使能寄存器
        vu32 INTSTS;                                                                //SD主机DMA中断状态寄存器
}SDIO_DMA_TypeDef;

typedef struct
{
        vu32 GCTL;                                                                        //SD主机全局控制和状态寄存器
        vu32 GINTEN;                                                                //SD主机全局中断控制寄存器
        vu32 GINTSTS;                                                                //SD主机全局中断状态寄存器
        u32 Reserved1[5];
        vu32 CTL;                                                                        //SD主机控制和状态寄存器
        vu32 ARG;                                                                        //SD主机命令参数寄存器
        vu32 INTEN;                                                                        //SD主机中断允许寄存器
        vu32 INTSTS;                                                                //SD主机中断状态寄存器
        vu32 RESP0;                                                                        //SD主机接收响应令牌寄存器0
        vu32 RESP1;                                                                        //SD主机接收响应令牌寄存器1
        vu32 BLEN;                                                                        //SD主机块长度寄存器
        vu32 TMOUT;                                                                        //SD主机响应/数据输入超时寄存器
        vu32 ECTL;                                                                        //SD主机扩展控制寄存器
}SDIO_TypeDef;

#define SDIO_BUFF                              ((SDIO_BUFF_TypeDef *) SDIO_BUFF_BASE)
#define SDIO_DMA                               ((SDIO_DMA_TypeDef *) SDIO_DMA_BASE)
#define SDIO                                      ((SDIO_TypeDef *) SDIO_BASE)


使用特权

评论回复
沙发
nawu|  楼主 | 2021-6-7 18:48 | 只看该作者
//SDIO.c

/*************************************************************************************************************
* 文件名:                        sdio.c
* 功能:                        NUC970 sdio驱动
* 作者:                        cp1300@139.com
* 创建时间:                2020-09-04
* 最后修改时间:        2020-09-04
* 详细:                       
*************************************************************************************************************/
#include "nuc970_system.h"
#include "sdio.h"
#include "sdio_const.h"

__inline u32 SDIO_GetResp1CardStatu(void);//获取R1响应的卡状态数据

#define SDIO_DelayUS(x)                Delay_US(x)
#define SDIO_TIMEOUT_US                (100*1000)                //SDIO软件延时


/*************************************************************************************************************************
* 函数                        :        bool SDIO_Init(void)
* 功能                        :        SDIO接口初始化
* 参数                        :        无
* 返回                        :        TRUE:初始化成功;FALSE:初始化失败;
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         默认会选择 SD host port 0
*************************************************************************************************************************/
bool SDIO_Init(void)
{
        //SDIO时钟选择,使用CPU时钟,CPU使用的是UPLL,300MHz
        u32 tempreg = SYS_REG_TYPE(REG_CLK_DIVCTL9);
       
        SYS_DeviceClockEnable(DEV_SDIO, TRUE);        //使能时钟
        SYS_DeviceReset(DEV_RESET_SDIO);                //复位外设
       
        tempreg &= ~(0xFFFF);                                        //清除掉之前的设置
        tempreg |= 3 << 3;                                                //时钟源选择UPLL 0x0:XIN;0x2:APLL;0x3:UPLL
        tempreg |= 2 << 0;                                                //PLL时钟分频(2+1),输出100MHz
        tempreg |= SDIO_CLK_400K << 8;                        //SDH_N分频系数+1, 390KHz
        SYS_REG_TYPE(REG_CLK_DIVCTL9) = tempreg;
        Delay_US(100);
        SDIO->GCTL = 1;                                                        //关闭并复位SDIO
        nop;nop;
        SDIO->GCTL |= BIT1;                                                //使能SDIO-不使能无法设置寄存器
        nop;nop;
       
        //SDIO寄存器设置          
        SDIO->GINTEN = 0;                                                //关闭DMA中断
        SDIO->GINTSTS = 1;                                                //清除DMA错误中断
        SDIO->CTL = SDIO_CTL_SW_RST;                        //数据1bit模式;复位内部状态机;
        while(SDIO->CTL & SDIO_CTL_SW_RST);
        SDIO->CTL = (0x09u<<24) | (1<<16);                //设置默认配置
        SDIO->INTEN = 0;                                                //中断全部关闭
        SDIO_SetDataTransBlockSize(SDIO_DataBlockSize_512B);        //默认块大小:512字节
        SDIO_SetDataTransTimeOut(0xFFFFFF);                //SDIO传输数据超时设置-设置为非常大,直接由应用程序来决定超时
        SDIO_SetBusWide(SDIO_BusWide_1b);                //SDIO设置总线宽度
        SDIO_SetPower(TRUE);                                        //SDIO电源控制-使能
        SDIO_DMA->CTL = BIT1;                                        //DMA复位,不启动分散加载功能
        while(SDIO_DMA->CTL & BIT1);
        SDIO_DMA->INTEN = 0;                                        //关闭DMA中断
        SDIO_DMA->CTL |= BIT0;                                        //使能DMA-2020-09-12折腾几天发现,此处必须开启DMA,否则R2响应的数据无法被接收

        return TRUE;
}



使用特权

评论回复
板凳
nawu|  楼主 | 2021-6-7 18:49 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        bool SDIO_SetOut74Clock(void)
* 功能                        :        SDIO输出74个时钟
* 参数                        :        无
* 返回                        :        TRUE:成功;FALSE:失败
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-12
* 最后修改时间         :         2020-09-12
* 说明                        :        
*************************************************************************************************************************/
bool SDIO_SetOut74Clock(void)
{
        u32 timeout = SDIO_TIMEOUT_US;//读等待超时计数器
       
        SDIO->CTL |= BIT5;                                                //SDIO输出74个时钟,用于初始化SD卡,等待SD卡上电稳定
        while(SDIO->CTL & BIT5)
        {
                timeout --;
                Delay_US(1);
        }
        if(timeout == 0)
        {
                SDIO->CTL |= SDIO_CTL_SW_RST;                //复位SDIO控制器
                return FALSE;
        }
       
        return TRUE;
}



使用特权

评论回复
地板
nawu|  楼主 | 2021-6-7 18:49 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        void SDIO_SetClockSpeed(SDIO_CLOCK_SPEED ClkSpeed)
* 功能                        :        SDIO设置时钟速度
* 参数                        :        ClkSpeed:时钟速度,见SDIO_CLOCK_SPEED
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :        
*************************************************************************************************************************/
void SDIO_SetClockSpeed(SDIO_CLOCK_SPEED ClkSpeed)
{
        u32 tempreg = SYS_REG_TYPE(REG_CLK_DIVCTL9);
       
        tempreg &= ~(0xFF << 8);                                        //清除掉之前的设置
        tempreg |= (ClkSpeed & 0xff) << 8;                        //SDH_N分频系数+1
        SYS_REG_TYPE(REG_CLK_DIVCTL9) = tempreg;
        Delay_US(10);
}


使用特权

评论回复
5
nawu|  楼主 | 2021-6-7 18:50 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        u8 SDIO_GetPortSelect(void)
* 功能                        :        获取当前选择的port(0-1)
* 参数                        :        无
* 返回                        :        通道0-1
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :        
*************************************************************************************************************************/
u8 SDIO_GetPortSelect(void)
{
        if(SDIO->CTL & BIT29) return 1;
        else return 0;
}



使用特权

评论回复
6
nawu|  楼主 | 2021-6-7 18:51 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_SetPortSelect(u8 port)
* 功能                        :        设置SDIO当前port(0-1)
* 参数                        :        通道0-1
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :        
*************************************************************************************************************************/
void SDIO_SetPortSelect(u8 port)
{
        if(port) SDIO->CTL |= BIT29;
        else SDIO->CTL &= ~BIT29;
}


使用特权

评论回复
7
nawu|  楼主 | 2021-6-7 18:52 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_SetBusWide(SDIO_BUS_WIDE BusWide)
* 功能                        :        SDIO设置总线宽度
* 参数                        :        BusWide:总线宽度,见SDIO_BUS_WIDE
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :        
*************************************************************************************************************************/
void SDIO_SetBusWide(SDIO_BUS_WIDE BusWide)
{
        if(BusWide == SDIO_BusWide_1b)
        {
                SDIO->CTL &= ~BIT15;                //设置为1bit模式
        }
        else
        {
                SDIO->CTL |= BIT15;                        //设置为4bit模式
        }
}



使用特权

评论回复
8
nawu|  楼主 | 2021-6-7 18:54 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_BUS_WIDE SDIO_GetBusWide(void)
* 功能                        :        获取SDIO设置的总线宽度
* 参数                        :        无
* 返回                        :        总线宽度,见SDIO_BUS_WIDE
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         可以获取当前端口的总线宽度
*************************************************************************************************************************/
SDIO_BUS_WIDE SDIO_GetBusWide(void)
{
        if(SDIO->CTL & BIT15) return SDIO_BusWide_4b;
        else return SDIO_BusWide_1b;
}



使用特权

评论回复
9
nawu|  楼主 | 2021-6-7 18:55 | 只看该作者

/*************************************************************************************************************************
*函数        :        void SDIO_SendCommand(u8 CmdIndex,u32 CmdArg,SDIO_WAIT_RESP WaitResp)
*功能        :        SDIO发送一个命令
*参数        :        CmdIdx:指令索引;CmdArg:命令参数;WaitResp:响应类型
*返回        :        无
*依赖        :         底层宏定义
*作者        :        cp1300@139.com
*时间        :        2020-09-04
*最后修改时间:        2020-09-04
*说明        :        响应类型
                                        SDIO_Response_No           无应答
                                        SDIO_Response_Short        短应答
                                        SDIO_Response_Long         长应答
                                此单片机只区分有应答还是无应答
*************************************************************************************************************************/
void SDIO_SendCommand(u8 CmdIndex, u32 CmdArg, SDIO_WAIT_RESP WaitResp)
{       
        u32 tmpreg;
       
        //先确保之前的命令都执行完成了,如果存在超时的,请清除掉
        while(SDIO->CTL & (BIT5 | BIT6 | 0X1F))
        {
                SDIO->CTL |= BIT14;                                        //SW_RESET
                SYS_DelayMS(1);
        }
       
        SDIO->ARG = CmdArg;                                                //参数
       
        tmpreg = SDIO->CTL;
        tmpreg &= ~(0X3F << 8);                                        //清除命令
        tmpreg |= (CmdIndex&0X3F) << 8;                        //设置新的命令index       
        if(SDIO_Response_Long == WaitResp)                //长响应R2
        {
                tmpreg |= SDIO_CTL_R2IEN_Msk;                //使能R2应答
        }
        else if(SDIO_Response_Short == WaitResp) //短响应R1
        {
                tmpreg |= SDIO_CTL_RIEN_Msk;                //使能R1应答
        }
          tmpreg |= SDIO_CTL_COEN_Msk;                        //使能命令发送
        //清除所有标志
        SDIO->INTSTS = SDIO->INTSTS;                        //清除中断状态
        SDIO->CTL = tmpreg;                                                //写入,执行
}



使用特权

评论回复
10
nawu|  楼主 | 2021-6-7 18:56 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_SetPower(bool isPowerUp)
* 功能                        :        SDIO电源控制
* 参数                        :        isPowerUp:TRUE:通电,为卡提供时钟;FALSE:掉电,停止时钟
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :        
*************************************************************************************************************************/
void SDIO_SetPower(bool isPowerUp)
{
       
        if(isPowerUp)
        {
                SDIO->ECTL |= 1<<(SDIO_GetPortSelect()&0x1);        //通电
        }
        else
        {
                SDIO->ECTL &= ~(1<<(SDIO_GetPortSelect()&0x1));//掉电
        }
}



使用特权

评论回复
11
nawu|  楼主 | 2021-6-7 18:57 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_SetPowerSaving(bool isSaving)
* 功能                        :        SDIO节能模式开关
* 参数                        :        isSaving:TRUE:仅在总线激活时使能 SDIO_CK;FALSE:始终使能 SDIO_CK 时钟
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         要实现节能模式,可在总线空闲时通过将 CLK_KEEP1 置 0来禁止 SDIO_CK 时钟输出
*************************************************************************************************************************/
void SDIO_SetPowerSaving(bool isSaving)
{
        if(isSaving)
        {
                SDIO->CTL &= ~BIT31;        //使能节能模式
        }
        else
        {
                SDIO->CTL |= BIT31;                //关闭节能模式
        }
}


使用特权

评论回复
12
nawu|  楼主 | 2021-6-7 18:58 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_StartDataTrans(bool isRead)
* 功能                        :        SDIO开始数据传输
* 参数                        :        isRead:是否是读取
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         数据传输必须首先写入到数据计时器寄存器和数据长度寄存器,然后才写入到数据控制寄存器。
                                        对于 SDIO 多字节传输,数据长度寄存器中的值必须在 1 到 512 之间。
*************************************************************************************************************************/
void SDIO_StartDataTrans(bool isRead)
{
        SDIO->INTSTS = SDIO->INTSTS;                                                //清除中断状态
        if(isRead)                                                                                        //读取方向
        {
                SDIO->CTL |= BIT2;
        }
        else //发送方向
        {
                SDIO->CTL |= BIT3;
        }
}  


使用特权

评论回复
13
nawu|  楼主 | 2021-6-7 18:59 | 只看该作者

/*************************************************************************************************************************
* 函数                        :        void SDIO_SetAndStartDataTrans(u8 *pDataBuff, bool isEnableReadData, SDIO_DataBlockSize SDIOBlockSize, u32 TransDataLen)
* 功能                        :        设置SDIO并开始准备数据传输
* 参数                        :        pDataBuff:传输的数据缓冲区;isEnableReadData:是否为读取数据;SDIOBlockSize:SDIO传输块大小;TransDataLen:传输数据长度
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         数据传输必须首先写入到数据计时器寄存器和数据长度寄存器,然后才写入到数据控制寄存器。
                                        对于 SDIO 多字节传输,数据长度寄存器中的值必须在 1 到 512 之间。
                                        会使能DMA传输
*************************************************************************************************************************/
void SDIO_SetAndStartDataTrans(u8 *pDataBuff, bool isEnableReadData, SDIO_DataBlockSize SDIOBlockSize, u32 TransDataLen)
{
        //初始化DMA
        SDIO_DMA->SA = (u32)pDataBuff;                                                                        //设置DMA数据传输地址
        //SDIO传输数据块大小设置
        SDIO_SetDataTransBlockSize(SDIOBlockSize);                                                //设置传输块大小
        //SDIO传输数据长度
        SDIO_SetDataTransLength(TransDataLen);                               
       
        SDIO->INTSTS = SDIO->INTSTS;                                                                        //清除中断状态       
        //数据读取方向
        if(isEnableReadData)                                                                                         //读数据,卡到控制器
        {
                SDIO->CTL |= BIT2;
        }
        else                                                                                                                         //写数据,控制器到卡
        {
                SDIO->CTL |= BIT3;
        }
}  


使用特权

评论回复
14
nawu|  楼主 | 2021-6-7 19:00 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_ClearDataTrans(void)
* 功能                        :        SDIO清除数据传输
* 参数                        :       
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         手册上说无需清除DTEN,但是实际使用发现DTEN并不会被清除。
*************************************************************************************************************************/
void SDIO_ClearDataTrans(void)
{
        u32 timeout = SDIO_TIMEOUT_US;//读等待超时计数器
       
        if(SDIO->CTL & (SDIO_CTL_DOEN_Msk | SDIO_CTL_DIEN_Msk))        //之前的数据传输未完成
        {
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                //SW_RESET
                while(SDIO->CTL & SDIO_CTL_SW_RST)
                {
                        timeout --;
                        Delay_US(1);
                }
                if(timeout == 0)
                {
                        DEBUG("复位SDIO命令失败\r\n");
                }
        }
        if((SDIO_DMA->INTSTS & 0x03) || (SDIO_DMA->CTL & BIT9))        //传输出错,或者DMA还在忙
        {
                SDIO_DMA->INTSTS = 0x03;        //清除错误
               
                timeout = SDIO_TIMEOUT_US;        //读等待超时计数器
                SDIO_DMA->CTL |= BIT1;                //复位DMA,会清除DMA相关配置寄存器
                while(SDIO_DMA->CTL & BIT1)
                {
                        timeout --;
                        Delay_US(1);
                }
                if(timeout == 0)
                {
                        DEBUG("复位SDIO DMA失败\r\n");
                }
        }
}  



使用特权

评论回复
15
nawu|  楼主 | 2021-6-7 19:01 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_SetDataTransTimeOut(u32 DataIimeOut)
* 功能                        :        SDIO传输数据超时设置
* 参数                        :        DataIimeOut:数据超时计数,以总线周期为准
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :        
*************************************************************************************************************************/
void SDIO_SetDataTransTimeOut(u32 DataIimeOut)
{
        SDIO->TMOUT = DataIimeOut;                        //以卡总线时钟周期表示的数据超时周期。
}  



使用特权

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

/*************************************************************************************************************************
* 函数                        :        void SDIO_SetDataTransBlockSize(SDIO_DataBlockSize DataBlockSize)
* 功能                        :        SDIO传输数据块大小设置
* 参数                        :        DataBlockSize:块大小
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :        
*************************************************************************************************************************/
void SDIO_SetDataTransBlockSize(SDIO_DataBlockSize DataBlockSize)
{
        SDIO->BLEN = DataBlockSize  & 0X7FF;
}  



使用特权

评论回复
17
nawu|  楼主 | 2021-6-7 19:03 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_SetDataTransAddr(u32 Addr)
* 功能                        :        SDIO要传输的数据地址
* 参数                        :        Addr:要传输的数据地址
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-12
* 最后修改时间         :         2020-09-12
* 说明                        :        
*************************************************************************************************************************/
void SDIO_SetDataTransAddr(u32 Addr)
{
        SDIO_DMA->SA = Addr;
}



使用特权

评论回复
18
nawu|  楼主 | 2021-6-7 19:04 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_SetDataTransLength(u32 DataLen)
* 功能                        :        SDIO传输数据长度
* 参数                        :        DataLen:传输数据长度(必须为块大小的整数倍)
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         对于块数据传输,数据长度寄存器中的值必须是块大小的倍数(请参见 SDIO_DCTRL)。 数据传输必须首先写入到数据计时器寄存器和数据长度寄存器,然后才写入到数据控制寄存器。
                                        对于 SDIO 多字节传输,数据长度寄存器中的值必须在 1 到 512 之间。
                                        块大小为512字节时,最大传输512*255=130560B,最小512字节。
*************************************************************************************************************************/
void SDIO_SetDataTransLength(u32 DataLen)
{
        u32 BlockByteSize = (SDIO->BLEN&0x7FF)+1;                                                                                                                //当前设置的块字节大小
        u32 tempreg;
       
        DataLen /= BlockByteSize;                                                                                                                                        //转换为要传输的快
        if(DataLen == 0)
        {
                DEBUG("传输大小不足一块,无法开始传输!\r\n");
                return;                                                                                                                                                                        //如果传输数量不足一块,则直接退出
        }
        else if(DataLen > 255)
        {
                DEBUG("最多一次传输255个块,超出范围了%d!\r\n", DataLen);
                DataLen = 255;
        }
       
          tempreg = SDIO->CTL;
        tempreg &= ~(0xFF<<16);        //清除块设置
        tempreg |= DataLen << 16;
        SDIO->CTL = tempreg;
}  


使用特权

评论回复
19
nawu|  楼主 | 2021-6-7 19:05 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        void SDIO_GetResponse(SDIO_RESP_TYPE RespIndex, u32 *pRespData)
* 功能                        :        获取返回响应状态
* 参数                        :        RespIndex:见SDIO_RESP_TYPE;pRespData:响应数据缓冲区
* 返回                        :        无
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-12
* 说明                        :         短响应需要1个字;长响应需要4个字的缓冲区
                                        短响应:u32[0]  卡状态 [31:0]
                                        长响应:u32[0] 卡状态 [127:96];[1]:卡状态 [95:64];[2]:卡状态 [63:32];[3]:卡状态 [31:1]0b
                                        NUC970 的SDH返回的长响应去掉了最低8位,并且最高字节在前面,最前面固定为0x3F(去掉)从第二字节开始,但是最低16bit都是0
*************************************************************************************************************************/
void SDIO_GetResponse(SDIO_RESP_TYPE RespIndex, u32 *pRespData)
{
        switch(RespIndex)
        {
                case SDIO_RESP_Short:
                {
                        pRespData[0] = SDIO_GetResp1CardStatu();        //获取R1响应的卡状态数据;
                }break;
                case SDIO_RESP_Long:
                {
                        u8 i;
                       
                        //只会响应16字节,但是最前面字节是无效的固定为0x3F,也就是缺少一字节有效响应
                        for(i = 0;i < 4;i ++)
                        {
                                pRespData = SDIO_BUFF->Buff[1+i*4+0];
                                pRespData <<= 8;
                                pRespData |= SDIO_BUFF->Buff[1+i*4+1];
                                pRespData <<= 8;
                                pRespData |= SDIO_BUFF->Buff[1+i*4+2];
                                pRespData <<= 8;
                                pRespData |= SDIO_BUFF->Buff[1+i*4+3];
                        }
                        pRespData[3] &= 0xFFFFFF00;
                       
                }break;
                default:break;
        }
}       



使用特权

评论回复
20
nawu|  楼主 | 2021-6-7 19:06 | 只看该作者
/*************************************************************************************************************************
* 函数                        :        SDIO_Error SDIO_CmdError(void)
* 功能                        :        获取指令执行状态(无响应)
* 参数                        :        无
* 返回                        :        SDIO_Error
* 依赖                        :        底层宏定义
* 作者                        :        cp1300@139.com
* 时间                        :        2020-09-04
* 最后修改时间         :         2020-09-04
* 说明                        :         无响应,只要命令发送完成了就退出
*************************************************************************************************************************/
SDIO_Error SDIO_CmdError(void)
{
        SDIO_Error Status = SDIO_OK;
       
        u32 timeout=SDIO_TIMEOUT_US;
       
        while (timeout)
        {
                timeout--;
                if((SDIO->CTL & SDIO_CTL_COEN_Msk) == 0) break;                        //命令发送完成了
                SDIO_DelayUS(1);
        }
        if(timeout==0)
        {
                SDIO->CTL |= SDIO_CTL_SW_RST;                                                        //复位SDIO控制器
                return SDIO_CMD_RSP_TIMEOUT;  
        }
       
        //清除所有标志
        SDIO->INTSTS = SDIO->INTSTS;
       
        return Status;
}         



使用特权

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

本版积分规则

73

主题

3308

帖子

3

粉丝