初级会员

- 积分
- 67
- 金钱
- 67
- 注册时间
- 2012-7-26
- 在线时间
- 10 小时
|
10金钱
本帖最后由 lrjray 于 2017-10-21 01:01 编辑
最近使用的调试STM32F4的SDIO加DMA,加FATFS,已经调试通过,但有一些疑问
SD_WriteMultiBlocks函数的参数依次为(源地址,目的地址,扇区大小,扇区数),使用DMA传输时,数据手册指明DMA的NDTR为数据的长度,范围(0~65535),也就是说DMA一次最大传输64KB字节,但SD_WriteMultiBlocks写入的大小为“扇区大小*扇区数”,也就是说SD_WriteMultiBlocks传递的参数可能溢出,网上找了多份FatFs代码,没有发现对此处做了参数检查,但多次测试没有问题。
[mw_shl_code=c,true]SD_Error SD_WriteMultiBlocks(uint8_t *writebuff, uint32_t WriteAddr, uint16_t BlockSize, uint32_t NumberOfBlocks)
{
SD_Error errorstatus = SD_OK;
TransferError = SD_OK;
TransferEnd = 0;
StopCondition = 1;
SDIO->DCTRL = 0x0;
if (CardType == SDIO_HIGH_CAPACITY_SD_CARD)
{
BlockSize = 512;
WriteAddr /= 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);
}
/*!< To improve performance */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t) (RCA << 16);
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_APP_CMD;
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);
}
/*!< To improve performance */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)NumberOfBlocks;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_SET_BLOCK_COUNT;
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_BLOCK_COUNT);
if (errorstatus != SD_OK)
{
return(errorstatus);
}
/*!< Send CMD25 WRITE_MULT_BLOCK with argument data address */
SDIO_CmdInitStructure.SDIO_Argument = (uint32_t)WriteAddr;
SDIO_CmdInitStructure.SDIO_CmdIndex = SD_CMD_WRITE_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_WRITE_MULT_BLOCK);
if (SD_OK != errorstatus)
{
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_ToCard;
SDIO_DataInitStructure.SDIO_TransferMode = SDIO_TransferMode_Block;
SDIO_DataInitStructure.SDIO_DPSM = SDIO_DPSM_Enable;
SDIO_DataConfig(&SDIO_DataInitStructure);
SDIO_ITConfig(SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_DATAEND | SDIO_IT_RXOVERR | SDIO_IT_STBITERR, ENABLE);
SDIO_DMACmd(ENABLE);
SD_LowLevel_DMA_TxConfig((uint32_t *)writebuff, (NumberOfBlocks * BlockSize));
return(errorstatus);
}[/mw_shl_code]
此处88行,用“扇区大小及扇区数计算总长度并写入,没有检查范围”,见如下函数
[mw_shl_code=c,true]void SD_LowLevel_DMA_TxConfig(uint32_t * BufferSRC, uint32_t BufferSize)
{
DMA_ClearFlag(SD_SDIO_DMA_STREAM, SD_SDIO_DMA_FLAG_FEIF | SD_SDIO_DMA_FLAG_DMEIF | SD_SDIO_DMA_FLAG_TEIF | SD_SDIO_DMA_FLAG_HTIF | SD_SDIO_DMA_FLAG_TCIF);
/* DMA2 Stream3 or Stream6 disable */
DMA_Cmd(SD_SDIO_DMA_STREAM, DISABLE);
/* DMA2 Stream3 or Stream6 Config */
DMA_DeInit(SD_SDIO_DMA_STREAM);
/* Set DMA Structure */
SDDMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)BufferSRC;
SDDMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
SDDMA_InitStructure.DMA_BufferSize = BufferSize;
DMA_Init(SD_SDIO_DMA_STREAM, &SDDMA_InitStructure);
DMA_ITConfig(SD_SDIO_DMA_STREAM, DMA_IT_TC, ENABLE);
DMA_FlowControllerConfig(SD_SDIO_DMA_STREAM, DMA_FlowCtrl_Peripheral);
/* DMA2 Stream3 or Stream6 enable */
DMA_Cmd(SD_SDIO_DMA_STREAM, ENABLE);
}
[/mw_shl_code]
也就是是该函数写入超过64KB可能出错,但实际使用多种张卡测试发现
直接调用SD_WriteMultiBlocks函数,发现一次写入长度小于等于256KB,数据是正常的,这远远大于DMA规定的64KB
直接调用SD_WriteMultiBlocks函数,一次写入长度512KB,前256KB数据是正常的,后256KB同先256KB的内容,不是预期写入的内容
直接调用SD_WriteMultiBlocks函数,一次写入长度1024KB,前256KB数据是正常的,后3个256KB块的内容同第一个256KB的内容,不是预期写入的内容
非常困惑,求大家指导
|
|