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

This discussion is locked. Please start a new topic to ask your question.
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