Skip to main content
Graduate II
February 13, 2024
Solved

STM32H743 external loader

  • February 13, 2024
  • 4 replies
  • 8513 views

I went through the ST External QSPI Loader how to and have verified my quadspi.c/h driver is good with the Winbond W25Q64 flash part we are using.  However after I create the .stldr and load it into the STM32 Programmer it will not read from the flash...get Error:data read failed.  I've attached the project if someone could help me out with what could be wrong?

    This topic has been closed for replies.
    Best answer by PFlor.2

    Just to wrap up the solution to this LONG thread....

    Initially I was using TIM6 for the timebase (based on application using FreeRTOS that cannot use SysTick) but the NVIC priority was set to 15.  I'm not sure if the priority was the problem or some timeout with the Loader_Src.c Init() function, but the ST Support solution to comment out __set_PRIMASK(0); that enabled interrupts just masked the issue and since the interrupts were no longer running the HAL_GetTick() never incremented so timeout values made no difference and I had HAL_Delay() overridden to use a loop of NOP.

    PFlor2_0-1733955529552.png

    By using SysTick for the Timebase and setting it's NVIC priority to 0 instead of 15 (default) I was able to use enable interrupts in Init() and use the standard HAL_Delay() and HAL_GetTick() just fine and almost everything worked just fine.  However, the Chip Erase still failed....Tesla was correct that this was a timeout issue.  Basically, I had a timeout value of 20000 (HAL_QSPI_TIMEOUT_DEFAULT_VALUE) I was using for most the QSPI functions.  I started using a larger value for erasing the chip, but I was using this larger timeout for issuing the erase chip command when in fact the HAL_QSPI_AutoPolling() is what needed the larger timeout value since that is what is waiting for the erase to complete.  Once I modified my AutoPolling function to use a larger timeout when doing a chip erase then that method started working as well.   Just multiple misunderstanding of how this loader works on my part on multiple fronts.

    #define CSP_QPSI_TIMEOUT_DEFAULT_VALUE 20000
    #define CSP_QPSI_MASSERASE_TIMEOUT_VALUE 65000
    
    
    uint8_t CSP_QSPI_Erase_Chip(void) {
    
     QSPI_CommandTypeDef sCommand = { 0 };
    
     if (QSPI_WriteEnable() != HAL_OK) {
     return HAL_ERROR;
     }
    
     /* Erasing Sequence --------------------------------- */
     sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
     sCommand.Instruction = CHIP_ERASE_CMD;
     sCommand.AddressMode = QSPI_ADDRESS_NONE;
     sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
     sCommand.DataMode = QSPI_DATA_NONE;
     sCommand.DummyCycles = 0;
     sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
     sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
     sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
    
     if (HAL_QSPI_Command(&hqspi, &sCommand, CSP_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
     return HAL_ERROR;
     }
    
     if (QSPI_AutoPollingMemReady(CSP_QPSI_MASSERASE_TIMEOUT_VALUE) != HAL_OK) {
     return HAL_ERROR;
     }
    
     return HAL_OK;
    
    }

     

    4 replies

    Graduate II
    February 13, 2024

    Are you sure the Winbond W25Q64 part you're using supports Writing Status Register 2 with it's own command?

    The 0x6B 1-1-4 command for memory mapping is apt to fail if QE isn't set.

    Graduate II
    February 13, 2024

    Most of the Winbond W25Qxx series support a Write Status Registers command that writes both SR1 and SR2 as a pair of bytes. A smaller subset support WRSR1 and WRSR2 as individual commands.

    Given the broad array of stock / parts, and the difficulty in determining which you have mounted, its probably inadvisable to use WRSR2 unless you know it works. You could probably read-back to check, but these and other QSPI frequently don't have a status reporting BAD / INVALID command.

    Probably supported on the W25Q64JV, but is that what you are using? Please indicate part marking.

    https://community.st.com/t5/stm32-mcus-products/what-are-all-the-things-i-need-to-create-my-external-loader/td-p/158844

    PFlor.2Author
    Graduate II
    February 13, 2024

    sorry I replied on the wrong post earlier...tried to copy it here but wouldn't take.  Couldn't delete the reply on the other post either, ugh...

    https://community.st.com/t5/stm32-mcus-products/what-are-all-the-things-i-need-to-create-my-external-loader/td-p/158844

    Yes, the part is the W25Q64JVSIQ.  As I mentioned in the other reply, I've been using this in memory mapped mode with TouchGFX in my application for some time now so I'm pretty confident the CSP_QSPI_EnableMemoryMappedMode() is working.  If I'm understanding you correctly, I believe the memory mapped mode would not work if this was the issue.

    PFlor.2Author
    Graduate II
    March 19, 2024

    Found a resolution for this issue...

    Apparently the enabling interrupts in the Init() function of the Loader_Src.c provided in the ST repository for the H7 external loader was hanging after it entered this function the first time.  Made the modifications below per ST suggestion...

    PFlor2_0-1710859554743.png 

    Once this was done however the HAL_Delay() in my QuadSPI drivers would hang (made sense since interrupts are disabled I guess) so I also had to include a local HAL_Delay() function that used NOP instead of ticks.

    I added this in my quadspi.c file...

    PFlor2_1-1710859743199.png

    ST support is still looking into whey the enabling of interrupts is hanging in this case.

     

    Graduate II
    March 19, 2024

    They need to move to a model that doesn't use interrupts.

    If the board is running at 64 MHz, you can enable TIM2 / TIM5, with PSC=64000-1, ARR=0xFFFFFFFF, and you can pull the millisecond count from TIM->CNT

    Using HAL_Delay() will make things slow. The HAL_GetTick() should be used to provide a bounding timeout, but functions should return as soon as the device is ready / finished.

    PFlor.2Author
    Graduate II
    December 9, 2024

    Tesla I have a mostly working external loader I developed for the Windbond W25Q64JV but for some reason the "Erase Chip" function for the external flash fails with the STM32Programmer as seen below...

    PFlor2_0-1733777190465.png

     

    This function works fine with the loader you provided for me (CLIVEONE-W25Q64_STM32H7XX-PB2-PB6-PD11-PF9-PE2-PA1.stldr) back in May 2023.  Could you share your W25Q64 driver code with me so I can see what is wrong with mine?

    PFlor.2AuthorAnswer
    Graduate II
    December 11, 2024

    Just to wrap up the solution to this LONG thread....

    Initially I was using TIM6 for the timebase (based on application using FreeRTOS that cannot use SysTick) but the NVIC priority was set to 15.  I'm not sure if the priority was the problem or some timeout with the Loader_Src.c Init() function, but the ST Support solution to comment out __set_PRIMASK(0); that enabled interrupts just masked the issue and since the interrupts were no longer running the HAL_GetTick() never incremented so timeout values made no difference and I had HAL_Delay() overridden to use a loop of NOP.

    PFlor2_0-1733955529552.png

    By using SysTick for the Timebase and setting it's NVIC priority to 0 instead of 15 (default) I was able to use enable interrupts in Init() and use the standard HAL_Delay() and HAL_GetTick() just fine and almost everything worked just fine.  However, the Chip Erase still failed....Tesla was correct that this was a timeout issue.  Basically, I had a timeout value of 20000 (HAL_QSPI_TIMEOUT_DEFAULT_VALUE) I was using for most the QSPI functions.  I started using a larger value for erasing the chip, but I was using this larger timeout for issuing the erase chip command when in fact the HAL_QSPI_AutoPolling() is what needed the larger timeout value since that is what is waiting for the erase to complete.  Once I modified my AutoPolling function to use a larger timeout when doing a chip erase then that method started working as well.   Just multiple misunderstanding of how this loader works on my part on multiple fronts.

    #define CSP_QPSI_TIMEOUT_DEFAULT_VALUE 20000
    #define CSP_QPSI_MASSERASE_TIMEOUT_VALUE 65000
    
    
    uint8_t CSP_QSPI_Erase_Chip(void) {
    
     QSPI_CommandTypeDef sCommand = { 0 };
    
     if (QSPI_WriteEnable() != HAL_OK) {
     return HAL_ERROR;
     }
    
     /* Erasing Sequence --------------------------------- */
     sCommand.InstructionMode = QSPI_INSTRUCTION_1_LINE;
     sCommand.Instruction = CHIP_ERASE_CMD;
     sCommand.AddressMode = QSPI_ADDRESS_NONE;
     sCommand.AlternateByteMode = QSPI_ALTERNATE_BYTES_NONE;
     sCommand.DataMode = QSPI_DATA_NONE;
     sCommand.DummyCycles = 0;
     sCommand.DdrMode = QSPI_DDR_MODE_DISABLE;
     sCommand.DdrHoldHalfCycle = QSPI_DDR_HHC_ANALOG_DELAY;
     sCommand.SIOOMode = QSPI_SIOO_INST_EVERY_CMD;
    
     if (HAL_QSPI_Command(&hqspi, &sCommand, CSP_QPSI_TIMEOUT_DEFAULT_VALUE) != HAL_OK) {
     return HAL_ERROR;
     }
    
     if (QSPI_AutoPollingMemReady(CSP_QPSI_MASSERASE_TIMEOUT_VALUE) != HAL_OK) {
     return HAL_ERROR;
     }
    
     return HAL_OK;
    
    }

     

    Explorer II
    February 20, 2025

    Hello,

    I am usig STM32H730ZBT6 with S25FL064LABNFI041 external Flashe and facing the same "Failed to erase memory" error. I have tried everything commented in this post and some others, but without success.

    I upload my project for the case someone could check it.

    I have already spent 3 days with this issue and I can't afford more, but it is essential for carrying out or projects, so any help will be really grateful.

    Thank you in advance and regards.

    Egoitz.