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

@Community member​ Thank you very much and sorry for the late response I was out of office , unfortunately my pin configuration is :

PB2,PB10,PC9,Pc10,PD13,PE2 which is not mentioned on your github files. I would find the source much more usefull though as I am not only in need of a flash loader but also a driver. About my current bsp I have copied this project which is very similar to mine https://github.com/uraetech/STM32H750-Development-Board/tree/master/H750%20QSPI%20W25Q128 and change some register definitions for compatibility between JV and FV variants with no success I can only read the flash,read the manufacturers Id but not erase or write

Thanks again Spyros M.

There are so many pin combinations.

https://github.com/cturvey/stm32extldr/blob/main/h7_w25q128/CLIVEONE-W25Q128_STM32H7XX-PB2-PB10-PC9-PC10-PE2-PD13.stldr

These particular ones are coded in assembler, with a table driven pin initialization list. Really don't furnish source for these as it involves more tools and support than I can afford to provide.

Writing and Erasing can't occur concurrently with Memory Mapped Read

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

Current STLDR and FLM (Keil) forks for these now live here

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

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

@Community member​ Thank you very much.

Unfortunately this doesn't work.Probably because of the different register bits between W25Q128JV and W25Q128FV , cube programmer stucks at erasing sector 0 for a minute and then it throws errors . I am aware that Writing and Erasing can't occur concurrently with Memory Mapped Read but I want the full driver in my use case for the reason below:

My product will store some bitmaps on the flash ,also my product will have a bootloader and probably many updates will occur.On the updates the bitmaps will probably change so the bootloader responsible for the updates will have to do what a flash loader does but without a jtag and with a usb for more user friendliness . And that's why I need to implement a whole driver and not only the memory mapped part.Thanks for the effort , it is bad that I didn't achieve what I wanted but I guess there are no shortcuts in my case.

Here are my logs by the way

EDIT :

@Community member​ Thank you very much.

oof I had a hardware problem , I was nor reading neither writing to flash IO3 due to a hardware error , my pin configuration is

PB2-> Clock

PB10-> CS

PC9 -> IO0

PD12 -> IO1

PD13-> IO2

PE2-> IO3

I am very sorry for the trouble!

The things are relatively easy to modify at this point.

PE2 should be D2/IO2

PD13 should be D3/IO3

It you have these switch we might need to use DUAL mode rather than QUAD

What's the key difference of the JV vs FV in your experiments?

Can you should schematic section for this as built?

This is my pin cheat sheet (although I think the AF mapping is slightly different for OSPI)

https://github.com/cturvey/stm32extldr/blob/main/h7pins.txt

Winbond parts to hand : W25Q128BVFG W25Q64BVFIG W25Q256FVFG W25Q512JVFQ

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

https://github.com/cturvey/stm32extldr/blob/main/h7_w25q128/CLIVEONE-W25Q128_STM32H7XX-PB2-PB10-PC9-PD12-PE2-PD13.stldr

Not currently supporting DTR/DDR modes, loader doesn't really benefit from them. Also can't find readily available JVF(I)M parts in the SOP/SOIC-16 300mil form-factor currently. If someone has a few pieces they can send me, drop me an email.

W25Q128JVFIQ

W25Q128JVFIM (DTR)

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

The screen I made with Touchgfx works just fine. But Flash Memory is at 82% and will be full soon. So I need to implement QSPI. I have W25Q128JVSQ Flash and 176 pin STM32H743IITx board. Could you please prepare an MX file (with .ioc extension) for me? I work in a company that carries out an R&D project and I need to finish this job as soon as possible. Otherwise it won't be good for me.

KADAY.1
Associate II

0693W00000D2h1JQAR.jpg0693W00000D2h6hQAB.jpg0693W00000D2h6SQAR.jpg

KADAY.1
Associate II

These (4 pictures) are the images of the product, can you please help me urgently?

KADAY.1
Associate II

0693W00000D2h7pQAB.png