2025-10-09 3:30 AM
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
2025-10-09 4:13 AM
Hello @PAV and welcome to the community;
Are you configuring the memory in DTR mode?
In your configuration, you have disabled DTR mode for the address
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE
I think it should be
sCommand.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_ENABLE
Also, I recommend you to look at STM32CubeU5/Projects/STM32U5x9J-DK/Examples/OSPI/OSPI_NOR_MemoryMapped at main · STMicroelectronics/STM32CubeU5 · GitHub example may help you.
Thank you.
Kaouthar
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.