看完书,我自己重新写了一遍代码。
写代码过程中,对DMA以下标绿的部分很不以为意。
1 void SD_DMA_TxConfig(uint32_t *DMA_Tx_Buf, uint32_t BufferSize) 2 { 3 DMA_InitTypeDef DMA_InitStruct; 4 5 /*Clock Enable-----In GPIO Config*/ 6 7 /*Flag Clear----------------------------*/ 8 DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4); 9 10 /*!< DMA2 Channel4 disable */ 11 DMA_Cmd(DMA2_Channel4, DISABLE); 12 13 /*-------------- Reset DMA init structure parameters values ------------------*/ 14 DMA_InitStruct.DMA_PeripheralBaseAddr = SD_FIFO_ADDR; 15 DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)DMA_Tx_Buf; 16 DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralDST; 17 DMA_InitStruct.DMA_BufferSize = BufferSize / 4; //除以4,把字转成字节单位 18 DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable; 19 DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable; 20 DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Word; 21 DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_Word; 22 DMA_InitStruct.DMA_Mode = DMA_Mode_Normal; 23 DMA_InitStruct.DMA_Priority = DMA_Priority_High; 24 DMA_InitStruct.DMA_M2M = DMA_M2M_Disable; 25 26 DMA_Init(DMA2_Channel4,&DMA_InitStruct); 27 DMA_Cmd(DMA2_Channel4, ENABLE); 28 } 29 30 31 /** 32 *@brief: Config_SD_DMA_Rx Function 33 Src:SD_card 34 Des:Buf 35 *@params:None 36 *@retvals:None 37 */ 38 void SD_DMA_RxConfig(uint32_t *DMA_Rx_Buf, uint32_t BufferSize) 39 { 40 DMA_InitTypeDef DMA_InitStruct; 41 42 /*Clock Enable-----In GPIO Config*/ 43 44 /*Flags Clear----------------*/ 45 DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);//清除DMA标志位 46 47 /*!< DMA2 Channel4 disable */ 48 DMA_Cmd(DMA2_Channel4, DISABLE); //SDIO为第四通道 49 50 51 /*-------------- Reset DMA init structure parameters values ------------------*/ 52 DMA_InitStruct.DMA_PeripheralBaseAddr = SD_FIFO_ADDR; (代码同上,此处省略此处 DMA_InitStruct 结构体初始化......)
64 DMA_Init(DMA2_Channel4,&DMA_InitStruct); 65 DMA_Cmd(DMA2_Channel4, ENABLE); 66 }
首先要分析的是这两个代码在哪里调用的?
在读单个块的函数中, SD_ReadBlock 通过下面的代码实现数据传输,其中第4行调用了SD_DMA_RxConfig()。
1 #elif defined (SD_DMA_MODE) 2 SDIO_ITConfig(SDIO_IT_DATAEND, ENABLE); 3 SDIO_DMACmd(ENABLE); 4 SD_DMA_RxConfig((uint32_t *)readbuff, BlockSize);
//读多个块第4行为 SD_DMA_RxConfig((uint32_t *)readbuff, (NumberOfBlocks * BlockSize));
同理,在写单个块的函数 SD_WriteBlock 中,也有相同内容。
1 #elif defined (SD_DMA_MODE) 2 SDIO_ITConfig(SDIO_IT_DATAEND, ENABLE); 3 SD_DMA_TxConfig((uint32_t *)writebuff, BlockSize); 4 SDIO_DMACmd(ENABLE);
经过我的实验,上面代码下面这部分内容(DMA清楚标志)取掉也不会有影响。
但是为了程序的稳健性,最好还是加上。
7 /*Flag Clear----------------------------*/ 8 DMA_ClearFlag(DMA2_FLAG_TC4 | DMA2_FLAG_TE4 | DMA2_FLAG_HT4 | DMA2_FLAG_GL4);
但是不能没有这行代码:
10 /*!< DMA2 Channel4 disable */ 11 DMA_Cmd(DMA2_Channel4, DISABLE);
一种原因是:在 SD_SingleBlockTest(void) 中,一开始进行写,已经使能了DMA传输,
当接下来进行读的时候,如果不先让DMA暂时停止(此时需要修改的DMA结构体参数还没改),那么可能导致数据传输的错乱。
也就是说:有可能DMA本来应该把数据从SD卡传到SDIO,但是由于DMA仍在工作。
同时,在SD_ReadBlock代码中,SDIO_DMACmd(ENABLE);在SD_DMA_RxConfig的前面。因此DMA把数据从SDIO传到SD卡了。
总结一下:就是在多次进行不同方向的DMA传输的时候,记得暂时现将DMA功能关闭一下,防止误操作,本来不应该传输的传出去了。
标签:DMA,OK,TRANSFER,DMA2,SDIO,FLAG,InitStruct,SD From: https://www.cnblogs.com/FBsharl/p/17461955.html