AnsweredAssumed Answered

STM32F103 ext SRAM to SPI failure

Question asked by brousalis.angelo on Jan 26, 2013
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




 


Outcomes