Understanding QSPI memory transaction timings with DMA
Hello,
I'm implementing QSPI on STM32L451 with a NOR FLASH memory (Micron MT25QL512ABB, 64Mbytes) for the first time, using DMA, for the moment it seems to work, but I'm surprised by the timings.
CPU runs at 16MHz, QSPI clock speed is 8MHz. For this example I'm reading 256 bytes.
Full transaction :

I'm surprised to see that the full read sequence is performed in burst of 7 bytes (14 clock cycles), spaced by approx 2µs delay between each burst. Since there is a FIFO on QSPI, there should no delay ? And why always 7 bytes bursts ?
While the transaction is running the CPU is running an infinite loop for debug.


That does not change if FifoThreshold is set to 1, 4 or 8. I have some difficulties to understand this parameter, in typical examples it is set to 4, but why ? Why 4 and not 1 ? What consequences on code ? Does it apply on DMA usage, or only for non DMA access (for "status register read" for example)
Another question : the datasheet suffers from absence of detailled chonograms about the "SampleShifting" parameter. Is it ok to let it at "NONE" ? (no circuitry added on the lines, short connection to the memory, and low frequency clock).
Here are the configurations :
QSPI and DMA modules config :
/* QUADSPI parameter configuration*/
hqspi.Instance = QUADSPI;
hqspi.Init.ClockPrescaler = 1;
hqspi.Init.FifoThreshold = 4;
hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
hqspi.Init.FlashSize = 25;
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;
/* QUADSPI DMA Init */
/* QUADSPI Init */
hdma_quadspi.Instance = DMA2_Channel7;
hdma_quadspi.Init.Request = DMA_REQUEST_3;
hdma_quadspi.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_quadspi.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_quadspi.Init.MemInc = DMA_MINC_ENABLE;
hdma_quadspi.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_quadspi.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_quadspi.Init.Mode = DMA_NORMAL;
hdma_quadspi.Init.Priority = DMA_PRIORITY_MEDIUM;
QSPI read sequence :
uint8_t FLASH_Read_Page(uint32_t address, uint8_t * buffer, uint32_t lg)
{
// Configuring the command execution
qspi_flash_config.AddressSize = QSPI_ADDRESS_32_BITS;
qspi_flash_config.InstructionMode = QSPI_INSTRUCTION_1_LINE;
qspi_flash_config.DdrMode = QSPI_DDR_MODE_DISABLE;
qspi_flash_config.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
qspi_flash_config.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
qspi_flash_config.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
qspi_flash_config.AlternateBytes = 0;
qspi_flash_config.AlternateBytesSize = 0;
qspi_flash_config.Instruction = CMD_READ_4B_QUADIO_INOUT;
qspi_flash_config.AddressMode = QSPI_ADDRESS_4_LINES;
qspi_flash_config.Address = address;
qspi_flash_config.DummyCycles = 10;
qspi_flash_config.DataMode = QSPI_DATA_4_LINES;
qspi_flash_config.NbData = lg;
HAL_QSPI_Command(&hqspi_flash, &qspi_flash_config, 1000);
HAL_QSPI_Receive_DMA(&hqspi_flash, buffer);
}
