STM32F4 Passen Sie das Linker-Skript an, um Speicher für die EEPROM-Emulation zu sparen

Ich muss FLASH für meine virtuelle EEPROM-Emulation auf einem STM32F405VGT6 reservieren:

https://www.mouser.ch/datasheet/2/389/stm32f405rg-956214.pdf

Die Seiten, die ich benötige, befinden sich in Sektor 2 und Sektor 3 des Flashs und nicht am Ende der Flash-Region. Also brauche ich so etwas:

MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 32k
EMULATED_EEPROM (rwx) : ORIGIN = 0x8008000 LENGTH=2*16k
FLASH (rx)      : ORIGIN = 0x8008000+2*16k, LENGTH = 1024k-(32k+2*16k)
}

Aber dieses ofc. funktioniert nicht. Wie kann ich das Linker-Skript anpassen, um diese Partitionsreservierung des Flash-Speichers zu erreichen?

Blinken

Linker-Skript:

/*
*****************************************************************************
**

**  File        : stm32_flash.ld
**
**  Abstract    : Linker script for STM32F405VG Device with
**                1024KByte FLASH, 128KByte RAM
**
**                Set heap size, stack size and stack location according
**                to application requirements.
**
**                Set memory bank area and size if external memory is used.
**
**  Target      : STMicroelectronics STM32
**
**  Environment : Atollic TrueSTUDIO(R)
**
**  Distribution: The file is distributed as is, without any warranty
**                of any kind.
**
**  (c)Copyright Atollic AB.
**  You may use this file as-is or modify it according to the needs of your
**  project. This file may only be built (assembled or compiled and linked)
**  using the Atollic TrueSTUDIO(R) product. The use of this file together
**  with other tools than Atollic TrueSTUDIO(R) is not permitted.
**
*****************************************************************************
*/

/* Entry Point */
ENTRY(Reset_Handler)

/* Highest address of the user mode stack */
_estack = 0x20020000;    /* end of RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0x200;      /* required amount of heap  */
_Min_Stack_Size = 0x400; /* required amount of stack */

/* Specify the memory areas */
MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
FLASH (rx)      : ORIGIN = 0x8000000, LENGTH = 1024K
}

/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH

  /* The program code and other data goes into FLASH */
  .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 goes into FLASH */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
  .ARM : {
    __exidx_start = .;
    *(.ARM.exidx*)
    __exidx_end = .;
  } >FLASH

  .preinit_array     :
  {
    PROVIDE_HIDDEN (__preinit_array_start = .);
    KEEP (*(.preinit_array*))
    PROVIDE_HIDDEN (__preinit_array_end = .);
  } >FLASH
  .init_array :
  {
    PROVIDE_HIDDEN (__init_array_start = .);
    KEEP (*(SORT(.init_array.*)))
    KEEP (*(.init_array*))
    PROVIDE_HIDDEN (__init_array_end = .);
  } >FLASH
  .fini_array :
  {
    PROVIDE_HIDDEN (__fini_array_start = .);
    KEEP (*(SORT(.fini_array.*)))
    KEEP (*(.fini_array*))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH

  /* used by the startup to initialize data */
  _sidata = LOADADDR(.data);

  /* Initialized data sections goes into RAM, load LMA copy after code */
  .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

  _siccmram = LOADADDR(.ccmram);

  /* CCM-RAM section 
  * 
  * IMPORTANT NOTE! 
  * If initialized variables will be placed in this section,
  * the startup code needs to be modified to copy the init-values.  
  */
  .ccmram :
  {
    . = ALIGN(4);
    _sccmram = .;       /* create a global symbol at ccmram start */
    *(.ccmram)
    *(.ccmram*)

    . = ALIGN(4);
    _eccmram = .;       /* create a global symbol at ccmram end */
  } >CCMRAM AT> FLASH


  /* Uninitialized data section */
  . = ALIGN(4);
  .bss :
  {
    /* This is used by the startup in order to initialize the .bss secion */
    _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 left */
  ._user_heap_stack :
  {
    . = ALIGN(4);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM



  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }

  .ARM.attributes 0 : { *(.ARM.attributes) }
}

Antworten (2)

Sie können versuchen (nie selbst getestet)

MEMORY
{
RAM (xrw)      : ORIGIN = 0x20000000, LENGTH = 128K
CCMRAM (rw)      : ORIGIN = 0x10000000, LENGTH = 64K
FLASH_1 (rx)      : ORIGIN = 0x8000000, LENGTH = 32k
EMULATED_EEPROM (rwx) : ORIGIN = 0x8008000 LENGTH=2*16k
FLASH (rx)      : ORIGIN = 0x8008000+2*16k, LENGTH = 1024k-(32k+2*16k)
}

  .text2 :  
  {  
    ...  
  } >> FLASH_1

  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* Startup code */
    . = ALIGN(4);
  } >FLASH_1

aber um irgendetwas in den text2-Abschnitt zu platzieren (einige Funktionen zum Beispiel), müssen Sie sie mit deklarieren__attribute__ ((section ("text2")))

Sie waren ziemlich nah dran - geben Sie ihnen einfach verschiedene Namen und stellen Sie sicher, dass alles an den richtigen Stellen ist.

Das Folgende sollte funktionieren (ich habe einen ähnlichen Code, der funktioniert), aber beachten Sie, dass der größte Teil der ersten Seite verschwendet wird, wenn dort nur der ISR-Vektor vorhanden ist (der unter 1k liegt). Sie können dort einen zusätzlichen Abschnitt hinzufügen - aber es muss speziell gekennzeichnet werden, was dort in den Code eingefügt wird, und IMO ist die Mühe für diese mageren 1,5% des gesamten Flash nicht wert.

Als Nebenbemerkung - ein solches Setup neigte dazu, meinen Debugger zu verwirren (ich weiß nicht, ob es GDB selbst oder QtCreator war, der GDB falsche Daten gab), sodass ich am Ende ein anderes Linker-Skript für Debugging-Zwecke verwendete.

MEMORY
{
    RAM (xrw)               : ORIGIN = 0x20000000, LENGTH = 128K
    CCMRAM (rw)             : ORIGIN = 0x10000000, LENGTH = 64K
    FLASH_BOOT (rx)         : ORIGIN = 0x8000000,
                              LENGTH = 32k
    EMULATED_EEPROM (rwx)   : ORIGIN = ORIGIN(FLASH_BOOT) + LENGTH(FLASH_BOOT), 
                              LENGTH=2*16k
    FLASH (rx)              : ORIGIN = ORIGIN(EMULATED_EEPROM) + LENGTH(EMULATED_EEPROM),
                              LENGTH = 1024k - LENGTH(FLASH_BOOT) - LENGTH(EMULATED_EEPROM)
}

SECTIONS
{
    .isr_vector :
    {
        . = ALIGN(4);
        KEEP(*(.isr_vector)) /* Startup code */
        . = ALIGN(4);
    } >FLASH_BOOT

    /* The program code and other data goes into FLASH */
    .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
}
Perfekt, jetzt funktioniert es super.
@HansPeterLoft Wenn es funktioniert, könnten Sie die Antwort akzeptieren?
Ich habe das gleiche Problem wie OP und habe diese Lösung ausprobiert - Sie lässt sich gut kompilieren und der Debugger startet korrekt in der Hauptdatei, aber sobald eine Funktion in einer separaten .cpp-Datei aufgerufen wird, tritt der MCU-Hardfault auf. (0x605122c <error: Cannot access memory at address 0x605122c>) - Irgendwelche Ideen, was ich übersehen habe?
@antipattern die Adresse in Ihrer Fehlermeldung sieht nicht richtig aus - ich habe seit über zwei Jahren nicht mehr mit STM32 gearbeitet, aber das ist niedriger als sogar der Arbeitsspeicher. Versuchen Sie, auf ein Peripheriegerät zuzugreifen? Oder haben Sie vielleicht eine nicht initialisierte Variable?
Entschuldigen Sie die Störung, es wurde durch einen fehlerhaften Lesevorgang in den Flash-Speicher verursacht, der im Konstruktor eines verschachtelten Klassenmitglieds ausgeführt wurde, das im Bereich dieses Funktionsaufrufs initialisiert wurde. Blöder Fehler meinerseits. Tolle Antwort aber!