本帖最后由 ZDawn 于 2018-1-9 14:31 编辑
用别的板子烧了原子哥的SDIO程序之后,在 “查找SD卡的SCR寄存器值” 的函数子函数里面会死循环,FIFO无接收数据,导致SDIO->STA值一直为零。但是这种情况仅限于普通的上电。
我用keil 和JLINK在线调试的话第一次也会进入死循环,但是用keil 调试的复位按钮之后,再重新执行就能正常运行,不再进入那个死循环。
正常上电的话偶尔等1分钟也能读到FIFO的值从而跳出死循环。
请问这会是什么原因导致每次的第一次上电时候,SDIO->STA值一直为零??(查询模式和DMA模式都是一样的结果)
以下是程序:
//查找SD卡的SCR寄存器值
//rca:卡相对地址
//pscr:数据缓存区(存储SCR内容)
//返回值:错误状态
SD_Error FindSCR(u16 rca,u32 *pscr)
{
u8 ii=50;
u32 index = 0;
SD_Error errorstatus = SD_OK;
u32 tempscr[2]={0,0};
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)8; //发送CMD16,短响应,设置Block Size为8字节
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN; // cmd16
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //r1
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
delay_ms(1);
errorstatus=CmdResp1Error(SD_CMD_SET_BLOCKLEN);
if(errorstatus!=SD_OK)return errorstatus;
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) RCA << 16;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;//发送CMD55,短响应
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short;
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
errorstatus=CmdResp1Error(SD_CMD_APP_CMD);
if(errorstatus!=SD_OK)return errorstatus;
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DataLength = 8; //8个字节长度,block为8字节,SD卡到SDIO.
SDIO_DataInitStructure.SDIO_DataBlockSize = SDIO_DataBlockSize_8b ; //块大小8byte
SDIO_DataInitStructure.SDIO_TransferDir = SDIO_TransferDir_ToSDIO;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataConfig(&SDIO_DataInitStructure);
// delay_ms(1);
SDIO_CmdInitStructure.SDIO_Argument = 0x0;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SD_APP_SEND_SCR; //发送ACMD51,短响应,参数为0
SDIO_CmdInitStructure.SDIO_Response = SDIO_Response_Short; //r1
SDIO_CmdInitStructure.SDIO_Wait = SDIO_Wait_No;
SDIO_CmdInitStructure.SDIO_CPSM = SDIO_CPSM_Enable;
SDIO_SendCommand(&SDIO_CmdInitStructure);
// delay_ms(1);
errorstatus=CmdResp1Error(SD_CMD_SD_APP_SEND_SCR);
if(errorstatus!=SD_OK)return errorstatus;
// delay_ms(1);
//进入死循环的段落,if 语句一直不通过判定
while(!(SDIO->STA&(SDIO_FLAG_RXOVERR|SDIO_FLAG_DCRCFAIL|SDIO_FLAG_DTIMEOUT|SDIO_FLAG_DBCKEND|SDIO_FLAG_STBITERR)))
{
if(SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)//接收FIFO数据可用
{
*(tempscr+index)=SDIO_ReadData(); //读取FIFO内容
index++;
if(index>=2)break;
}
}
if(SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET) //数据超时错误
{
SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT); //清错误标志
return SD_DATA_TIMEOUT;
}else if(SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET) //数据块CRC错误
{
SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL); //清错误标志
return SD_DATA_CRC_FAIL;
}else if(SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR) != RESET) //接收fifo上溢错误
{
SDIO_ClearFlag(SDIO_FLAG_RXOVERR); //清错误标志
return SD_RX_OVERRUN;
}else if(SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET) //接收起始位错误
{
SDIO_ClearFlag(SDIO_FLAG_STBITERR);//清错误标志
return SD_START_BIT_ERR;
}
SDIO_ClearFlag(SDIO_STATIC_FLAGS);//清除所有标记
//把数据顺序按8位为单位倒过来.
*(pscr+1)=((tempscr[0]&SD_0TO7BITS)<<24)|((tempscr[0]&SD_8TO15BITS)<<8)|((tempscr[0]&SD_16TO23BITS)>>8)|((tempscr[0]&SD_24TO31BITS)>>24);
*(pscr)=((tempscr[1]&SD_0TO7BITS)<<24)|((tempscr[1]&SD_8TO15BITS)<<8)|((tempscr[1]&SD_16TO23BITS)>>8)|((tempscr[1]&SD_24TO31BITS)>>24);
return errorstatus;
}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
你说的软复位是指单片机软复位?
keil那个复位
有一些我是这么解决的,在需要初始化TF卡的时候降低主频,初始化完毕后再次拉高主频。
然后我也用过别的可行的方法,就是不降低主频的情况下,由于有时候热插拔TF卡,会造成TF卡初始化失败并且卡死在某些循环代码里面,所以我找到所有会卡死的位置,添加“卡死次数判断”,要是连续循环执行n次失败的话,就认为是“TF卡初始化卡死了”,然后直接退出初始化函数,等程序下次再执行TF卡初始化的时候就成功了。
一周热门 更多>