Linker Problems STM32 + FreeRTOS MPU

der-da wrote on Thursday, September 15, 2011:

I am using the STM3210E_eval (the new Rev. with MPU) and the Sourcery GCC compiler. (FreeRTOS 7.0.0 and StdPeriph Lib 3.5)

Thanks to the examples on stf12.org setting up FreeRtos without MPU was easy and worked great. However I am now trying to get the MPU-Port running.
I took the code from the “CORTEX_MPU_LPC1768_GCC_RedSuite” example and adjusted FreeRTOS.h, the adresses in the main code and the LCD routines for the STM32F103. Compiles just fine.

The problem is the Linker Script. “Placeholders” like

	. = ORIGIN( SRAM ) + _Privileged_Data_Region_Size;

will cause the code to somehow bloat

c:/programme/codesourcery/sourcery g++ lite/bin/../lib/gcc/arm-none-eabi/4.5.2/../../../../arm-none-eabi/bin/ld.exe: FreeRtos_MPU-LPC_Example.elf section `.text' will not fit in region `FLASH'
c:/programme/codesourcery/sourcery g++ lite/bin/../lib/gcc/arm-none-eabi/4.5.2/../../../../arm-none-eabi/bin/ld.exe: region `FLASH' overflowed by 133201600 bytes

If you set the flash to 1000M look at the listfile you will see a gap of the size of 0x8004000. No code in between.

Does anyone have a working Linker Script for the STM32 family and the MPU-port?
Or an explanation for the behavior?

Regards,

Torben

edwards3 wrote on Thursday, September 15, 2011:

Please could you post the whole likner script.

der-da wrote on Saturday, September 17, 2011:

I accidentally posted the placeholder thing for the Ram Region.

Here is the whole linker:

/* Entry Point */
ENTRY(Reset_Handler)
/* Highest address of the user mode stack */
_estack = 0x20018000;    /* end of 96K RAM */
/* Generate a link error if heap and stack don't fit into RAM */
_Min_Heap_Size = 0;      /* required amount of heap  */
_Min_Stack_Size = 0x200; /* required amount of stack */
/* Specify the memory areas */
MEMORY
{
  
  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 1M
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 96K
  MEMORY_B1 (rx)  : ORIGIN = 0x60000000, LENGTH = 0K
}
/* Variables used by FreeRTOS-MPU. */
_Privileged_Functions_Region_Size = 16K;
_Privileged_Data_Region_Size = 256;
__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( RAM );
__SRAM_segment_end__ = __SRAM_segment_start__ + LENGTH( RAM );
__privileged_data_start__ = ORIGIN( RAM );
__privileged_data_end__ = ORIGIN( RAM ) + _Privileged_Data_Region_Size;
/* Define output sections */
SECTIONS
{
  /* The startup code goes first into FLASH, then the priv. functions */
	privileged_functions :
	{
		KEEP(*(.isr_vector))
		*(privileged_functions)
	} > FLASH
  /* The program code and other data goes into FLASH */
  .text :
  {
     
    /* Non privileged code kept out of the first 16K or flash. -- Doesn't Work as expected */
    . = __privileged_functions_start__ + _Privileged_Functions_Region_Size; 
     . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */
    KEEP (*(.init))
    KEEP (*(.fini))
    . = ALIGN(4);
    _etext = .;        /* define a global symbols at end of code */
  } >FLASH
   .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
    .ARM : {
    __exidx_start = .;
      *(.ARM.exidx*)
      __exidx_end = .;
    } >FLASH
  .ARM.attributes : { *(.ARM.attributes) } > 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 (*(.fini_array*))
    KEEP (*(SORT(.fini_array.*)))
    PROVIDE_HIDDEN (__fini_array_end = .);
  } >FLASH
  /* used by the startup to initialize data */
  _sidata = .;
	/* zero initialized data */		
	privileged_data :
	{
		_bss = .;
		*(privileged_data)
		/* Non kernel data is kept out of the first 256 bytes of SRAM. */
	} > RAM	
	. = ORIGIN( RAM ) + _Privileged_Data_Region_Size;
  /* 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
  
    /* Initialized data sections goes into RAM, load LMA copy after code */
  .data : AT ( _sidata )
  {
    . = 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
  PROVIDE ( end = _ebss );
  PROVIDE ( _end = _ebss );
  /* User_heap_stack section, used to check that there is enough RAM left */
  ._user_heap_stack :
  {
    . = ALIGN(4);
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(4);
  } >RAM
  /* MEMORY_bank1 section, code must be located here explicitly            */
  /* Example: extern int foo(void) __attribute__ ((section (".mb1text"))); */
  .memory_b1_text :
  {
    *(.mb1text)        /* .mb1text sections (code) */
    *(.mb1text*)       /* .mb1text* sections (code)  */
    *(.mb1rodata)      /* read-only data (constants) */
    *(.mb1rodata*)
  } >MEMORY_B1
  /* Remove information from the standard libraries */
  /DISCARD/ :
  {
    libc.a ( * )
    libm.a ( * )
    libgcc.a ( * )
  }
}

Regards,

Torben

der-da wrote on Thursday, October 06, 2011:

BUMP

Does no one have an idea?

Regards,
Torben

anonymous wrote on Tuesday, March 27, 2012:

I faced exactly the same strange problem when adapted STM32 CMSIS linker script from this one. Solved by moving problematic line out of .text {} block an placing it just before block. But original script in example project works fine howewer. Looks like bug in linker.

anonymous wrote on Wednesday, March 28, 2012:

Oops. Not solved, just seemed as solved. Placeholder moved out from .text block actually does nothing ! It doesn’t rewinds location. I wasted two days trying to get FreeRTOS MPU working until I found reason. But now I don’t know how to fix it !
I expect that codeline

. = __privileged_functions_start__ + _Privileged_Functions_Region_Size;

just rewinds current location to specified value and subsequent .text section will start being placed from this point. But it results in such linker map:

...
.text		0x08001dc8	0x8005780
		0x08004000	. = (__privileged_functions_start__ + _Privileged_Functions_Region_Size)
 *fill*		0x08001dc8	0x8004000	00
 *(.text*)
 .text		0x10005dc8	...
 ...

It recognizes resulted address as size and makes zero-filled region with this size ! It is crazy ???
(Official CORTEX_MPU_LPC1768_GCC_RedSuite luckily works only because flash address origin starts with just small 0x0. It results in small memory waste and little misalignment between actual data placement and defined regions.)

I’m using Yagarto ARM Toolchain 4.6.0

Does no one have an idea?

anonymous wrote on Wednesday, March 28, 2012:

Found solution:

. += __privileged_functions_start__ + _Privileged_Functions_Region_Size - .;

Remaining placeholders in script must be converted to such manner.

anonymous wrote on Wednesday, March 28, 2012:

Oops. No. __privileged_functions_start__ must be replaced with ORIGIN( FLASH ). I’m confused finally.

anonymous wrote on Sunday, April 01, 2012:

Posted a bug report