采用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部分的代码需要作相应修改,详见附件。
|