0
\$\begingroup\$

I am facing problem with STM32F401RE with SPI flash driver. I am able to do normal SPI operations like read,write etc... But I need to use DMA to read and write to FLASH. /******************************** I am trying to read the data(DMA Methos) from specific address location 0x700000 which was written already. *********************/

Now I was able to DMA sent sucessfully but on the DMA Receiving buffer it has starting four bytes of NULL data followed by actual Data and last four bytes are missing.

Original: STM32F4xx SPI Firmware Library Example: communication with an S25FL164K SPI FLASH from SPANSION

Receiving : "0x00 0x00 0x00 0x00 STM32F4xx SPI Firmware Library Example: communication with an S25FL164K SPI FLASH from SPAN"

Can some one please suggest why I am getting junk characters like NULL in the first four bytes and why the last four bytes are missing??

Is there any issue issues with clock cycles?? And one more thing I have to clear/read all the data present on "SPI1->DR " before the dma transfer

This is the code.. Please suggest if any issues in the below code

   SPI_InitTypeDef  SPI_InitStructure;
   GPIO_InitTypeDef GPIO_InitStructure;

/*!< Enable the SPI clock */
sFLASH_SPI_CLK_INIT(sFLASH_SPI_CLK, ENABLE);

/*!< Enable GPIO clocks */

/*!< Enable GPIO clocks */
RCC_AHB1PeriphClockCmd(sFLASH_SPI_SCK_GPIO_CLK | sFLASH_SPI_MISO_GPIO_CLK |
                     sFLASH_SPI_MOSI_GPIO_CLK | sFLASH_CS_GPIO_CLK, ENABLE);

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);
/*!< SPI pins configuration *************************************************/

/*!< Connect SPI pins to AF5 */
GPIO_PinAFConfig(sFLASH_SPI_SCK_GPIO_PORT, sFLASH_SPI_SCK_SOURCE, sFLASH_SPI_SCK_AF);
GPIO_PinAFConfig(sFLASH_SPI_MISO_GPIO_PORT, sFLASH_SPI_MISO_SOURCE, sFLASH_SPI_MISO_AF);
GPIO_PinAFConfig(sFLASH_SPI_MOSI_GPIO_PORT, sFLASH_SPI_MOSI_SOURCE, sFLASH_SPI_MOSI_AF);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;

/*!< SPI SCK pin configuration */
GPIO_InitStructure.GPIO_Pin = sFLASH_SPI_SCK_PIN;
GPIO_Init(sFLASH_SPI_SCK_GPIO_PORT, &GPIO_InitStructure);

/*!< SPI MOSI pin configuration */
GPIO_InitStructure.GPIO_Pin =  sFLASH_SPI_MOSI_PIN;
GPIO_Init(sFLASH_SPI_MOSI_GPIO_PORT, &GPIO_InitStructure);

/*!< SPI MISO pin configuration */
GPIO_InitStructure.GPIO_Pin =  sFLASH_SPI_MISO_PIN;
GPIO_Init(sFLASH_SPI_MISO_GPIO_PORT, &GPIO_InitStructure);

/*!< Configure sFLASH Card CS pin in output pushpull mode ********************/
GPIO_InitStructure.GPIO_Pin = sFLASH_CS_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(sFLASH_CS_GPIO_PORT, &GPIO_InitStructure);

/*!< 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_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(sFLASH_SPI, &SPI_InitStructure);
void SPI_DMA_READ(uint8_t* Addref, uint8_t* pRxBuf, uint16_t rx_len)
{
    uint16_t i;

    memset(pTmpBuf1, 0, rx_len + 3);
    memset(pTmpBuf2, 0, rx_len + 3);

      pTmpBuf1[0] = sFLASH_CMD_READ;
    pTmpBuf1[1] = Addref[0];
    pTmpBuf1[2] = Addref[1];
    pTmpBuf1[3] = Addref[2];


  DMA_InitStructure.DMA_BufferSize = (uint16_t)(rx_len);
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable ;
 DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull ;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single ;
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)(&(SPI1->DR));
    DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_InitStructure.DMA_MemoryDataSize =  DMA_MemoryDataSize_Byte;
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;

    /* Configure Tx DMA */
    DMA_InitStructure.DMA_Channel = DMA_Channel_3;
    DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral;
    DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)pTmpBuf1;
    DMA_Init(DMA2_Stream3, &DMA_InitStructure);

/* Configure Rx DMA */
    DMA_InitStructure.DMA_Channel = DMA_Channel_3;
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory;
    DMA_InitStructure.DMA_Memory0BaseAddr =(uint32_t)pTmpBuf2;
    DMA_Init(DMA2_Stream2, &DMA_InitStructure);
 #if 1      
      //DMA Interrupt Structure Initialisation
    static NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel =                  DMA2_Stream2_IRQn;//SPI_PORT_DMA_TX_IRQn;
 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    //Initialise the Interrupt
NVIC_Init(&NVIC_InitStructure);

// Enable DMA1 channel IRQ Channel */
DMA_ITConfig(DMA2_Stream2, DMA_IT_TC, ENABLE);

 #endif
/* Enable the DMA channel */

   /* Enable the DMA SPI TX Stream */
DMA_Cmd(DMA2_Stream3, ENABLE);
/* Enable the DMA SPI RX Stream */
DMA_Cmd(DMA2_Stream2, ENABLE);

    /* Enable the SPI Rx DMA request */
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);

sFLASH_CS_LOW();

while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) == SET)
{}


 SPI_Cmd(SPI1, ENABLE);
    while(trasfer_complete_rx == 0);
memcpy(pRxBuf, pTmpBuf2 ,rx_len);

/*******************************************/ IRQ Handler /***************************************/

  void DMA2_Stream2_IRQHandler()
  {

if(DMA_GetITStatus(DMA2_Stream2,DMA_IT_TCIF2))
 DMA_ClearITPendingBit(DMA2_Stream2,DMA_IT_TCIF2);

DMA_ClearITPendingBit(DMA2_Stream3,DMA_IT_TCIF3);
DMA_ClearITPendingBit(DMA2_Stream2,DMA_IT_TCIF2);

DMA_Cmd(DMA2_Stream3, DISABLE);
DMA_Cmd(DMA2_Stream2, DISABLE);

SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, DISABLE);
SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, DISABLE);

SPI_Cmd(SPI1, DISABLE);
sFLASH_CS_HIGH();
trasfer_complete_rx =1;
while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); // Wait for Empty

USART_SendData(USART2,*(pTmpBuf2+2)); // Send 'I'
}
\$\endgroup\$
3
  • 1
    \$\begingroup\$ What do you mean by "No data available at the receiver buffer"? There's always something there ... just not what you expect? What do you see vs. what do you expect to see? Do you see any error flags set in the DMA module? \$\endgroup\$
    – brhans
    Nov 10, 2016 at 14:09
  • \$\begingroup\$ Hello Brhans, yesterday it was like all null(0x00)'s present in the received buffer. But today i was able to do DMA transfer sucessfuly and received the data with Four NULL values in the starting of the buffer and last four charters are missing. For example "STM32F4xx SPI Firmware Library Example: communication with an S25FL164K SPI FLASH from SPANSION" but it is receiving like " 0x00 0x00 0x00 0x00 STM32F4xx SPI Firmware Library Example: communication with an S25FL164K SPI FLASH from SPAN" \$\endgroup\$ Nov 11, 2016 at 9:08
  • \$\begingroup\$ I'm voting to close this question as off-topic because it has been abandoned in unanswerable condition by a poster who has not returned to the site in over two years. \$\endgroup\$ Dec 24, 2018 at 19:18

1 Answer 1

-1
\$\begingroup\$

This is for stm32f401re
First the DMA initialization

void init_spi1_dma(void)
{
  DMA_InitTypeDef DMA_InitStructure;
  DMA_StructInit(&DMA_InitStructure);
  //
  // spi1 rx configuration
  //
  DMA_Cmd(DMA2_Stream0, DISABLE);
  while(DMA2_Stream0_BASE & 0x00000001); // wait for disable to take effect
  DMA_DeInit(DMA2_Stream0);
  DMA_InitStructure.DMA_Channel = DMA_Channel_3;
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralToMemory; // receive
// tell the DMA where to place the incoming characters
// in this case only one char at a time
// let the interrupt routine sort it out
  DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)dma_rx_buffer;
  DMA_InitStructure.DMA_BufferSize = (char)sizeof(dma_rx_buffer);
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR;
  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_Circular;
  DMA_InitStructure.DMA_Priority = DMA_Priority_High;
  DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;
  DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull;
  DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
  DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
  //
  // the interrupt flags for the DMA Stream:
  // DMA_IT: specifies the DMA interrupt pending bit to clear.
  //          This parameter can be any combination of the following values:
  //            DMA_IT_TCIFx:  Streamx transfer complete interrupt
  //            DMA_IT_HTIFx:  Streamx half transfer complete interrupt
  //            DMA_IT_TEIFx:  Streamx transfer error interrupt
  //            DMA_IT_DMEIFx: Streamx direct mode error interrupt
  //            DMA_IT_FEIFx:  Streamx FIFO error interrupt
  //         Where x can be 0 to 7 to select the DMA Stream.
  DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF2 | DMA_IT_TEIF2 | DMA_IT_HTIF2 | DMA_IT_FEIF2 | DMA_IT_DMEIF2);
  DMA_Init(DMA2_Stream0, &DMA_InitStructure);

// Enable the SPI Rx DMA request
  SPI_DMACmd(SPI1, SPI_DMAReq_Rx, ENABLE);                            
// Enable DMA Stream Transfer Complete interrupt
  DMA_ITConfig(DMA2_Stream0, DMA_IT_TC | DMA_IT_TE | DMA_IT_DME, ENABLE);   
// Enable the DMA Rx Stream
  DMA_Cmd(DMA2_Stream0, ENABLE);                                            

}

now the interrupt

//
// dma spi interrupt
//
void init_spi_dma_nvic()
{
  NVIC_InitTypeDef nvic_params;

  //NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
  nvic_params.NVIC_IRQChannel = DMA2_Stream0_IRQn;
  nvic_params.NVIC_IRQChannelPreemptionPriority = 3;
  nvic_params.NVIC_IRQChannelSubPriority = 0;
  nvic_params.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&nvic_params);
}

//
// spi1 rx dma interrupt
//
void DMA2_Stream0_IRQHandler(void)
{
  static uint16_t i = 0;

  if(rcvd == 0)
    i = 0;

  rcvd++;
  /* Test on DMA Stream Transfer Complete interrupt */
  if (DMA_GetITStatus(DMA2_Stream0, DMA_IT_TCIF0))
  {
    // place the incoming char away
    rx_buffer[i++] = dma_rx_buffer[0];
    // Clear DMA Stream Transfer Complete interrupt pending bit
    DMA_ClearITPendingBit(DMA2_Stream0, DMA_IT_TCIF0);

  }
}

have fun!

\$\endgroup\$
1
  • 2
    \$\begingroup\$ Dumping a bit of new code does not really constitute an answer; an answer should explain what the problem is. If the code in the question were horribly wrong, replacing it might be warranted, but again, you'd need to explain. Also beware that you are responding to a question that appears to have been abandoned for two years. \$\endgroup\$ Dec 24, 2018 at 19:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.