Skip to main content
CHou.1
Associate II
August 1, 2021
Solved

QSPI Flash Read Limit STM32F769I_EVAL

I'm currently playing around with the QSPI_ReadWrite_DMA example on an STM32F769I_EVAL board.

Link to example:

https://github.com/STMicroelectronics/STM32CubeF7/tree/master/Projects/STM32F769I_EVAL/Examples/QSPI/QSPI_ReadWrite_DMA.

I'm testing the QSPI Reads and it generally seems to be working most of the time but is consistently hanging when I try to read values of 0x10000 or higher.

I don't a read command limitation on the SPI Flash chip that comes with the STM32F769I_EVAL so I 'm wondering if anyone has any idea what could be the issue? Seems like a very particular boundary to stop working at. Not sure if it's an STM32 related limit?

Thanks!

This topic has been closed for replies.
Tesla DeLorean
Tesla DeLoreanBest answer
Guru
August 5, 2021

0693W00000D1fZVQAZ.jpg

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..

8 replies

TDK
August 2, 2021

There is not a 64kB limit to the QSPI address space and the chip on there has much more than 64kB of capacity.

Debug the code, where does it hang? Be specific.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Tesla DeLorean
Guru
August 2, 2021

DMA might have a 16-bit limit on the transfer count.

Many of the current QSPI NOR Flash have a 64KB block size. Usually a 256-byte page alignment/limit.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
CHou.1
CHou.1Author
Associate II
August 3, 2021

Thanks I'll try to give a bit more information.

From what I can see the last call made was HAL_QSPI_Receive_DMA which returns HAL_OK but the HAL_QSPI_RxCpltCallback never gets called which results in the while loop spinning indefinitely.

If I were to read the same range using the blocking version HAL_QSPI_Receive I see no issue, this is my current workaround.

My SPI Commands configurations are as follows:

sCommand.InstructionMode  = QSPI_INSTRUCTION_1_LINE; 

sCommand.AddressSize    = QSPI_ADDRESS_24_BITS;

sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE; 

sCommand.DdrMode      = QSPI_DDR_MODE_DISABLE;

sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;

sCommand.SIOOMode     = QSPI_SIOO_INST_EVERY_CMD;

sCommand.Instruction = QUAD_OUT_FAST_READ_CMD;

sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ_QUAD;

sCommand.AddressMode = QSPI_ADDRESS_1_LINE;

sCommand.Address   = address;

sCommand.DataMode  = QSPI_DATA_4_LINES;

 sCommand.NbData   = bufferSizeBytes;

The DMA is configured as such:

hdma.Init.Channel       = QSPI_DMA_CHANNEL;           

 hdma.Init.PeriphInc      = DMA_PINC_DISABLE;

 hdma.Init.MemInc       = DMA_MINC_ENABLE;

 hdma.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;

 hdma.Init.MemDataAlignment  = DMA_MDATAALIGN_BYTE;

 hdma.Init.Mode        = DMA_NORMAL;

 hdma.Init.Priority      = DMA_PRIORITY_LOW;

 hdma.Init.FIFOMode      = DMA_FIFOMODE_DISABLE;    /* FIFO mode disabled   */

 hdma.Init.FIFOThreshold    = DMA_FIFO_THRESHOLD_FULL;

 hdma.Init.MemBurst      = DMA_MBURST_SINGLE;      /* Memory burst      */

 hdma.Init.PeriphBurst     = DMA_PBURST_SINGLE;      /* Peripheral burst    */

 hdma.Instance         = QSPI_DMA_INSTANCE;

TDK
August 3, 2021

Okay. And where is your HAL_QSPI_Receive_DMA call? Are you trying to read more than 65535 bytes at a time?

"If you feel a post has answered your question, please click ""Accept as Solution""."
CHou.1
CHou.1Author
Associate II
August 5, 2021

> Are you trying to read more than 65535 bytes at a time?

Yes, if I try to read more than 65535 then I will never get the RxCplt flag set meaning the code waits indefinitely for the flag to be set.

The HAL_QSPI_Receive_DMA call occurs AFTER:

  • Checking the memory is reading using QSPI_AutoPolling
  • Setting the Dummy Cycles on the Flash
  • Sending QUAD_OUT_FAST_READ_CMD
  •  

Below is a snippet of the code (basically from the STM32 Example I mentioned in my first post): The difference is that the BUFFERSIZE is 0x10000 or greater when it fails.

/**
Comments:
StatusMatch and RxCplt are globals being set by the QSPI callback functions
*/
 while(1)
 {
 switch(step)
 {
 StatusMatch = 0;
 /* Configure automatic polling mode to wait for end of program ----- */ 
 QSPI_AutoPollingMemReady(&QSPIHandle);
 step++;
 }
 break;
 
 case 4:
 if(StatusMatch != 0)
 {
 StatusMatch = 0;
 RxCplt = 0;
 
 /* Configure Volatile Configuration register (with new dummy cycles) */
 QSPI_DummyCyclesCfg(&QSPIHandle);
 
 /* Reading Sequence ------------------------------------------------ */
 sCommand.Instruction = QUAD_OUT_FAST_READ_CMD;
 sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ_QUAD;
 
 if (HAL_QSPI_Command(&QSPIHandle, &sCommand, HAL_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK)
 {
 Error_Handler();
 }
 
 if (HAL_QSPI_Receive_DMA(&QSPIHandle, aRxBuffer) != HAL_OK)
 {
 Error_Handler();
 }
 step++;
 }
 break;
 
 case 5:
 if (RxCplt != 0)
 {
 RxCplt = 0;
 
 /* Result comparison ----------------------------------------------- */
 for (index = 0; index < BUFFERSIZE; index++)
 {
 if (aRxBuffer[index] != aTxBuffer[index])
 {
 BSP_LED_On(LED2);
 }
 }
 BSP_LED_Toggle(LED1);
 
 address += QSPI_PAGE_SIZE;
 if(address >= QSPI_END_ADDR)
 {
 address = 0;
 }
 step = 0;
 }
 break;
 
 default :
 Error_Handler();
 }
 }
  •  
Tesla DeLorean
Guru
August 5, 2021

Doesn't the DMA unit have a 16-bit transfer count limit?

For byte transfers that would be 64KB (perhaps less one byte)

Use HALF WORD or WORD transfers for larger transactions, and make sure your buffers are suitably aligned or decompose the transfers until they can be.

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
CHou.1
CHou.1Author
Associate II
August 6, 2021

Thank you for your help, sorry I should have checked the reference manual closer, this explains things I will check this out.