AnsweredAssumed Answered

STM32F4 Discovery SPI with DMA Ghost byte

Question asked by afzal.uzair on Jul 10, 2013
Latest reply on Jul 11, 2013 by waclawek.jan
I want to write a buffer into Winbond SPI flash using SPI DMA. When I write buffer, DMA write a null byte at first location and then start writing my buffer from second location and hence writes one character less than it should write. I donot know from where this null byte is comming. For example when I write "ALI" at 0x00 address, Data read from flash is "<NULL>AL". Without DMA all works fine. Below is the Code(I have included only necessary functions)

uint8_t TxBuffer1[] = "ALI";


#define countof(a)   (sizeof(a) / sizeof(*(a)))
#define TxBufferSize1   (countof(TxBuffer1)-1)

/**
  * @brief  Initializes the peripherals used by the SPI FLASH driver.
  * @param  None
  * @retval None
  */
void sFLASH_Init(void)
{
  SPI_InitTypeDef  SPI_InitStructure;


  sFLASH_LowLevel_Init();
    
  /*!< Deselect the FLASH: Chip Select high */
  sFLASH_CS_HIGH();


  /*!< SPI configuration */
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;// also works at SPI_CPOL_Low with SPI_CPHA_1Edge
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft ;
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;//(APB1/2=21MHz SPI Clock)
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
  SPI_InitStructure.SPI_CRCPolynomial = 7;
  SPI_Init(sFLASH_SPI, &SPI_InitStructure);


  /*!< Enable the sFLASH_SPI  */
  SPI_Cmd(sFLASH_SPI, ENABLE);
}
/**
  * @brief  Writes more than one byte to the FLASH with a single WRITE cycle 
  *         (Page WRITE sequence).
  * @note   The number of byte can't exceed the FLASH page size.
  * @param  pBuffer: pointer to the buffer  containing the data to be written
  *         to the FLASH.
  * @param  WriteAddr: FLASH's internal address to write to.
  * @param  NumByteToWrite: number of bytes to write to the FLASH, must be equal
  *         or less than "sFLASH_PAGESIZE" value.
  * @retval None
  */
void sFLASH_DMA_WritePage(uint32_t WriteAddr)
{     
  /*!< Enable the write access to the FLASH */
  sFLASH_WriteEnable();
  /*!< Select the FLASH: Chip Select low */
  sFLASH_CS_LOW();
  /*!< Send "Write to Memory " instruction */
  sFLASH_SendByte(sFLASH_CMD_WR_PAGE);
  /*!< Send WriteAddr high nibble address byte to write to */
  sFLASH_SendByte((WriteAddr & 0xFF0000) >> 16);
  /*!< Send WriteAddr medium nibble address byte to write to */
  sFLASH_SendByte((WriteAddr & 0xFF00) >> 8);
  /*!< Send WriteAddr low nibble address byte to write to */
  sFLASH_SendByte(WriteAddr & 0xFF);

  while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);
     
  /*!< while there is data to be written on the FLASH */
  DMA_Cmd(DMA1_Stream4, ENABLE);
     
}
/**
  * @brief  Sends a byte through the SPI interface and return the byte received
  *         from the SPI bus.
  * @param  byte: byte to send.
  * @retval The value of the received byte.
  */
uint8_t sFLASH_SendByte(uint8_t byte)
{
  /*!< Loop while DR register in not emplty */
  while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);


  /*!< Send byte through the SPI1 peripheral */
  SPI_I2S_SendData(sFLASH_SPI, byte);


  /*!< Wait to receive a byte */
  while (SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_RXNE) == RESET);


  /*!< Return the byte read from the SPI bus */
  return SPI_I2S_ReceiveData(sFLASH_SPI);
}


/**
  * @brief  Configures the DMA.
  * @param  None
  * @retval None
  */
void DMA_Configuration(void)
{
     /* SPI2_Tx   DMA1_Channel0_Stream4 */
     /* DMA clock enable */
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);
     
     DMA_DeInit(DMA1_Stream4);


  DMA_InitStructure.DMA_Channel = DMA_Channel_0;  
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI2->DR;     
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)TxBuffer1;
  DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
  DMA_InitStructure.DMA_BufferSize = TxBufferSize1;
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Enable;         
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
     
  DMA_Init(DMA1_Stream4, &DMA_InitStructure); 
     


  DMA_ITConfig(DMA1_Stream4, DMA_IT_TC, ENABLE);
  
  NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
 
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Stream4_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}




void DMA1_Stream4_IRQHandler(void)
{
  /* Test on DMA Stream Transfer Complete interrupt */
  if (DMA_GetITStatus(DMA1_Stream4, DMA_IT_TCIF4))
  {
           /* Clear DMA Stream Transfer Complete interrupt pending bit */
              DMA_ClearITPendingBit(DMA1_Stream4, DMA_IT_TCIF4);
          sFLASH_CS_HIGH();
          sFLASH_WaitForWriteEnd();
          while(SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_TXE) == RESET);
          while(SPI_I2S_GetFlagStatus(sFLASH_SPI, SPI_I2S_FLAG_BSY) == SET);
          
          /*!< while there is data to be written on the FLASH */
          DMA_Cmd(DMA1_Stream4, DISABLE);
    
  }
}

int main(void)
{   
  // Configure the DMA 
  DMA_Configuration();

  // Enable SPI DMA TX request 
  SPI_I2S_DMACmd(sFLASH_SPI,SPI_I2S_DMAReq_Tx, ENABLE);
     
  sFLASH_Erase4KB_32KB_64KB_Chip(0x00,sFLASH_CMD_ER_SECTOR_4KB);
     
  sFLASH_DMA_WritePage(0x00);

  /* Read data from SPI FLASH memory */
  sFLASH_ReadBuffer(Read_Buf1, 0x00, TxBufferSize1);
     
     
  for (Index = 0; Index < TxBufferSize1; Index++)
  {
     USART1_Put(Read_Buf1[Index]);
  }
 while (1);
}

Outcomes