2025-02-22 10:35 AM
I have a custom board with an STM32G473 running at 170MHz. I have the QSPI peripheral running correctly in indirect mode when the pre-scaler has a value of 5 (so ~23MHz) but when I decrease the pre-scaler any further all HAL_QSPI_Receive calls end up failing silently. I've tracked it down to the QSPI_WaitFlagStateUntilTimeout returning an error due to what seems like a timeout. Here's a snippet of my initialization code:
flashSPI.Instance = QUADSPI;
flashSPI.Init.ClockPrescaler = 2;
flashSPI.Init.FifoThreshold = 1;
flashSPI.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_NONE;
flashSPI.Init.FlashSize = 27;
flashSPI.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_1_CYCLE;
flashSPI.Init.ClockMode = QSPI_CLOCK_MODE_0;
flashSPI.Init.FlashID = QSPI_FLASH_ID_1;
flashSPI.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
__HAL_RCC_QSPI_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
__HAL_RCC_GPIOB_CLK_ENABLE();
// Initialize pins
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
// Configure NCS pin
GPIO_InitStruct.Pin = QSPI_NCS_Pin;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(QSPI_NCS_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = QSPI_CLK_Pin;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(QSPI_CLK_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = QSPI_IO3_Pin;
HAL_GPIO_Init(QSPI_IO3_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = QSPI_IO2_Pin;
HAL_GPIO_Init(QSPI_IO2_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = QSPI_IO1_Pin;
HAL_GPIO_Init(QSPI_IO1_Port, &GPIO_InitStruct);
GPIO_InitStruct.Pin = QSPI_IO0_Pin;
HAL_GPIO_Init(QSPI_IO0_Port, &GPIO_InitStruct);
__HAL_RCC_QSPI_FORCE_RESET();
__HAL_RCC_QSPI_RELEASE_RESET();
if(HAL_QSPI_Init(&flashSPI) != HAL_OK) return FC_ERROR;
// Enable interrupts
HAL_NVIC_SetPriority(QUADSPI_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(QUADSPI_IRQn);
// Check device ID and manufacturer ID
uint8_t jedec[3] = {0};
getJEDEC(jedec);
uint16_t deviceID = (jedec[1] << 8) | (jedec[2]);
if(jedec[0] != WINBOND_MFR_ID || deviceID != W25N02KV_DEVICE_ID) return FC_ERROR;
I tried implementing the "QUADSPI internal timing criticality" fix in the errata but haven't had any luck. Are there certain parameters I'm missing?