cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F767 QUADSPI with DMA

AShel.1
Associate III

I've referred STM32F769I_EVAL QSPI with DMA source code and implemented same way for STM32F767 but its not working. can anyone provide the sample code for STM32f767 QSPI with DMA

6 REPLIES 6
Arnon
Associate III

Hi

I am using it in indirect mode for a "simple", 4 lines SPI.

Once configured, CubeMX generates the following code in “MX_QUADSPI_Init�?

….

 hqspi.Instance = QUADSPI;

 hqspi.Init.ClockPrescaler = 64;

 hqspi.Init.FifoThreshold = 32;

 hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;

 hqspi.Init.FlashSize = 1;

 hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;

 hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;

 hqspi.Init.FlashID = QSPI_FLASH_ID_1;

 hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;

 if (HAL_QSPI_Init(&hqspi) != HAL_OK)

 {

   Error_Handler();

 }

To that end, I have added:

hqspi.Instance->DLR=NumberOfBytes;//set number of bytes to read\write per CS. The number of clks are 2x(Value+1)

hqspi.Instance->DCR|=0x001F0000;//Flash configuration register

hqspi.Instance->ABR=0;//alternate bytes registers

hqspi.Instance->CCR=0x07000000;//configure Indirect read mode, data on 4 lines DMA must be disabled first

 hqspi.Instance->CR|=0x00200005;//enable DMA

when a read is required:

HAL_QSPI_Receive_DMA(&hqspi,buffer);

Where buffer is the DMA destination.

--Arnon

0693W000001srLEQAY.jpg0693W000001srL9QAI.jpg

Thanks Arnon,

I've re-checked the configuration and settings. what I see is configuration parameters are changing in between function calls and because of this I get hard fault. My DMA settings are,

 Configure common DMA parameters */
    dma_handle.Init.Channel             = QSPI_DMAx_CHANNEL;
    //dma_handle.Init.Direction           = DMA_MEMORY_TO_MEMORY;
    dma_handle.Init.PeriphInc           = DMA_PINC_DISABLE;//ENABLE;
    dma_handle.Init.MemInc              = DMA_MINC_ENABLE;
    dma_handle.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;//DMA_PDATAALIGN_WORD;
    dma_handle.Init.MemDataAlignment    = DMA_MDATAALIGN_BYTE;//DMA_MDATAALIGN_WORD;
    dma_handle.Init.Mode                = DMA_NORMAL;
    dma_handle.Init.Priority            = DMA_PRIORITY_LOW;//HIGH;
    dma_handle.Init.FIFOMode            = DMA_FIFOMODE_DISABLE;//ENABLE;//DMA_FIFOMODE_DISABLE;
    dma_handle.Init.FIFOThreshold       = DMA_FIFO_THRESHOLD_FULL;
    dma_handle.Init.MemBurst            = DMA_MBURST_SINGLE;
    dma_handle.Init.PeriphBurst         = DMA_PBURST_SINGLE;
 
    dma_handle.Instance = QSPI_DMAx_STREAM;
    /* Associate the DMA handle */
 
    HAL_DMA_Init(&dma_handle);
    __HAL_LINKDMA(hqspi, hdma, dma_handle);
 
 
    /* Deinitialize the stream for new transfer */
    //HAL_DMA_DeInit(&dma_handle);
 
    /* Configure the DMA stream */
   // HAL_DMA_Init(&dma_handle);
 
    /* NVIC configuration for DMA transfer complete interrupt */
    HAL_NVIC_SetPriority(QSPI_DMAx_IRQn, 0x05, 0);
    HAL_NVIC_EnableIRQ(QSPI_DMAx_IRQn);

but if I step debug through the code, at the end in function HAL_DMA_Start_IT values of SrcAddress and DstAddress are just 0. because of this I get hard fault. but I'm not able to find out why DMA settings are getting changed.

HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
  HAL_StatusTypeDef status = HAL_OK;
 
  /* calculate DMA base and stream number */
  DMA_Base_Registers *regs = (DMA_Base_Registers *)hdma->StreamBaseAddress;
  
  /* Check the parameters */
  assert_param(IS_DMA_BUFFER_SIZE(DataLength));
 
  /* Process locked */
  __HAL_LOCK(hdma);
  
  if(HAL_DMA_STATE_READY == hdma->State)
  {
    /* Change DMA peripheral state */
    hdma->State = HAL_DMA_STATE_BUSY;
    
    /* Initialize the error code */
    hdma->ErrorCode = HAL_DMA_ERROR_NONE;
    
    /* Configure the source, destination address and the data length */
    DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
    
    /* Clear all interrupt flags at correct offset within the register */
    regs->IFCR = 0x3FU << hdma->StreamIndex;
    
    /* Enable Common interrupts*/
    hdma->Instance->CR  |= DMA_IT_TC | DMA_IT_TE | DMA_IT_DME;
    hdma->Instance->FCR |= DMA_IT_FE;
    
    if(hdma->XferHalfCpltCallback != NULL)
    {
      hdma->Instance->CR  |= DMA_IT_HT;
    }
    
    /* Enable the Peripheral */
    __HAL_DMA_ENABLE(hdma);
  }
  else
  {
    /* Process unlocked */
    __HAL_UNLOCK(hdma);	  
    
    /* Return error status */
    status = HAL_BUSY;
  }
  
  return status;
}

AShel.1
Associate III

any clue to....why DMA settings are changing in runtime?

Have you tried using the QSPI DMA functions?

They can be found at "stm32f7xx_hal_qspi.c"

For example, I am using the "HAL_QSPI_Receive_DMA" to initiate QSPI read. Source and destination are parameters to this function.

This function calls for HAL_DMA_Start_IT eventually.

--Arnon

AShel.1
Associate III

debugged further and found....hard fault is raised at line hdma->Instance->CR &= (uint32_t)(~DMA_SxCR_DBM); in function DMA_SetConfig

if I check DMA2D_CR control register bits 18 - 31 are reserved bits, then why we're clearing bit 19th bit of hdma->Instance->CR through DMA_SxCR_DBM(0x40000)

if I step debug this line it goes to HardFault_Handler function

static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
{
  /* Clear DBM bit */
  hdma->Instance->CR &= (uint32_t)(~DMA_SxCR_DBM);
 
  /* Configure DMA Stream data length */
  hdma->Instance->NDTR = DataLength;
 
  /* Memory to Peripheral */
  if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
  {
    /* Configure DMA Stream destination address */
    hdma->Instance->PAR = DstAddress;
 
    /* Configure DMA Stream source address */
    hdma->Instance->M0AR = SrcAddress;
  }
  /* Peripheral to Memory */
  else
  {
    /* Configure DMA Stream source address */
    hdma->Instance->PAR = SrcAddress;
 
    /* Configure DMA Stream destination address */
    hdma->Instance->M0AR = DstAddress;
  }
}

Hello Arnon,

Yes, I'm using QSPI DMA function HAL_QSPI_Transmit_DMA(&QSPIHandle, aTxBuffer) != HAL_OK for transmitting data...as this function was leading to hard fault....I've debugged it further and found hard fault is initiated at hdma->Instance->CR &= (uint32_t)(~DMA_SxCR_DBM); line in function DMA_SetConfig which is called HAL_DMA_Start_IT