SD卡SPI DMA模式FatFs读写,速度超1MB/s

2019-07-20 01:18发布

采用SPI DMA方式读写SD卡,适用于STM32F4。FatFs版本为最新的R0.11a。
一次读写512、1024、2048或4096字节,连续读写10s,然后计算读写速度。
测试的是一张8G的三星TF卡,以下是从串口获取的读写速度情况。
start reading ARTOGARD.WAV
fr: 0 num: 19522 br: 512
speed: 976.1kB/s
start reading ARTOGARD.WAV
fr: 0 num: 10866 br: 1024
speed: 1086.6kB/s
start reading ARTOGARD.WAV
fr: 0 num: 7660 br: 2048
speed: 1532.0kB/s
start reading ARTOGARD.WAV
fr: 0 num: 4827 br: 4096
speed: 1930.8kB/s

start writing 512.BIN
fr: 0 num: 6610 br: 512
speed: 330.5kB/s
start writing 1024.BIN
fr: 0 num: 3837 br: 1024
speed: 383.7kB/s
start writing 2048.BIN
fr: 0 num: 4037 br: 2048
speed: 807.4kB/s
start writing 4096.BIN
fr: 0 num: 3366 br: 4096
speed: 1346.4kB/s

SPI DMA方式核心部分代码如下,详见源码。 [mw_shl_code=c,true]void SD_DMA_Config(void) {     DMA_InitTypeDef DMA_InitStructure;     RCC_AHB1PeriphClockCmd(SD_DMA_RCC, ENABLE);     DMA_DeInit(SD_DMA_RX_STREAM);     DMA_DeInit(SD_DMA_TX_STREAM);     DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SD_SPI->DR));     DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;     DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;     DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;     DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;     DMA_InitStructure.DMA_Priority = DMA_Priority_High;     DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;     DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;     DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;     DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;     DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; //!!!     DMA_InitStructure.DMA_BufferSize = 0; //!!!     DMA_InitStructure.DMA_Channel = SD_DMA_RX_CHANNEL;     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0; //!!!     DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;     DMA_Init(SD_DMA_RX_STREAM, &DMA_InitStructure);     DMA_InitStructure.DMA_Channel = SD_DMA_TX_CHANNEL;     DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)0; //!!!     DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;     DMA_Init(SD_DMA_TX_STREAM, &DMA_InitStructure);     SPI_I2S_DMACmd(SD_SPI, SPI_I2S_DMAReq_Rx, ENABLE);     SPI_I2S_DMACmd(SD_SPI, SPI_I2S_DMAReq_Tx, ENABLE); }[/mw_shl_code]
SD卡读取设置(写入类似)
[mw_shl_code=c,true]// 设置接收通道 SD_DMA_RX_STREAM->CR |= DMA_MemoryInc_Enable; //自增 SD_DMA_RX_STREAM->M0AR = (uint32_t)pBuffer; SD_DMA_RX_STREAM->NDTR = BlockSize; //DMA_SetCurrDataCounter(SD_DMA_RX_STREAM, BlockSize); // 设置发送通道 SD_DMA_TX_STREAM->CR &= ~DMA_MemoryInc_Enable; //不自增 SD_DMA_TX_STREAM->M0AR = (uint32_t)&Dummy_Send; SD_DMA_TX_STREAM->NDTR = BlockSize; //DMA_SetCurrDataCounter(SD_DMA_TX_STREAM, BlockSize); // 启动 SD_DMA_RX_STREAM->CR |= DMA_SxCR_EN; //先启动接收 //DMA_Cmd(SD_DMA_RX_STREAM, ENABLE); while(!(SD_DMA_RX_STREAM->CR & DMA_SxCR_EN)); //while(DMA_GetCmdStatus(SD_DMA_RX_STREAM) == DISABLE); SD_DMA_TX_STREAM->CR |= DMA_SxCR_EN; //再启动发送 //DMA_Cmd(SD_DMA_TX_STREAM, ENABLE); while(!(SD_DMA_TX_STREAM->CR & DMA_SxCR_EN)); //while(DMA_GetCmdStatus(SD_DMA_TX_STREAM) == DISABLE); // 等待完成 while(!((SD_DMA->HISR & RESERVED_MASK) & SD_DMA_TX_TCIF)); //while(!DMA_GetFlagStatus(SD_DMA_TX_STREAM, SD_DMA_TX_TCIF)); while(!((SD_DMA->LISR & RESERVED_MASK) & SD_DMA_RX_TCIF)); //while(!DMA_GetFlagStatus(SD_DMA_RX_STREAM, SD_DMA_RX_TCIF)); // 清除完成标志 SD_DMA->LIFCR = SD_DMA_RX_TCIF & RESERVED_MASK; //清除接收完成标志 //DMA_ClearFlag(SD_DMA_RX_STREAM, SD_DMA_RX_TCIF); SD_DMA->HIFCR = SD_DMA_TX_TCIF & RESERVED_MASK; //清除发送完成标志 //DMA_ClearFlag(SD_DMA_TX_STREAM, SD_DMA_TX_TCIF); // 停止 SD_DMA_TX_STREAM->CR &= ~DMA_SxCR_EN; //DMA_Cmd(SD_DMA_TX_STREAM, DISABLE); while(SD_DMA_TX_STREAM->CR & DMA_SxCR_EN); //while(DMA_GetCmdStatus(SD_DMA_TX_STREAM) == ENABLE); SD_DMA_RX_STREAM->CR &= ~DMA_SxCR_EN; //DMA_Cmd(SD_DMA_RX_STREAM, DISABLE); while(SD_DMA_RX_STREAM->CR & DMA_SxCR_EN); //while(DMA_GetCmdStatus(SD_DMA_RX_STREAM) == ENABLE);[/mw_shl_code] STM32F3与F4的DMA存在一些区别,故DMA部分的代码需要作相应修改,详见附件。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。