Skip to main content
Explorer
October 23, 2023
Question

STM32H5 external loader

  • October 23, 2023
  • 20 replies
  • 15025 views

Hi,

 I need the project used to generate the external loader: MX25LM51245G_STM32H573I-DK.stldr. My custom board uses a STM32H563VIT6 and the same octo-spi flash from Macronix used in the STM32H573I-DK board. But with different gpios connections. So this project would be of great help to develop the external flash loader for my board.

 

Ari

    This topic has been closed for replies.

    20 replies

    Graduate II
    October 23, 2023

    Could probably get something close via  https://github.com/STMicroelectronics/stm32-external-loader/tree/main/STM32L5x_boards/MX25LM51245G_STM32L562E-DK

    With a pin list I could probably patch the current one, or port one of the H7/U5 variants I have working.

    Technical Moderator
    October 24, 2023

    Hi @AMend.7 ,

    Besides, the reply shared by @Tesla DeLorean, thanks to STM32CubeProgrammer software description you can create your own external loader.

    For that, please follow the steps shared in UM2237 and precisely 2.3.3 Developing customized loaders for external memory section.

    I hope this help you!

    Kaouthar

    Graduate II
    October 24, 2023

    I think having some XSPI examples for the H5 would seem like a more pressing need.

    https://github.com/STMicroelectronics/stm32-external-loader/tree/main

    Ported some of my Winbond Quad examples over to H5, building at least, but not something I can test in the near term.

    I think the manual falls short of the overall complexity and difficulty in constructing and testing external loaders. And they could have be designed with a lot better thought to allow for pin level configurability.

    Technical Moderator
    October 25, 2023

    Hi @AMend.7 ,

    I noted that the same request is already shared with your FAE.

    For sure he will get back to you if a project is available.

    Thank you.

    Kaouthar

    Graduate II
    October 25, 2023

    Yes, having in the OSPI / XSPI Examples directory would be the way to go, using the BSP/CSP code or whatever so there's a single point of change for porting. Ideally putting code here would force the dog-fooding of tools/resources, ie one where ST has to get it right and tested because it's what they have to use day in and out.

    I did order up some additional NUCLEO-H5's from DigiKey, but I should be able to patch the .STLDR before they get here.

    ; ARI STM32H563VIT6 MX25LM51245G
    ;
    ; PE11 ------> OCTOSPI1_NCS AF6
    ; PB2 ------> OCTOSPI1_DQS AF10
    ; PA3 ------> OCTOSPI1_CLK AF3
    ; PD11 ------> OCTOSPI1_IO0 AF9
    ; PD12 ------> OCTOSPI1_IO1 AF9
    ; PC2 ------> OCTOSPI1_IO2 AF9
    ; PD13 ------> OCTOSPI1_IO3 AF9
    ; PE7 ------> OCTOSPI1_IO4 AF10
    ; PE8 ------> OCTOSPI1_IO5 AF10
    ; PE9 ------> OCTOSPI1_IO6 AF10
    ; PE10 ------> OCTOSPI1_IO7 AF10
    AMend.7Author
    Explorer
    October 25, 2023

    I discovered that there is an MX25LM51245G driver equivalent to the one used in the flash loader project for the U5 dev boards, but adapted for the XSPI interface. I'll try to make the flash loader from this driver.

    \STM32Cube_FW_H5_V1.1.1\Drivers\BSP\Components\mx25lm51245g

    I don't understand why ST changed from OSPI to XSPI in the STM32H5's HAL library, if the H5's OSPI hardware is the same as the U5's.

    Graduate II
    October 25, 2023

    That and I could only find 8 IO pins on the H5 I was looking at. The code churn drives me mental..

    Graduate II
    October 27, 2023

    Ok, looks like my H5 boards will come in on Monday

    @Aziz BRIGUI is there some rational behind H5 external loaders building at 0x20003004 ?

    ========================================================================
    
    ** ELF Header Information
    
     File Name: MX25LM51245G_STM32H573I-DK.stldr
    
     Machine class: ELFCLASS32 (32-bit)
     Data encoding: ELFDATA2LSB (Little endian)
     Header version: EV_CURRENT (Current version)
     Operating System ABI: none
     ABI Version: 0
     File Type: ET_EXEC (Executable) (2)
     Machine: EM_ARM (ARM)
    
     Image Entry point: 0x20003005
     Flags: None (0x05000000)
    
     ARM ELF revision: 5 (ABI version 2)
    
     Conforms to Base float procedure-call standard
    
     Header size: 52 bytes (0x34)
     Program header entry size: 32 bytes (0x20)
     Section header entry size: 40 bytes (0x28)
    
     Program header entries: 2
     Section header entries: 20
    
     Program header offset: 159376 (0x00026e90)
     Section header offset: 159440 (0x00026ed0)
    
     Section header string table index: 1
    
    ========================================================================
    
    ** Program header #0 (PT_LOAD) [PF_R]
     Size : 200 bytes
     Virtual address: 0x00000000 (Alignment 4)
    
    
    ====================================
    
    ** Program header #1 (PT_LOAD) [PF_X + PF_W + PF_R]
     Size : 16205 bytes
     Virtual address: 0x20003004 (Alignment 4)
    
    
    ========================================================================
    Graduate
    July 24, 2024

    hi!

    did you succeed to make the external loader?

    I'm trying my best, I have a functional driver for a quad quad spi memory but when I make the external loader it doesn't work (read data failed)

    I'm using the NUCLEO-H563ZI with a MX25L512 

    I think I have problem with the linker file

    if you have succeeded can you share your project?

    best regards

     

     

    Graduate II
    July 24, 2024

    Ultimately I did get the OCTO part (MX25LM) working for Ari, as I recall.

    I do have my own H5 QSPI External Loaders working too now, for the MX25L and W25Q series, and can build to order. This for the MX25L64 but just needs a recompile with pin details for an MX25L512

    https://github.com/cturvey/stm32extldr/tree/main/h5_mx25l6433f

    This is my H5 Linker Script for a build using HAL and GNU/GCC + MAKE, ie not Cube and without interrupt non-sense.

    https://github.com/cturvey/stm32extldr/blob/main/ExternalLoader_H5.ld

    Graduate
    July 25, 2024

    thank you!

    today  i will try to use your linker file!

    i only have two  questions if you want to answer:

    RAM_INFO (r) : ORIGIN = 0, LENGTH = 1K /* 200-byte StorageInfo */
    RAM_PROG (xrw) : ORIGIN = 0x20003004, LENGTH = 256K-12292 /* 0x20003004 for H5 ?? */

    1) why the origin is at 0x20003004?

    2) in the Loader_src.c file i have to change the address of VTOR.

    if i understand well the line SCB->VTOR = 0x20000000 | 0x200; should be modified in SCB->VTOR = 0x20003004;

    am i correct?

    thank you!

    Graduate
    July 28, 2024

    Hello!

    i have followed your advise , i have instrumented with UART 

     

    i found someting really strange to me:

     

    the problem occours in this piece of code (that work without problem in the main):

    uint8_t CSP_QUADSPI_Init(void)
    {
     
    uint8_t mark1[] = "MARK1";
    uint8_t mark2[] = "MARK2";
    uint8_t mark3[] = "MARK3";
     
    HAL_UART_Transmit(&huart3,mark1,sizeof(mark1),1000);
     
      //prepare QSPI peripheral for ST-Link Utility operations
      if(HAL_XSPI_DeInit(&hospi1) != HAL_OK)
      {
      HAL_UART_Transmit(&huart3,mark2,sizeof(mark2),1000);
      return HAL_ERROR;
      }
     
      HAL_UART_Transmit(&huart3,mark3,sizeof(mark3),1000);
     
      MX_OCTOSPI1_Init();
     
      if(QSPI_ResetChip() != HAL_OK)
      {
        return HAL_ERROR;
      }
     
      HAL_Delay(1);
     
      if(QSPI_AutoPollingMemReady() != HAL_OK)
      {
        return HAL_ERROR;
      }
     
      if(QSPI_WriteEnable() != HAL_OK)
      {
        return HAL_ERROR;
      }
     
      if(QSPI_Configuration() != HAL_OK)
      {
        return HAL_ERROR;
      }
     
      return HAL_OK;
    }
     
    on the UART we can see "MARK1",but the code does'nt return from HAL_XSPI_DeInit(&hospi1)
    after "MARK1" nothing more appen on the UART, no "MARK2" and no "MARK3"
     
    it seems the code is stuck inside HAL_XSPI_DeInit(&hospi1) that is code written by cube ide , the function is in the file stm32h5xx_hal_xspi.c 
     
    i attach the file at this message
     
     
     
     

     

    Graduate II
    July 28, 2024

    Make sure hospi1 structure has the instance defined, there is not static initialization in loaders. Perhaps Hard Faulting or delays not working

    Graduate
    July 30, 2024

    Hi!

    you were right!

    the problem was the call to the HAL_XSPI_DeInit(&hospi1) before the call to MX_OCTOSPI1_Init()!

    its not possible to just remove the HAL_XSPI_DeInit(&hospi1), because during the sectors erase the init is called before each sector erase by the st programmer

    so i use this method:

    uint8_t CSP_QUADSPI_Init(void)
    {
     
      console(consoleDefault,"INIT QUADSPI\r\n");
     
      //prepare QSPI peripheral for ST-Link Utility operations
     
      if(hospi1.Instance == OCTOSPI1)
      {
           if(HAL_XSPI_DeInit(&hospi1) != HAL_OK)
           {
            console(consoleDefault,"DEINIT ERROR\r\n");
           return HAL_ERROR;
          }
         console(consoleDefault,"DEINIT OK\r\n");
      }
     
      MX_OCTOSPI1_Init();
     
      if(QSPI_ResetChip() != HAL_OK)
      {
        return HAL_ERROR;
      }
     
      HAL_Delay(1);
     
      if(QSPI_AutoPollingMemReady() != HAL_OK)
      {
        return HAL_ERROR;
      }
     
      if(QSPI_WriteEnable() != HAL_OK)
      {
        return HAL_ERROR;
      }
     
      if(QSPI_Configuration() != HAL_OK)
      {
        return HAL_ERROR;
      }
     
      return HAL_OK;
    }

    now i am able to read an sector erase the external memory!!!

    but not to write....

     

    the write function is called multiple times.. but only the first is going OK

     

    int
    Write(uint32_t Address, uint32_t Size, uint8_t* buffer) {
     
     
    console(consoleDefault,"WRITE\r\n");
    __set_PRIMASK(0); //enable interrupts
     
     
    if(hospi1.Instance != OCTOSPI1)
    {
    console(consoleDefault,"INSTANCE err\r\n");
    }
     
    if (HAL_XSPI_Abort(&hospi1) != HAL_OK) {
        console(consoleDefault,"WRITE abort err\r\n");
            __set_PRIMASK(1); //disable interrupts
            return LOADER_FAIL;
        }
     
        if (CSP_QSPI_WriteMemory((uint8_t*) buffer, (Address & (0x0fffffff)), Size) != HAL_OK) {
        console(consoleDefault,"WRITE err\r\n");
            __set_PRIMASK(1); //disable interrupts
            return LOADER_FAIL;
        }
     
        __set_PRIMASK(1); //disable interrupts
        return LOADER_OK;
    }
     
    the second time the HAL_XSPI_Abort return ERROR!
     
    i don't know why this firmware is like the Omero odyssey...

     

     

     

    Graduate
    July 30, 2024

    found the issue..

     

    the HAL_XSPI_Abort(&hospi1)  if don't have anything to abort return an error.. 

    hospi->ErrorCode = HAL_OSPI_ERROR_INVALID_SEQUENCE;

     

    the first time we call it the memory is in memory mapped mode.. so it is necessary and  it work.. the second time it is not necessary and return error..

     

    i have added a check on the status of the periferal before call the abort function and added the function that enable memory mapped mode at the end of the write (i do'n know if is necessary the last call of the write)..

     

    so .. only the chip erase now is missing (its optional)

    Graduate
    July 30, 2024

    finally all is working!

    the chip erase was a problem of timeout , the default autopolling have HAL_XSPI_TIMEOUT_DEFAULT_VALUE for timeout that is 5s, my memory have a typical erasing time of 140s to max 200s so i have increased the value to 200s and now its working!

     

    i have tried to remove the offset to RAM (xrw) : ORIGIN = 0x20003004, LENGTH = 256K - 12292 but its actually necessary ..  i think only ST could explain why!

     

    i attache to this comment my working  linker file and loader_src.c 

     

    thank you to everyone for the really precious advise!

     

     

     

     

    Graduate II
    July 30, 2024

    Yes, the 0x20003004 needs a bit more documentation from ST, but is what other working H5 loaders use.

    The +4 offset comes from the fact that ST stuffs opcodes at +0 to call the entry point functions, ie Init(), Read(), etc.

    /**
     * @brief Initializes the QSPI interface.
     * @retval QSPI memory status
     */
    static uint8_t BSP_XSPI_Init(XSPI_HandleTypeDef *hospi)
    {
     //memset(hospi, 0, sizeof(XSPI_HandleTypeDef));
    
     hospi->Instance = OCTOSPI1; // For DeInit to bite on
    
     /* Call the DeInit function to reset the driver */
     if (HAL_XSPI_DeInit(hospi) != HAL_OK)
     {
     return(XSPI_ERROR);
     }
    
     /* System level initialization */
     BSP_XSPI_MspInit(hospi, NULL);
    
     /* OSPI initialization */
     hospi->Init.FifoThresholdByte = 1; // 1..32 Interrupt threshold
    ...