Author Topic: Linker Scripts  (Read 4845 times)

0 Members and 1 Guest are viewing this topic.

Offline blewisjrTopic starter

  • Frequent Contributor
  • **
  • Posts: 301
Linker Scripts
« on: June 04, 2014, 02:08:41 pm »
Sorry if this is a dumb or simple question.

I am working on putting together a template for my ARM learnings and I am trying to better learn various tools outside of the IDE environment.  I do not want to hear preaching about using IDE's etc...

I am comfortable with the make files and compilers and such all that is done my issue falls in the realm of the linker scripts.  Does anyone know of where I can learn more about creating linker scripts?  I want my linker script to really be the bare minimum for ease of learning and understanding.  Normally google would be my friend but google is failing me on STM32 linker searching.  Every linker script I find is overly complex I just want to define memory regions and preserve a few sections.
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: Linker Scripts
« Reply #1 on: June 04, 2014, 02:29:25 pm »
What toolchain are you using? For the GNU toolchain, see the GNU ld manual.

Offline blewisjrTopic starter

  • Frequent Contributor
  • **
  • Posts: 301
Re: Linker Scripts
« Reply #2 on: June 04, 2014, 03:29:27 pm »
Using GCC so yes that is the right documentation.  Very clear documentation and from this I can easily construct a linker script as long as I can figure out what code and data sections are necessary.  I have no experience with gcc assembler and the sections the arm chips use.
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26907
  • Country: nl
    • NCT Developments
Re: Linker Scripts
« Reply #3 on: June 04, 2014, 05:21:19 pm »
You can use objdump to see which sections are in the object (elf) file. objdump is usually prepended by the name of the toolchain.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline blewisjrTopic starter

  • Frequent Contributor
  • **
  • Posts: 301
Re: Linker Scripts
« Reply #4 on: June 04, 2014, 07:51:10 pm »
Ok I think I got everything I need in the linker script through the use of object dump etc...  The only question left is there a specific place the stack and heap should be defined.  I have came across multiple different methods of doing the stack and heap on the internet is the a best suggested way to do it?
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: Linker Scripts
« Reply #5 on: June 04, 2014, 08:34:37 pm »
If you place your stack at the top of RAM, any overflow will silently write over your data. If you instead place it at the start of RAM, it will overflow into unmapped memory and trigger an exception.

Offline blewisjrTopic starter

  • Frequent Contributor
  • **
  • Posts: 301
Re: Linker Scripts
« Reply #6 on: June 04, 2014, 09:56:47 pm »
Ok thanks for the information.  I think I placed the stack at the start of ram to get errors on a stack overflow which I personally feel is rather important.  I might have gotten this backwards on which label should be what might need to swap _stack_end and _stack_start after looking at it again for the desired effect.  Then I placed the heap after the .bss section.  Here is the finished linker script and any input you can give would be much appreciated.  I am not exactly sure the difference between say .<section> and .<section>* in my head I make the assumption that the wildcard after the section name is for those special subsection cases that pop up from time to time.

I also am not sure about the glue_7 and glue_7t sections.  I saw them quite a bit in various examples and they are for swapping between arm and thumb code etc...  As far as I know the CortexM chips only support thumb mode so they can probably be taken out.  I am also sure I can get by without the heap as well especially at such a small size.

Code: [Select]
/* Basic Linker Script for STM32F303x Arm chip */

/* Main Entry Point */

ENTRY(Reset_Handler)

/* Memory Definitions */

MEMORY
{
FLASH (rx): ORIGIN = 0x08000000, LENGTH = 256K
RAM (rwx): ORIGIN = 0x20000000, LENGTH = 40K
}

/* Define stack and heap size */
stack_size = 1024;
heap_size = 256;

/* Define beginning and end of stack */
_stack_start = ORIGIN(RAM)+LENGTH(RAM);
_stack_end = _stack_start - stack_size;

/* Section Definitions */

SECTIONS
{
/* ARM Cortex startup code is in .isr_vector which goes in flash */
.isr_vector
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* startup is here */
. = ALIGN(4);
} > FLASH

/* Program code is stored in .text */
.text
{
. = ALIGN(4);
*(.text)      /* .text sections program code */
*(.text*)     /* .text* sections program code */
*(.rodata)    /* .rodata sections read only like constants */
*(.rodata*)   /* .rodata* sections read only like constants*/
*(.glue_7)    /* arm-thumb glue maybe needed */
*(.glue_7t)   /* thumb-arm glue maybe needed */

/* Must Keep sections not sure why all examples keep */
KEEP (*(.init))
KEEP (*(.fini))

. = ALIGN(4);
_etext = .;

/* data section start point */
_sidata = _etext;
} > FLASH

/* Initialized data is stored in .data */
.data: AT(_sidata)
{
. = ALIGN(4);
_sdata = .;

*(.data)    /* .data sections initialized data */
*(.data*)   /* .data* sections initialized data */

. = ALIGN(4);
_edata = .;
} > RAM

/* Uninitialized data section */
.bss:
{
. = ALIGN(4);
_sbss = .;

*(.bss)    /* .bss sections uninitialized data */
*(.bss*)   /* .bss* sections uninitialized data */
*(COMMON)  /* common symobols in object files  */

. = ALIGN(4);
_ebss = .;
} > RAM

/* Heap section */
.heap:
{
. = ALIGN(4);
_heap_start = .;
. = . + heap_size;
_heap_end = .;
} > RAM

/* Remove standard library information */
/DISCARD/:
{
libc.a (*)
libm.a (*)
libgcc.a (*)
}
}
« Last Edit: June 04, 2014, 10:06:38 pm by blewisjr »
 

Offline nctnico

  • Super Contributor
  • ***
  • Posts: 26907
  • Country: nl
    • NCT Developments
Re: Linker Scripts
« Reply #7 on: June 04, 2014, 11:39:39 pm »
It sounds about right. Make sure to have ld generate a map file and check whether everything is in the right place. A good thing to do is to have the startup code clear the stack as well at startup.
There are small lies, big lies and then there is what is on the screen of your oscilloscope.
 

Offline andersm

  • Super Contributor
  • ***
  • Posts: 1198
  • Country: fi
Re: Linker Scripts
« Reply #8 on: June 05, 2014, 05:20:15 am »
That definition will make the _stack_start symbol point to the very end of RAM. It's simplest to add a section for the stack, like you did for the heap.
Code: [Select]
.stack ORIGIN(RAM):
{
    _stack_end = .;
    ASSERT(stack_size % 8 == 0, "Stack size must be multiple of 8 bytes long")
    . = . + stack_size;
    __stack_start = .;
} > RAM
The assert just ensures the stack pointer is DWORD-aligned, as mandated by the ABI.

Offline blewisjrTopic starter

  • Frequent Contributor
  • **
  • Posts: 301
Re: Linker Scripts
« Reply #9 on: June 05, 2014, 11:58:31 am »
Ah ok that makes sense here are my modifications to move the stack.  I left out the assert simply because 1024 falls within the abi spec according to your checks.  I am not quite sure if I did it right but I placed the section for the stack before .data and added _sidata at the top of the stack hopefully everything falls into place like this.

Code: [Select]
/* Basic Linker Script for STM32F303x Arm chip */

/* Main Entry Point */

ENTRY(Reset_Handler)

/* Memory Definitions */

MEMORY
{
FLASH (rx): ORIGIN = 0x08000000, LENGTH = 256K
RAM (rwx): ORIGIN = 0x20000000, LENGTH = 40K
}

/* Define stack and heap size */
stack_size = 1024;
heap_size = 256;

/* Section Definitions */

SECTIONS
{
/* ARM Cortex startup code is in .isr_vector which goes in flash */
.isr_vector
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* startup is here */
. = ALIGN(4);
} > FLASH

/* Program code is stored in .text */
.text
{
. = ALIGN(4);
*(.text)      /* .text sections program code */
*(.text*)     /* .text* sections program code */
*(.rodata)    /* .rodata sections read only like constants */
*(.rodata*)   /* .rodata* sections read only like constants*/
*(.glue_7)    /* arm-thumb glue maybe needed */
*(.glue_7t)   /* thumb-arm glue maybe needed */

/* Must Keep sections not sure why all examples keep */
KEEP (*(.init))
KEEP (*(.fini))

. = ALIGN(4);
_etext = .;
} > FLASH

/* Stack section definition */
.stack ORIGIN(RAM):
{
_stack_end = .;
. = . + stack_size;
_stack_start = .;
_sidata = .;
} > RAM

/* Initialized data is stored in .data */
.data: AT(_sidata)
{
. = ALIGN(4);
_sdata = .;

*(.data)    /* .data sections initialized data */
*(.data*)   /* .data* sections initialized data */

. = ALIGN(4);
_edata = .;
} > RAM

/* Uninitialized data section */
.bss:
{
. = ALIGN(4);
_sbss = .;

*(.bss)    /* .bss sections uninitialized data */
*(.bss*)   /* .bss* sections uninitialized data */
*(COMMON)  /* common symobols in object files  */

. = ALIGN(4);
_ebss = .;
} > RAM

/* Heap section */
.heap:
{
. = ALIGN(4);
_heap_start = .;
. = . + heap_size;
_heap_end = .;
} > RAM

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


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf