2013-01-26 11:30 AM
Hello to all,
I have a design where cpu has to transfer blocks of data to a uSD card working in SPI2 mode. My routine is : static void SPIblockTxDMA(uint8_t *SD_Buffer_Tx,uint16_t Len) { SPI_Cmd(SPI_SDMEM, DISABLE); DMA_Cmd(SPI_SDMEM_Tx_DMA_Channel, DISABLE); DMA_ClearFlag(SPI_SDMEM_TX_GL_DMA_FLAG); SPI_SDMEM_Tx_DMA_Channel->CNDTR = Len; SPI_SDMEM_Tx_DMA_Channel->CMAR = (uint32_t)SD_Buffer_Tx; SPI_SDMEM_Tx_DMA_Channel->SPI_SDMEM_Tx_CCR |= DMA_CCR2_MINC; DMA_Cmd(SPI_SDMEM_Tx_DMA_Channel, ENABLE); // Enable DMA channels SPI_Cmd(SPI_SDMEM, ENABLE); while(!DMA_GetFlagStatus(SPI_SDMEM_Tx_DMA_FLAG)); while(!SPI_I2S_GetFlagStatus(SPI_SDMEM, SPI_I2S_FLAG_TXE)); while(SPI_I2S_GetFlagStatus(SPI_SDMEM, SPI_I2S_FLAG_BSY)); DMA_Cmd(SPI_SDMEM_Tx_DMA_Channel, DISABLE); } The routine works perfectly if SD_Buffer_Tx is in internal SRAM. If SD_Buffer_Tx is in external SRAM (which is 8 bits wide 55nS access time) it doesn't work all the times. It's behaviour changes every time I change something in my project, for example adding an irrelevant variable or some code elsewhere. The same code for reading through SPI always works perfectly : tatic void SPIblockRxDMA(uint8_t *SD_Buffer_Rx,uint16_t Len) { BYTE dummy = 0xff; DMA_Cmd(SPI_SDMEM_Rx_DMA_Channel, DISABLE); DMA_ClearFlag(SPI_SDMEM_RX_GL_DMA_FLAG); SPI_SDMEM_Rx_DMA_Channel->CNDTR = Len; SPI_SDMEM_Rx_DMA_Channel->CMAR = (uint32_t)SD_Buffer_Rx; DMA_Cmd(SPI_SDMEM_Rx_DMA_Channel, ENABLE); DMA_Cmd(SPI_SDMEM_Tx_DMA_Channel, DISABLE); DMA_ClearFlag(SPI_SDMEM_TX_GL_DMA_FLAG); SPI_SDMEM_Tx_DMA_Channel->CNDTR = Len; SPI_SDMEM_Tx_DMA_Channel->SPI_SDMEM_Tx_CCR &=~DMA_CCR2_MINC; SPI_SDMEM_Tx_DMA_Channel->CMAR = (uint32_t)&dummy; DMA_Cmd(SPI_SDMEM_Tx_DMA_Channel, ENABLE); while(!DMA_GetFlagStatus(SPI_SDMEM_Tx_DMA_FLAG)); while(SPI_I2S_GetFlagStatus(SPI_SDMEM, SPI_I2S_FLAG_TXE) != SET); while(SPI_I2S_GetFlagStatus(SPI_SDMEM, SPI_I2S_FLAG_BSY) != RESET); while(!DMA_GetFlagStatus(SPI_SDMEM_Rx_DMA_FLAG)); } I tried different SPI dividers but it seems that speed is not the problem. In my calling function replacing : SPIblockTxDMA(buff,512); with : wc = 512; do { spi_byte(*buff++); spi_byte(*buff++); } while(--wc); ie with a straight copy loop, everything works like a charm. Taking into account the errata regarding the limitation of multiple masters in FSMC controlled peripherals (in our case ext SRAM) I modified every external variable that may be accessed by interrupt handlers during the DMA transfer although with no effect. Are there any known issues regarding external SRAM DMA to SPI transfers ? Any help would be appreciated Thanks in advance, Angelo #external-sram #spi #dma2013-01-26 05:28 PM
It's behaviour changes every time I change something in my project, for example adding an irrelevant variable or some code elsewhere.
Might make you wonder what the compiler/linker are doing, and how these trivial changes are impacting the issue? Perhaps some alignment problem? Anyway these are symptoms that should not be ignored.2013-01-28 01:39 AM
Thanks for your answer Clive1. What kind of alignment is needed if buffers are 8 bit ?
The problem is that since buffers are many and mostly dynamic I cannot control their alignment easily. Experimentally I tried to copy to an internal buffer first but this is not a serious solution.