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
KADAY.1
Associate II

@Community member​  Please take these messages into consideration. And your help would be greatly appreciated. I need some free space and I don't know anything about it (I don't know how my Board will recognize Flash).

Should probably have started a new thread for this

Perhaps check out embryonic.dk he has a number of related videos

https://www.youtube.com/watch?v=237lPdMsDZs

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

hi Tesla Delorean

i need w25q256fv stldr for h743i.

the loader that you upload for this, erased successfully, but not validate erase...

can you help me and share the source of the w25q source project or generate

CLIVEONE-W25Q256FV_STM32FHXX-PB2-PB6-PF8-PF9-PF7-PF6

for me.

thank

PKann.1
Associate

MiladChalipa

Hi, Can you please share QSPI flash driver, with the updated Memory read/write/erase functions?

Please help, thankyou.

Hello.

thanks for your responses. 

I'm trying to create a .stldr file for stm32h7b0vbt6 and W25Q64.
at first I wrote all needed OSPI (QSPI) functions and I tested all of them. everything is ok. then according to ST tutorials (5 videos on youtube) I started to create stldr file. I added files to my project (in CubeIDE). then I write appropriate functions in CSP_QSPI_... functions. 

I realized an important different between N25Q series (that are used on those videos) with W25Q series. in N25Q, we have sectors, sub-sectors and pages. but in W25Q we have blocks, sectors and pages. so in W25Q, blocks are equivalent to sectors in N25Q and so we should notice that.

I did all of that. at last I tested functionalities with sample test (in github repo of that tutorial). every thing was good. then I used linker.ld to create stldr file. I generated it and copied it into external loaders directory of CubeProgrammer. I used it to write my app to external flash. and this was the result:

mass storage function: it works very good

sector erase: that is ok

write: when sector erase ends and CubeProgrammer wants to write my hex file, after writing 428KB of data, it give me an error and stops. and then when I compare the memory data with main hex file I see exactly from this address everything is clear (0xFF) in external flash.

I'm working on it for about 1 week and I can not realize what is the problem. 

do you have any help for me?
I attached the code of Core directory of CubeIDE project + the linker.ld file (in that tutorial github repo we have two directories: one for H7 series and one for another according to SRAM addresses)

thanks

Rebuilt my earlier OCTOSPI loader with the pin configuration

https://github.com/cturvey/stm32extldr/blob/main/h7_w25q64/CLIVEONE-W25Q64_STM32H7AX-PB2-PB6-PD11-PD12-PE2-PD13.stldr

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