Skip to main content
Visitor II
December 3, 2024
Solved

OCTOSPI: HAL_OSPI_AutoPolling() seems to read 1 extra byte

  • December 3, 2024
  • 2 replies
  • 1330 views

Hi.

I'm using a STM32U5A5 MCU to communicate with a FLASH device through OCTOSPI.

Flash is connected to port P1, and all signals are controlled by OCTOSPIM / OCTOSPI1 MCU hardware.

a.png

I'm sending command "0x06" = WRITE_ENABLE, and after that I need to check that bit "WEL" (Write Enable Latch) is set in STATUS register. Nothing exotic here, just regular FLASH operations.

Reading device status register is performed by sending command "0x0F" = GET_FEATURES with 8-bit address 0xC0 = "STATUS". Device will ouput STATUS value on the next 8 clocks.

What I see is that function HAL_OSPI_AutoPolling() seems to be reading 1 extra byte :

TEK00090.PNG

The first 06 command is my WRITE_ENABLE command on 8 clocks.

The next 0F C0 command is isssued by polling. Note the 2 bytes "02 02" in output. Polling stops immediately because condition is met. Total is 32 clocks, while it should be 24 clocks only.

If I don't use HAL_OSPI_AutoPolling() but HAL_OSPI_Receive() to manually read once the STATUS register, I have the expected signals :

TEK00089.PNG

First command is "06" = WRITE_ENABLE on 8 clocks.

Next command is "0F C0" = GET_FEATURES(STATUS) and status value = "02" as output. Total is 24 clocks as expected.

Code :

void octospi_flash_set_WEL(enum octospi_t octospi)
{
OSPI_RegularCmdTypeDef scmd;

scmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
scmd.FlashId = HAL_OSPI_FLASH_ID_1;
scmd.Instruction = 0x06U/*WRITE_ENABLE*/;
scmd.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
scmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
scmd.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
//scmd.Address = 0x00U;
scmd.AddressMode = HAL_OSPI_ADDRESS_NONE;
//scmd.AddressSize = HAL_OSPI_ADDRESS_8_BITS;
//scmd.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
//scmd.AlternateBytes = 0xFFFFFFFFU;
scmd.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
//scmd.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS;
//scmd.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;
scmd.DataMode = HAL_OSPI_DATA_NONE;
//scmd.NbData = 0U;
//scmd.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
scmd.DummyCycles = 0U;
scmd.DQSMode = HAL_OSPI_DQS_DISABLE;
scmd.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
HAL_OSPI_Command(&ctxt[octospi].handle, &scmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

scmd.OperationType = HAL_OSPI_OPTYPE_COMMON_CFG;
scmd.FlashId = HAL_OSPI_FLASH_ID_1;
scmd.Instruction = 0x0FU/*GET_FEATURES*/;
scmd.InstructionMode = HAL_OSPI_INSTRUCTION_1_LINE;
scmd.InstructionSize = HAL_OSPI_INSTRUCTION_8_BITS;
scmd.InstructionDtrMode = HAL_OSPI_INSTRUCTION_DTR_DISABLE;
scmd.Address = 0xC0U/*STATUS*/;
scmd.AddressMode = HAL_OSPI_ADDRESS_1_LINE;
scmd.AddressSize = HAL_OSPI_ADDRESS_8_BITS;
scmd.AddressDtrMode = HAL_OSPI_ADDRESS_DTR_DISABLE;
//scmd.AlternateBytes = 0xFFFFFFFFU;
//scmd.AlternateBytesMode = HAL_OSPI_ALTERNATE_BYTES_NONE;
//scmd.AlternateBytesSize = HAL_OSPI_ALTERNATE_BYTES_8_BITS;
//scmd.AlternateBytesDtrMode = HAL_OSPI_ALTERNATE_BYTES_DTR_DISABLE;
scmd.DataMode = HAL_OSPI_DATA_1_LINE;
scmd.NbData = 1U;
scmd.DataDtrMode = HAL_OSPI_DATA_DTR_DISABLE;
scmd.DummyCycles = 0U;
scmd.DQSMode = HAL_OSPI_DQS_DISABLE;
scmd.SIOOMode = HAL_OSPI_SIOO_INST_EVERY_CMD;
HAL_OSPI_Command(&ctxt[octospi].handle, &scmd, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);

if( 1 )
{
OSPI_AutoPollingTypeDef poll;
poll.Match = 0x02U;
poll.Mask = 0x02U;
poll.MatchMode = HAL_OSPI_MATCH_MODE_AND;
poll.AutomaticStop = HAL_OSPI_AUTOMATIC_STOP_ENABLE;
poll.Interval = 0x10U;
HAL_OSPI_AutoPolling(&ctxt[octospi].handle, &poll, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
}
else
{
uint8_t value;
HAL_OSPI_Receive(&ctxt[octospi].handle, &value, HAL_OSPI_TIMEOUT_DEFAULT_VALUE);
}
}

Any idea of what could be wrong ?

Thanks a lot.

Fabrice

 

    This topic has been closed for replies.
    Best answer by KDJEM.1

    Hello @Fabrice_GIRARDOT,

    The OCTOSPI interface may generate up to six extra dummy clock cycles after it reads the last data due to internal synchronization.

    So, it is expected from the OCTOSPI sometimes to send extra clock cycles when making read operations. The OCTOSPI filters the received bytes and takes only the considered ones.

    So, sending an extra clock cycle when reading the status register gives you always the status register with an updated state. It is not impacted the application or the memory. This behavior it is not impacting the OCTOSPI/Memory functionality.

    This phenomenon is documented in RM0456

    KDJEM1_0-1733409918637.png

    Is my reply answer your request?

    Thank you.

    Kaouthar

     

     

    2 replies

    KDJEM.1Answer
    Technical Moderator
    December 5, 2024

    Hello @Fabrice_GIRARDOT,

    The OCTOSPI interface may generate up to six extra dummy clock cycles after it reads the last data due to internal synchronization.

    So, it is expected from the OCTOSPI sometimes to send extra clock cycles when making read operations. The OCTOSPI filters the received bytes and takes only the considered ones.

    So, sending an extra clock cycle when reading the status register gives you always the status register with an updated state. It is not impacted the application or the memory. This behavior it is not impacting the OCTOSPI/Memory functionality.

    This phenomenon is documented in RM0456

    KDJEM1_0-1733409918637.png

    Is my reply answer your request?

    Thank you.

    Kaouthar

     

     

    Visitor II
    December 9, 2024

    Hello @KDJEM.1 

    Your reply fully answers my request.

    Thanks a lot !

    Graduate II
    February 19, 2025

    Just an FYI

    OSPI_RegularCmdTypeDef scmd; // This is dangerous/problematic, the auto variable contains random stack junk on entry

    OSPI_RegularCmdTypeDef scmd = {0}; // Explicitly clear it for consistent/predictable behaviour

    Visitor II
    February 20, 2025

    Thanks for the hint.

    I updated my code.