STM32U5G9NJ-DK1: OCTOSPI Auto-Polling Timeout in OctalPollingWEL() for Macronix Flash
Hi,
I'm encountering an issue with OCTOSPI auto-polling on the STM32U5G9NJ-DK1 Discovery Kit while following the "Octo-SPI FLASH in Regular-command protocol example" from AN5050 (Rev 12, February 2025). Specifically, in the OctalPollingWEL() function, HAL_OSPI_AutoPolling() always times out while waiting for HAL_OSPI_FLAG_SM (Status Match) to set. It calls OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_SM, SET, tickstart, Timeout) and returns an error, triggering Error_Handler().
Link for Application Note:- https://www.st.com/resource/en/application_note/an5050-getting-started-with-octospi-hexadecaspi-and-xspi-interface-on-stm32-mcus-stmicroelectronics.pdf
/* Octal polling Write enable latch function */
void OctalPollingWEL(void) {
OSPI_AutoPollingTypeDef sConfig;
OSPI_RegularCmdTypeDef sCommand;
/* Initialize Indirect read mode for Software Polling to wait until WEL=1 */
sCommand.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
sCommand.FlashId = HAL_OSPI_FLASH_ID_1;
sCommand.Instruction = OCTAL_READ_STATUS_REG_CMD;
sCommand.InstructionMode = HAL_OSPI_INSTRUCTION_8_LINES;
sCommand.InstructionSize = HAL_OSPI_INSTRUCTION_16_BITS;
sCommand.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_ENABLE;
sCommand.Address = 0x0;
sCommand.AddressMode = HAL_OSPI_ADDRESS_8_LINES;
sCommand.AddressSize = HAL_OSPI_ADDRESS_32_BITS;
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
sCommand.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
sCommand.DataMode = HAL_OSPI_DATA_8_LINES;
sCommand.DataDtrMode = HAL_OSPI_DATA_DTR_ENABLE;
sCommand.NbData = 2;
sCommand.DummyCycles = DUMMY_CLOCK_CYCLES_READ_REG;
sCommand.DQSMode = HAL_OSPI_DQS_DISABLE;
sCommand.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
/* Set the mask to 0x02 to mask all Status REG bits except WEL */
/* Set the match to 0x02 to check if the WEL bit is Set */
sConfig.Match = WRITE_ENABLE_MATCH_VALUE;
sConfig.Mask = WRITE_ENABLE_MASK_VALUE;
sConfig.MatchMode = HAL_OSPI_MATCH_MODE_AND;
sConfig.Interval = AUTO_POLLING_INTERVAL;
sConfig.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE;
if (HAL_OSPI_Command(&hospi1, &sCommand, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) !=
HAL_OK) {
Error_Handler();
}
/* Start Automatic-Polling mode to wait until the memory is ready WEL=1 */
if (HAL_OSPI_AutoPolling(&hospi1, &sConfig, HAL_OSPI_TIMEOUT_DEFAULT_VALUE) !=
HAL_OK) {
Error_Handler();
}
}
/**
* @brief Configure the OSPI Automatic Polling Mode in blocking mode.
* @PAram hospi : OSPI handle
* @PAram cfg : structure that contains the polling configuration information.
* @PAram Timeout : Timeout duration
* @note This function is used only in Automatic Polling Mode
* @retval HAL status
*/
HAL_StatusTypeDef HAL_OSPI_AutoPolling(OSPI_HandleTypeDef *hospi, OSPI_AutoPollingTypeDef *cfg, uint32_t Timeout)
{
HAL_StatusTypeDef status;
uint32_t tickstart = HAL_GetTick();
uint32_t addr_reg = hospi->Instance->AR;
uint32_t ir_reg = hospi->Instance->IR;
#ifdef USE_FULL_ASSERT
uint32_t dlr_reg = hospi->Instance->DLR;
#endif /* USE_FULL_ASSERT */
/* Check the parameters of the autopolling configuration structure */
assert_param(IS_OSPI_MATCH_MODE(cfg->MatchMode));
assert_param(IS_OSPI_AUTOMATIC_STOP(cfg->AutomaticStop));
assert_param(IS_OSPI_INTERVAL(cfg->Interval));
assert_param(IS_OSPI_STATUS_BYTES_SIZE(dlr_reg + 1U));
/* Check the state */
if ((hospi->State == HAL_OSPI_STATE_CMD_CFG) && (cfg->AutomaticStop == HAL_OSPI_AUTOMATIC_STOP_ENABLE))
{
/* Wait till busy flag is reset */
status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_BUSY, RESET, tickstart, Timeout);
if (status == HAL_OK)
{
/* Configure registers */
WRITE_REG(hospi->Instance->PSMAR, cfg->Match);
WRITE_REG(hospi->Instance->PSMKR, cfg->Mask);
WRITE_REG(hospi->Instance->PIR, cfg->Interval);
MODIFY_REG(hospi->Instance->CR, (OCTOSPI_CR_PMM | OCTOSPI_CR_APMS | OCTOSPI_CR_FMODE),
(cfg->MatchMode | cfg->AutomaticStop | OSPI_FUNCTIONAL_MODE_AUTO_POLLING));
/* Trig the transfer by re-writing address or instruction register */
if (hospi->Init.MemoryType == HAL_OSPI_MEMTYPE_HYPERBUS)
{
WRITE_REG(hospi->Instance->AR, addr_reg);
}
else
{
if (READ_BIT(hospi->Instance->CCR, OCTOSPI_CCR_ADMODE) != HAL_OSPI_ADDRESS_NONE)
{
WRITE_REG(hospi->Instance->AR, addr_reg);
}
else
{
WRITE_REG(hospi->Instance->IR, ir_reg);
}
}
/* Wait till status match flag is set to go back in idle state */
status = OSPI_WaitFlagStateUntilTimeout(hospi, HAL_OSPI_FLAG_SM, SET, tickstart, Timeout);
if (status == HAL_OK)
{
/* Clear status match flag */
__HAL_OSPI_CLEAR_FLAG(hospi, HAL_OSPI_FLAG_SM);
/* Update state */
hospi->State = HAL_OSPI_STATE_READY;
}
}
}
else
{
status = HAL_ERROR;
hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;
}
/* Return function status */
return status;
}
Regards,
Pavan

