cancel
Showing results for 
Search instead for 
Did you mean: 

Why does HAL_QSPI_AutoPolling keep polling whereas the timeout has been reached and returning an error flag ?

DFell.1
Associate II

Hello everyone,

I'm today encountering a new issue where your help will be more than welcome.

I'm communicating with an external Flash Memory using the QSPI of the STM32H7 than I own and everything is working as expected at the first run. I can write and read status without any problem.

However when I wanted to have some code more reliable by adding some check status, using the HAL_QSPI_AutoPolling, of my Flash Memory I run into some issue.

Here is the configuration I'm running to have this issue:

QSPI_CommandTypeDef sCommand;
    QSPI_AutoPollingTypeDef sConfig;
    HAL_StatusTypeDef err = HAL_ERROR;
 
    //! # Configure automatic polling mode to wait for memory ready (WIP bit)
    sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
    sCommand.Instruction = S25F064L_CMD_RDSR1;
    sCommand.AddressMode = QSPI_ADDRESS_NONE;
    sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
    sCommand.DataMode = QSPI_DATA_1_LINE;
    sCommand.DummyCycles = 0;
    sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
    sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
    sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
 
    //! ## WIP bit should not be set
    sConfig.Match = 0x02;
    sConfig.Mask = S25F064L_SR1V_WIP;
    sConfig.MatchMode = QSPI_MATCH_MODE_AND;
    sConfig.StatusBytesSize = 1;
    sConfig.Interval = 0x10;
    sConfig.AutomaticStop = QSPI_AUTOMATIC_STOP_ENABLE;
 
    //! ## Start polling
    HAL_GPIO_WritePin(DBG_PIN_1_GPIO_Port, DBG_PIN_1_Pin, GPIO_PIN_SET);
    err = HAL_QSPI_AutoPolling(&hqspi, &sCommand, &sConfig, S25F064L_TIMEOUT);
    HAL_GPIO_WritePin(DBG_PIN_1_GPIO_Port, DBG_PIN_1_Pin, GPIO_PIN_RESET);
 
    if (err != HAL_OK)
    {
        HAL_QSPI_Abort(&hqspi);
    }

Setting the Mask Match to 0x02 is making me having this issue, since the value returning and expected by my product is 0x00. It was at first a mistakes of mine, but I then realized that this behavior is not what I was expected and can't get it work properly with the wrong value.

I am sure than the timeout is working properly since my external pin is toggling as expected (after 100ms) as you can see in the screenshot of my logic analyser.

0693W00000Ly1ApQAJ.pngBut you can also see than the communication is not stopping even with the presence of the HAL_QSPI_Abort command.

9 REPLIES 9

The mask indicates the bit your interested in looking at, not the states of it. WIP is BIT 0, not BIT 1

((SR & 1) == 2) is NEVER going to be TRUE

HAL_GetTick() can fail if SysTick isn't working, or you're doing things in interrupt/callback context.

HAL_QSPI_Abort() is unlikely to significantly alter the state within the memory device. ie an Erase going on for several minutes, etc.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
DFell.1
Associate II

In the description I made a mistake and mean match instead ok mask, sorry.

Concerning the assertion for this test I did the failure in purpose, since my goal is to stop the Auto Polling after an unsuccess match.

This part of the code is running without any task, so there is no interruption or context to switch.

I checked again and SysTick is enable and working as expected.

So if HAL_QSPI_Abort is not stopping the communication ongoing because of my Auto Polling call, how could I do it ?

You'll have to root-cause why the timeout is not working, you have all the source code, and it should be using HAL_GetTick() at the lowest levels in order to measure elapsed time.

HAL_QSPI_Abort() can likely control the QSPI peripheral on the STM32 side. The QSPI memory devices typically don't have an async reset, or it is not independently connected. You'll need to look at what the memory device has in the way of stopping, abort or pausing on going activities. Those commands would be in the data sheet of the memory device.

The HAL should have DeInit/Init function which can reset and restart the QSPI peripheral.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
AMart.22
Associate

The timeout seems to be working. The pinout toggles as expected. Did you check the QSPI registers set by the HAL? It's surprising HAL_QSPI_Abort does not reset the autopolling flag in the QSPI registers.

A solution might be to set the registers manually.

I don't see a clean way to do it using the HAL.

The timeout seems to be working fine as indicate by the GPIO on the logic analyzer.

Concerning the memory, the chip is a slave device and the STM32 the master. Here my issue is the master never stop polling the QSPI memory (slave) even after the end of the timeout or the HAL_QSPI_Abort().

Doing a call to DeInit/Init function seems to be very a heavy process to stop an internal HAL_QSPI_AutoPolling function.

Yes the timeout is working, I played with different time value and the GPIO pin is evolving as expected.

I might have a look to control register but using the HAL was a way for me to avoid this process and this is the solution I'm looking for.

@Imen DAHMEN​ @Amel NASRI​ @Nawres GHARBI​ can you have someone review this failure.

I've walked the code, and a lot of the BSP code examples, and there doesn't seem to be any proper handling of the Timeout situation. The code itself time's out, and then subsequent code typically drops through with an error, but it doesn't seem to do anything to address the error, or stop the QSPI/OCTOSPI peripheral, and leaves the instance state in a BUSY condition.

None of the reference code uses the HAL_QSPI_Abort(), and in one of the L4 BSP examples the AutoPoll is actually emulated by doing normal reads, and mask/compare at the edge of a do-while loop.

So you don't have to regress a massive amount of code you might want the default behaviour for the HAL_xSPI_AutoPolling() to abort/stop the current bus activity in the TIMEOUT case

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

I think I understand what you're seeing/complaining about. All the reference/example code entirely ignores this failure mode/path

The underlying abort should be initiated via

  /* Configure QSPI: CR register with Abort request */

  SET_BIT(hqspi->Instance->CR, QUADSPI_CR_ABORT);

or

  SET_BIT(QSPI->CR, QUADSPI_CR_ABORT);

The other alternative perhaps via QUADSPI_CR_EN clear/set

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..

Hello,

Any news about this issue?