cancel
Showing results for 
Search instead for 
Did you mean: 

Generating external Loader (.stldr) for specific hardware

MiladChalipa
Senior

In the last weeks, I was working on running W25Q256 nor flash chip from vendor Winbond with STM32F746 MCU on a custom board. My guideline in this road is ST's how to run QSPI flash video tutorial (5-part video) and of course some genius guys in the community who's helped me a lot to rewrite the functions of QSPI flash (Init, Erase, Write, Memory-mapped). So far functions tested in the Main.c and I can read the pre-written data on the memory. The next step is to generate (.stldr) external loader file and modify Flash.ld file.

according to the video tutorial, I added Loader_Src.c, dev_inf.c, and dev_inf.h files to the workspace but there is a little confusion about flash.ld file that contains memory definitions and all other data and text stuff to assign to specific memory (>FLASH, >RAM, >QUADSPI).

for the point of concern, I use STM32F746 with IS42S32400F SD-RAM connected with 2-banks to MCU and of-course W25Q256 NOR-FLASH.

  1. how to modify flash.ld file to my specific condition and generate .stldr file using loader files added?
  2. I generated an external loader file before, but when I added the loader file to the CUBEPROGRAMMER directory, it didn't recognize by the programmer and got an error with blank fields in EL section of the programmer!

here I uploaded relevant files for check

STM32F746BGTX_FLASH.ld

/**
 ******************************************************************************
 * @file      LinkerScript.ld
 * @author    Auto-generated by STM32CubeIDE
 * @brief     Linker script for STM32F746BGTx Device from STM32F7 series
 *                      1024Kbytes FLASH
 *                      320Kbytes RAM
 *
 *            Set heap size, stack size and stack location according
 *            to application requirements.
 *
 *            Set memory bank area and size if external memory is used
 ******************************************************************************
 * @attention
 *
 * <h2><center>&copy; Copyright (c) 2020 STMicroelectronics.
 * All rights reserved.</center></h2>
 *
 * This software component is licensed by ST under BSD 3-Clause license,
 * the "License"; You may not use this file except in compliance with the
 * License. You may obtain a copy of the License at:
 *                        opensource.org/licenses/BSD-3-Clause
 *
 ******************************************************************************
 */
 
/* Entry Point */
ENTRY(Reset_Handler)
 
/* Highest address of the user mode stack */
_estack = ORIGIN(RAM) + LENGTH(RAM);	/* end of "RAM" Ram type memory */
 
_Min_Heap_Size = 0x200 ;	/* required amount of heap  */
_Min_Stack_Size = 0x400 ;	/* required amount of stack */
 
/* Memories definition */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,  LENGTH = 320K
  FLASH    (rx)   : ORIGIN = 0x8000000,   LENGTH = 1024K
}
 
/* Sections */
SECTIONS
{
  /* The startup code into "FLASH" Rom type memory */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH
 
  /* The program code and other data into "FLASH" Rom type memory */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    *(.eh_frame)
 
    KEEP (*(.init))
    KEEP (*(.fini))
 
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH
 
  /* Constant data into "FLASH" Rom type memory */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH
 
  .ARM.extab   : { 
    . = ALIGN(4);
    *(.ARM.extab* .gnu.linkonce.armextab.*)
    . = ALIGN(4);
  } >FLASH
  
  .ARM : {
    . = ALIGN(4);
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
    . = ALIGN(4);
  } >FLASH
 
  .preinit_array     :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
    . = ALIGN(4);
  } >FLASH
  
  .init_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
    . = ALIGN(4);
  } >FLASH
  
  .fini_array :
  {
    . = ALIGN(4);
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
    . = ALIGN(4);
  } >FLASH
 
  /* Used by the startup to initialize data */
  _sidata = LOADADDR(.data);
 
  /* Initialized data sections into "RAM" Ram type memory */
  .data : 
  {
    . = ALIGN(4);
    _sdata = .;        /* create a global symbol at data start */
    *(.data)           /* .data sections */
    *(.data*)          /* .data* sections */
 
    . = ALIGN(4);
    _edata = .;        /* define a global symbol at data end */
    
  } >RAM AT> FLASH
 
  /* Uninitialized data section into "RAM" Ram type memory */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss section */
    _sbss = .;         /* define a global symbol at bss start */
    __bss_start__ = _sbss;
    *(.bss)
    *(.bss*)
    *(COMMON)
 
    . = ALIGN(4);
    _ebss = .;         /* define a global symbol at bss end */
    __bss_end__ = _ebss;
  } >RAM
 
  /* User_heap_stack section, used to check that there is enough "RAM" Ram  type memory left */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM
 
  /* Remove information from the compiler libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
 
  .ARM.attributes 0 : { *(.ARM.attributes) } 
}

 Dev_inf.c

/*
 * Dev_Inf.c
 *
 */
#include "Dev_Inf.h"
#include "quadspi.h"
 
/* This structure contains information used by ST-LINK Utility to program and erase the device */
#if defined (__ICCARM__)
__root struct StorageInfo const StorageInfo  =  {
#else
struct StorageInfo const StorageInfo = {
#endif
    "QSPI_flashloader_CSP",                  // Device Name + version number
    NOR_FLASH,                           // Device Type
    0x90000000,                          // Device Start Address
    MEMORY_FLASH_SIZE,                   // Device Size in Bytes
    MEMORY_PAGE_SIZE,                    // Programming Page Size
    0xFF,                                // Initial Content of Erased Memory
 
    // Specify Size and Address of Sectors (view example below)
    {   {
            (MEMORY_FLASH_SIZE / MEMORY_SECTOR_SIZE),  // Sector Numbers,
            (uint32_t) MEMORY_SECTOR_SIZE
        },       //Sector Size
 
        { 0x00000000, 0x00000000 }
    }
};

35 REPLIES 35
MiladChalipa
Senior

@Community member​ 

Dear Clive, would you please make an external loader for me? cause it becomes really really annoying to me:confounded_face:.

My flash chip: W25Q256FV

Pinouts:

  PF6   ------> QUADSPI_BK1_IO3

  PF7   ------> QUADSPI_BK1_IO2

  PF8   ------> QUADSPI_BK1_IO0

  PF9   ------> QUADSPI_BK1_IO1

  PB2   ------> QUADSPI_CLK

  PB6   ------> QUADSPI_BK1_NCS

it would really helps.

Note: this is a commercial project and not a hobby, So I'm running out of time. please let me know if a refund needed😉

I have a W25Q64/128 one built (3-Byte Addressing), I'll need to finish porting the 256 (4-Byte)

The initial load on the H7 is still broken in Cube Programmer, so a disconnect/connect is required before it runs the STLDR/ELF Init function properly

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

This might work...

Still under development

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

0693W000006I5fOQAS.png@Community member​ Unfortunately none of them works. still, has init fail error even when connect/disconnect.

Actually (maybe) it is because of the H7 compatible loader, Mine is F746 instead. As you know, the RAM start address and vector table location are different from H7.

Ok, sorry, had H7 on the bench, will migrate something to the F7

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

@Community member​ I can't believe it works...Thanks a lot, each and every function are completely OK, saved my life, Clive. ST community is meanless without your efforts man.:baby_angel:

Thank you so much for the hard work @Community member​ . I am currently trying to make a flash loader for an H7 for a W25Q128, unfortunately yours doesn't work on my case probably because of the many variations of W25Q128 ( I own an W25Q128JVSIQ and I guess you own a FV due to the naming convention on the next file). Do you happen to have the .c and .h driver files for the stldr ? I guess I will have to do some very small modifications. Thank you in advance.

Spyros

If anyone is interested here are my logs from cube programmer with verbosity level=3 while trying to flash a small bin of 9 bytes .

Current builds are here for assortment of pin configurations

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

My fixtures are for the 300-mil SOIC-16 devices not the SOIC-8 ones. Functionally they should be identical.

If you have working/tested BSP code for your platform I can review that in the context of it not working in the loader context.

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