cancel
Showing results for 
Search instead for 
Did you mean: 

Stm32 FreeRtos Internal Flash Linker Script

ebast
Associate II

I have some functions to read-and write to memory to STM32F103 internal memory. This functions work on the gcc and standard linker script. When I want to use the internal flash with stm32 and freertos. FreeRtos does not allow to me access when I want to write a data into internal flash. Here is the standard freertos linker script file.

Default linker script file for freertos for stm32.

/*************************************************
* linker script for ST32F103 & MPU  REV 1.02
************************************************/ 
 
GROUP(libgcc.a libc.a)
 
 
MEMORY
{
    FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 1024K
    SRAM (xrw)  : ORIGIN = 0x20000000, LENGTH =  96K
}
/* Higher address of the user mode stack */
_estack = ORIGIN(SRAM)+LENGTH(SRAM);
/*
 *There will be a link error if there is not this amount of RAM free at the end.
 */
_Minimum_Stack_Size = 1K;
_Minimum_Heap_Size = 1K;
 
/* Variables used by FreeRTOS-MPU. */
_Privileged_Functions_Region_Size = 16K;
_Privileged_Data_Region_Size = 512;
 
__FLASH_segment_start__ = ORIGIN( FLASH );
__FLASH_segment_end__ = __FLASH_segment_start__ + LENGTH( FLASH );
 
__privileged_functions_start__ = ORIGIN( FLASH );
__privileged_functions_end__ = __privileged_functions_start__ + _Privileged_Functions_Region_Size;
 
__SRAM_segment_start__ = ORIGIN( SRAM );
__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( SRAM );
 
__privileged_data_start__ = ORIGIN( SRAM );
__privileged_data_end__ = ORIGIN( SRAM ) + _Privileged_Data_Region_Size;    
 
ENTRY(Reset_Handler)
 
SECTIONS
{
    /* 
        Privileged section at the start of the flash. 
        Vectors must be first whatever. 
    */
    .isr_vectors :
    {
        . = ALIGN(4);
        _isr_vectors_offs = . - __FLASH_segment_start__;
        KEEP(*(.isr_vectors))            /* Startup code */
    } >FLASH
    privileged_functions :
    {
        . = ALIGN(4);
        *(privileged_functions)
    } > FLASH
 
    /* Non privileged code starts here. */
    .text_offset :
    {
        . = ALIGN(4);
        . =  . + _Privileged_Functions_Region_Size;
    } > FLASH
    .text :
    {
        . = ALIGN(4);
        *(.text)                   /* remaining code */
        *(.text.*)                 /* remaining code */
        *(.rodata)                 /* read-only data (constants) */
        *(.rodata*)
        *(.glue_7)
        *(.glue_7t)
    } > FLASH
    /* 
        .ARM.exidx is sorted, so has to go in its own output section.  
    */
    . = ALIGN(4);
    __exidx_start = .;
    .ARM.exidx :
    {
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } >FLASH
    __exidx_end = .;
    /* -- */    
    .data.align :
    {
        . = ALIGN(4);
        _etext = .;
        _sipdata = _etext; /* Used by the startup in order to initialize privileged variables */
    } >FLASH
    /* -- */
    .pdata.align :
    {
        . = ALIGN(4);
        . =  . + _Privileged_Data_Region_Size;
        _sidata = .; /* Used by the startup in order to initialize variables */
    } >FLASH
    /*
        * This is the Privileged data section. It is stored in RAM but the initial values
        * are held in flash and copied to RAM by the startup code
    */
    privileged_data :  AT ( _sipdata )  /* AT makes the LMA follow on in the binary image */
    {
        . = ALIGN(4);
        _bss = .;
        _spdata = . ;
        *(privileged_data)
        _epdata = . ;
    } > SRAM    
    /*
        * This is the initialized data section. It is stored in RAM but the initial values
        * are held in flash and copied to RAM by the startup code
    */
    .data_offset  :
    {
        . = ALIGN(4);
        . = . + _Privileged_Data_Region_Size;
    } > SRAM
    .data  : AT ( _sidata  )  /* AT makes the LMA follow on in the binary image */
    {
        _sdata = . ; /* Used by the startup in order to initialize the .data section */
        KEEP(*(vtable))
        KEEP( *(.data) )
        KEEP( *(.data.*) )
        . = ALIGN(4);
        _edata = . ; /* Used by the startup in order to initialize the .data section */
    } >SRAM
 
    /*
        * This is the uninitialized data section. Date here is stored in RAM and will be
        * set to zero by the startup code.
        */
    .bss :
    {
        . = ALIGN(4);
        _sbss = .; /* Used by the startup in order to initialize the .bss section */
         *(.bss)
         *(.bss.*)
         *(COMMON)
        . = ALIGN(4);
        _ebss = . ; /* Used by the startup in order to initialize the .bss section */
    } >SRAM
 
/*
 * This is the heap section
 * This is just to check that there is enough RAM left for the heap
 * It should generate an error if it's full.
 */
    ._sheap :
    {
        . = ALIGN(4);
      _heap_begin = . ;
      . = . + _Minimum_Heap_Size ;
      . = ALIGN(4);
      _heap_end = . ;
    } >SRAM
/*
 * This is the user stack section
 * This is just to check that there is enough RAM left for the User mode stack
 * It should generate an error if it's full.
 */
    ._usrstack :
    {
        . = ALIGN(4);
      _susrstack = . ;
      . = . + _Minimum_Stack_Size ;
      . = ALIGN(4);
      _eusrstack = . ;
    } >SRAM
 
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE( _heap = _heap_begin );
PROVIDE ( _eheap = _heap_end );
 
}

and here is the my new linker script file here to access the last page of the stm32f103 which is page 255. When I want to modify the page255. It does not allow me. Do you have suggestion that how can use the internal flash of the stm32 with freertos? I just need to use one page in the flash when freertos in the usage. Everything works if I do not use freertos

4 REPLIES 4
ebast
Associate II

and here is the edited linker script file. The different between two linker script file. Thank you from now

FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 1022K

FLASH_STORAGE (rwx) : ORIGIN = 0x08000000+1022K, LENGTH = 2K

/*************************************************
* linker script for ST32F103 & MPU  REV 1.02
************************************************/ 
 
GROUP(libgcc.a libc.a)
 
 
MEMORY
{
    FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 1022K
    FLASH_STORAGE (rwx)   : ORIGIN = 0x08000000+1022K, LENGTH = 2K
    SRAM (xrw)  : ORIGIN = 0x20000000, LENGTH =  96K
}
/* Higher address of the user mode stack */
_estack = ORIGIN(SRAM)+LENGTH(SRAM);
/*
 *There will be a link error if there is not this amount of RAM free at the end.
 */
_Minimum_Stack_Size = 1K;
_Minimum_Heap_Size = 1K;
 
/* Variables used by FreeRTOS-MPU. */
_Privileged_Functions_Region_Size = 16K;
_Privileged_Data_Region_Size = 512;
 
__FLASH_segment_start__ = ORIGIN( FLASH );
__FLASH_segment_end__ = __FLASH_segment_start__ + LENGTH( FLASH );
 
__privileged_functions_start__ = ORIGIN( FLASH );
__privileged_functions_end__ = __privileged_functions_start__ + _Privileged_Functions_Region_Size;
 
__SRAM_segment_start__ = ORIGIN( SRAM );
__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( SRAM );
 
__privileged_data_start__ = ORIGIN( SRAM );
__privileged_data_end__ = ORIGIN( SRAM ) + _Privileged_Data_Region_Size;    
 
ENTRY(Reset_Handler)
 
SECTIONS
{
    /* 
        Privileged section at the start of the flash. 
        Vectors must be first whatever. 
    */
    .isr_vectors :
    {
        . = ALIGN(4);
        _isr_vectors_offs = . - __FLASH_segment_start__;
        KEEP(*(.isr_vectors))            /* Startup code */
    } >FLASH
    privileged_functions :
    {
        . = ALIGN(4);
        *(privileged_functions)
    } > FLASH
 
    /* Non privileged code starts here. */
    .text_offset :
    {
        . = ALIGN(4);
        . =  . + _Privileged_Functions_Region_Size;
    } > FLASH
    .text :
    {
        . = ALIGN(4);
        *(.text)                   /* remaining code */
        *(.text.*)                 /* remaining code */
        *(.rodata)                 /* read-only data (constants) */
        *(.rodata*)
        *(.glue_7)
        *(.glue_7t)
    } > FLASH
    /* 
        .ARM.exidx is sorted, so has to go in its own output section.  
    */
    . = ALIGN(4);
    __exidx_start = .;
    .ARM.exidx :
    {
        *(.ARM.exidx* .gnu.linkonce.armexidx.*)
    } >FLASH
    __exidx_end = .;
    /* -- */    
    .data.align :
    {
        . = ALIGN(4);
        _etext = .;
        _sipdata = _etext; /* Used by the startup in order to initialize privileged variables */
    } >FLASH
    /* -- */
    .pdata.align :
    {
        . = ALIGN(4);
        . =  . + _Privileged_Data_Region_Size;
        _sidata = .; /* Used by the startup in order to initialize variables */
    } >FLASH
    /*
        * This is the Privileged data section. It is stored in RAM but the initial values
        * are held in flash and copied to RAM by the startup code
    */
    privileged_data :  AT ( _sipdata )  /* AT makes the LMA follow on in the binary image */
    {
        . = ALIGN(4);
        _bss = .;
        _spdata = . ;
        *(privileged_data)
        _epdata = . ;
    } > SRAM    
    /*
        * This is the initialized data section. It is stored in RAM but the initial values
        * are held in flash and copied to RAM by the startup code
    */
    .data_offset  :
    {
        . = ALIGN(4);
        . = . + _Privileged_Data_Region_Size;
    } > SRAM
    .data  : AT ( _sidata  )  /* AT makes the LMA follow on in the binary image */
    {
        _sdata = . ; /* Used by the startup in order to initialize the .data section */
        KEEP(*(vtable))
        KEEP( *(.data) )
        KEEP( *(.data.*) )
        . = ALIGN(4);
        _edata = . ; /* Used by the startup in order to initialize the .data section */
    } >SRAM
 
    /*
        * This is the uninitialized data section. Date here is stored in RAM and will be
        * set to zero by the startup code.
        */
    .bss :
    {
        . = ALIGN(4);
        _sbss = .; /* Used by the startup in order to initialize the .bss section */
         *(.bss)
         *(.bss.*)
         *(COMMON)
        . = ALIGN(4);
        _ebss = . ; /* Used by the startup in order to initialize the .bss section */
    } >SRAM
 
/*
 * This is the heap section
 * This is just to check that there is enough RAM left for the heap
 * It should generate an error if it's full.
 */
    ._sheap :
    {
        . = ALIGN(4);
      _heap_begin = . ;
      . = . + _Minimum_Heap_Size ;
      . = ALIGN(4);
      _heap_end = . ;
    } >SRAM
/*
 * This is the user stack section
 * This is just to check that there is enough RAM left for the User mode stack
 * It should generate an error if it's full.
 */
    ._usrstack :
    {
        . = ALIGN(4);
      _susrstack = . ;
      . = . + _Minimum_Stack_Size ;
      . = ALIGN(4);
      _eusrstack = . ;
    } >SRAM
 
PROVIDE ( end = _ebss );
PROVIDE ( _end = _ebss );
PROVIDE( _heap = _heap_begin );
PROVIDE ( _eheap = _heap_end );
 
}

Check the MPU settings to understand what/why areas are protected from access

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

I will look that. You mean I will touch the linker script right?

No, something in your code is enabling and configuring the MPU with ranges of valid/usable addresses, review *that* code, once you understand what that is doing, and the expectation that creates pivot to how that gets described/controlled in the script.

Seem to recall the MPU wants regions which are a power of two. Check the TRM for the core.

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