cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 ext SRAM to SPI failure

abrous3d
Associate II
Posted on January 26, 2013 at 20:30

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 #dma
2 REPLIES 2
Posted on January 27, 2013 at 02:28

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.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
abrous3d
Associate II
Posted on January 28, 2013 at 10:39

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.