本帖最后由 风萧寒 于 2016-10-16 21:05 编辑
写的很详细
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循环。
|