stm32 3.5固件库带sdio版本V4.5.0 bug修改
来源:互联网 发布:js如何引入模块 编辑:程序博客网 时间:2024/06/08 00:32
转帖,原出处 http://blog.csdn.net/cokewei/article/details/7343915
写的很详细
1:SD_WaitReadOperation()或者SD_WaitWriteOperation()函数死循环
原因:数据传输错误导致传输中断,无法满足退出等待的判断条件。
代码分析:
SD_Error SD_WaitReadOperation(void)
{
SD_Error errorstatus = SD_OK;
while ((SD_DMAEndOfTransferStatus() == RESET) && (TransferEnd == 0) && (TransferError == SD_OK))
{}
if (TransferError != SD_OK)
{
return(TransferError);
}
return(errorstatus);
}
代码中用了while()是导致死循环的原因。TransferEnd ,TransferError 这两个参数是在中断中修改的, SD_DMAEndOfTransferStatus() 的结束条件是DMA传输结束。
看中断例程:
SD_Error SD_ProcessIRQSrc(void)
{
if (StopCondition == 1)
{
SDIO->ARG = 0x0;
SDIO->CMD = 0x44C;
TransferError = CmdResp1Error(SD_CMD_STOP_TRANSMISSION);
}
else
{
TransferError = SD_OK;
}
SDIO_ClearITPendingBit(SDIO_IT_DATAEND);
SDIO_ITConfig(SDIO_IT_DATAEND, DISABLE);
TransferEnd = 1;
return(TransferError);
}
中断配置为数据传输结束中断SDIO_ITConfig(SDIO_IT_DATAEND, ENABLE);
数据传输出错导致传输中断的情况下,SD_DMAEndOfTransferStatus的判断为false,TransferEnd 和TransferError 的状态也不会改变,导致while循环无法退出。
解决:
中断配置为SDIO_ITConfig(SDIO_IT_RXOVERR|SDIO_IT_DTIMEOUT|SDIO_IT_DCRCFAIL|SDIO_IT_DATAEND, ENABLE);
中断例程修改:
SD_Error SD_ProcessIRQSrc(void)
{
if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT);
TransferError = SD_DATA_TIMEOUT;
}
else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL);
TransferError = SD_DATA_CRC_FAIL;
}
else if (SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_RXOVERR);
TransferError = SD_RX_OVERRUN;
}
else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_STBITERR);
TransferError = SD_START_BIT_ERR;
}
else
{
if (StopCondition == 1)
{
SDIO->ARG = 0x0;
SDIO->CMD = 0x44C;
TransferError = CmdResp1Error(SD_CMD_STOP_TRANSMISSION);
}
else
{
TransferError = SD_OK;
}
}
SDIO_ITConfig(SDIO_IT_RXOVERR|SDIO_IT_DTIMEOUT|SDIO_IT_DCRCFAIL|SDIO_IT_DATAEND, DISABLE);
TransferEnd = 1;
return(TransferError);
}
这么做的作用是发生错误时也会进入中断,即使dma没有结束,也能退出while循环。
2:sd_init()过程失败
可能性1:按照SD规范,初始化之前需要有74个或更多个clock让sd卡同步,例程中把clock开起来后直接发送cmd0,没有同步clock,所以先修改SD_PowerON函数内SDIO_ClockCmd(ENABLE);调用之后增加200us延时。
可能性2:发生SDIO_FLAG_DCRCFAIL错误。
修改SDIO_TRANSFER_CLK_DIV 来修改数据传输速率。
按照ST例程的注释,数据传输速率不能超过25M,但是原先配置SDIO_TRANSFER_CLK_DIV=0,按照72M主频计算的话传输速度达到72/2=36M,不出错就怪了。
我现在配置SDIO_TRANSFER_CLK_DIV=2后正常。
可能性3:固件库使用不正确。使用V4.5的例程,固件库需要用V3.5.0的,试过3.2的固件库会失败。
3:SD_DMAEndOfTransferStatus函数内没有清标志位,按照datasheet,标志位是由手动清除的。
4:SD_ReadBlock()发生SDIO_FLAG_DCRCFAIL错误。
一开始是实践发现,先执行一下SD_ReadMultiBlocks函数,以后再执行SD_ReadBlock就正常了。很奇怪的现象吧。后来查阅了一些资料,发现SD卡的block大小并不是固定的,可以配置为512,1024等,于是怀疑是block大小配置不正确导致。检查发现SD_ReadBlock操作之前没有设置sd卡block大小,也就是cmd16,加入这个代码就像行了
/*!< Set Block Size for Card */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
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_SET_BLOCKLEN);
if (SD_OK != errorstatus)
{
return(errorstatus);
}
其实这个操作并不是每次读操作都要执行的,如果中途不改变block大小,只要初始化的时候设置一次就可以了
多块读的函数如下:
SD_Error SD_ReadMultiBlocks(uint8_t *readbuff, uint32_t ReadAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
{
#if defined (SD_POLLING_MODE)
uint32_t count = 0, *tempbuff = (uint32_t *)readbuff;
#endif
SD_Error errorstatus = SD_OK;
TransferError = SD_OK;
TransferEnd = 0;
StopCondition = 1;
SDIO->DCTRL = 0x0;
/*if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
{
BlockSize = 512;
ReadAddr >>= 9;
}*/
if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
{
BlockSize = 512;
ReadAddr /= 512;
}
/*!< Set Block Size for Card */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
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_SET_BLOCKLEN);
if (SD_OK != errorstatus)
{
return(errorstatus);
}
/*!< Set Block Size for Card */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) BlockSize;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCKLEN;
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_SET_BLOCKLEN);
if (SD_OK != errorstatus)
{
return(errorstatus);
}
if(NumberOfBlocks > 0)
{
/* Common to all modes */
if (NumberOfBlocks * BlockSize > SD_MAX_DATA_LENGTH)
{
errorstatus = SD_INVALID_PARAMETER;
return(errorstatus);
}
SDIO_DataInitStructure.SDIO_DataTimeOut = SD_DATATIMEOUT;
SDIO_DataInitStructure.SDIO_DataLength = NumberOfBlocks * BlockSize;
SDIO_DataInitStructure.SDIO_DataBlockSize = (uint32_t) 9 << 4;
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);
/*!< Send CMD18 READ_MULT_BLOCK with argument data address */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)ReadAddr;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_READ_MULT_BLOCK;
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_READ_MULT_BLOCK);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
}
#if defined (SD_POLLING_MODE)
/* Polling mode */
while (!(SDIO->STA &(SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DATAEND | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_STBITERR)))
{
if (SDIO_GetFlagStatus(SDIO_FLAG_RXFIFOHF) != RESET)
{
for (count = 0; count < SD_HALFFIFO; count++)
{
*(tempbuff + count) = SDIO->FIFO;//SDIO_ReadData();
}
tempbuff += SD_HALFFIFO;
}
}
if (SDIO_GetFlagStatus(SDIO_FLAG_DTIMEOUT) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_DTIMEOUT);
errorstatus = SD_DATA_TIMEOUT;
return(errorstatus);
}
else if (SDIO_GetFlagStatus(SDIO_FLAG_DCRCFAIL) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_DCRCFAIL);
errorstatus = SD_DATA_CRC_FAIL;
return(errorstatus);
}
else if (SDIO_GetFlagStatus(SDIO_FLAG_RXOVERR) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_RXOVERR);
errorstatus = SD_RX_OVERRUN;
return(errorstatus);
}
else if (SDIO_GetFlagStatus(SDIO_FLAG_STBITERR) != RESET)
{
SDIO_ClearFlag(SDIO_FLAG_STBITERR);
errorstatus = SD_START_BIT_ERR;
return(errorstatus);
}
while (SDIO_GetFlagStatus(SDIO_FLAG_RXDAVL) != RESET)
{
*tempbuff = SDIO->FIFO;//SDIO_ReadData();
tempbuff++;
}
//for(count=0;count<1000000;count++);
if (SDIO_GetFlagStatus(SDIO_FLAG_DATAEND) != RESET)
{
/* In Case Of SD-CARD Send Command STOP_TRANSMISSION */
if ((SDIO_STD_CAPACITY_SD_CARD_V1_1 == CardType) || (SDIO_HIGH_CAPACITY_SD_CARD == CardType) || (SDIO_STD_CAPACITY_SD_CARD_V2_0 == CardType))
{
/* Send CMD12 STOP_TRANSMISSION */
SDIO_CmdInitStructure.SDIO_Argument = 0x0;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_STOP_TRANSMISSION;
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_STOP_TRANSMISSION);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
}
}
/* Clear all the static flags */
SDIO_ClearFlag(SDIO_STATIC_FLAGS);
#elif defined (SD_DMA_MODE)
SDIO_ITConfig(SDIO_IT_RXOVERR|SDIO_IT_DTIMEOUT|SDIO_IT_DCRCFAIL|SDIO_IT_DATAEND, ENABLE);
SDIO_DMACmd(ENABLE);
SD_LowLevel_DMA_RxConfig((uint32_t *)readbuff, BlockSize * NumberOfBlocks);
#endif
errorstatus = SD_WaitReadOperation(); ////121226 等待读操作完成
if (errorstatus != SD_OK)
{
return(errorstatus);
}
while(SD_GetStatus()!=SD_TRANSFER_OK);
return(errorstatus);
}
- stm32 3.5固件库带sdio版本V4.5.0 bug修改
- 20130408-[转]stm32 3.5固件库带sdio版本V4.5.0 bug修改
- stm32 sdio调试,修改官方例程bug,已成功调通SDIO读取SD卡
- fastreport v4.7.5版本中,一个资源处理bug
- openstack bug跨版本修改
- 对于新近STM32上SDIO用4bitDMA模式读写SHDC的驱动修改
- STM32 + SDIO + FATFS 调试记录
- STM32 SDIO 报错 SD_RX_OVERRUN
- STM32 USB SD读卡器(SDIO)
- OneThink 1.0版本中的BUG修改
- STM32的SDIO-WIFI资料归纳
- STM32的SDIO-WIFI资料归纳
- xtrabackup版本较低触发nfs-v4的bug:cp: failed to preserve ownership: Invalid argument
- 修改 lucene Highlighter.net 2.0 版本一处Bug
- Bean Query 修改Bug的版本(1.0.1)已发布
- SDIO
- SDIO
- SDIO
- 2第一个JAVA程序
- 从10到13年
- 计算程序的时间
- 题目27 水池数目
- POJ 3625 Building Roads 存在建好的边
- stm32 3.5固件库带sdio版本V4.5.0 bug修改
- 3JAVA的注泽
- PCB布线技巧
- python3-postgresql
- HDU2527:Safe Or Unsafe(哈弗曼树)
- 路
- 20131118作业提交
- android开发
- 数组的反射