Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT




Loading

Linker Script for C++ on SAM7

Posted by sven-de on August 2, 2011
Hi,
along my journey into embedded OO I stumbled upon another problem: The linker script doesn't supply a .ctors-section and won't link global objects. I consulted these two ressources:
http://www.state-machine.com/arm/Building_bare-metal_ARM_with_GNU.pdf
http://gandalf.arubi.uni-kl.de/avr_projects/arm_projects/index_at91.html#at91_cpp
But at the end of the day I realised, that I'd really need some time to understand how linker-script, startup and low-level-init work within as well as together. So I just copied this between prog: and .data:
.ctors :
{
PROVIDE(__ctors_start__ = .);
KEEP(*(SORT(.ctors.*)))
KEEP(*(.ctors))
PROVIDE(__ctors_end__ = .);
} >flash

.dtors :
{
PROVIDE(__dtors_start__ = .);
KEEP(*(SORT(.dtors.*)))
KEEP(*(.dtors))
PROVIDE(__dtors_end__ = .);
} >flash

But got more errors. I've a weak understanding what the code in the two above ressources does, but have absolutely no clue about those (sparsely commented) files supplied with FreeRTOS. So I tend to swap atmel-rom.ld, boot.s und syscalls.c with those from the second ressource. Is that possible, or do they currently contain anything specific to FreeRTOS I have to take care of? Or are there even more files involved, such as Cstartup_SAM7.c and Cstartup.s79 in SRCAtmel?

Is there any other way to achieve this without having to go deeply into GNU ld, and start-up procedures?

RE: Linker Script for C++ on SAM7

Posted by Richard on August 2, 2011
The linker script has nothing FreeRTOS specific as far as I know.

The start up file must set up a stack for both Supervisor and IRQ modes, as a minimum (FIQ too if you use that), and install vPortYieldProcessor() as the SWI interrupt handler.

There has been lots of discussion here on the topic of C++ in the past, and some C++ projects posted to the FreeRTOS Interactive site too. http://interactive.freertos.org

Regards.

RE: Linker Script for C++ on SAM7

Posted by sven-de on August 2, 2011
Richard, your response time makes me once again forget, that you aren't earning a single dime with this support (except those few bucks I paid for the eBook). Thanks!

I suppose with "start up file" you mean boot.s which apparently sets vPortYieldProcessor() as SoftwareInterrupt. But there's another file ./SrcAtmel/Cstartup.s97 which does the same. May I assume, since it's not linked, called or compiled anywhere, that this one is obsolete?

I was a bit confused to find LowLevelInit()-funtion in ./SrcAtmel/Cstartup_SAM7.c. All documentation I read until now treats low-level-init and startup-code as two different things - perhaps the naming could be changed with the next update of this demo.

Am I right, that syscalls.c has nothing to do with this? In 2009 you said that FreeRTOS doesn't even use of any of it's functions...

When this is my lucky day Richard Damon will soon come around the corner and post a platinum grade linker-script for C++ ;-)

RE: Linker Script for C++ on SAM7

Posted by Richard on August 2, 2011
Which directory are you getting these files from? Just from the file name, I would say that Cstartup.s97 is probably an (old) IAR V.4x source file, and therefore should not be built with GCC. It is a long time since I did any SAM7 stuff, but I think the demos in the FreeRTOS download are for IAR, unless I did an Eclipse version at some time too.

Regards.

RE: Linker Script for C++ on SAM7

Posted by sven-de on August 2, 2011
Yes, I'm using the GCC/Eclipse demo which has SrcAtmel/ right in RTOSDemo/. And your guess is probably right since the head-comment in Cstartup.s97 mentions IAR.

RE: Linker Script for C++ on SAM7

Posted by Richard on August 2, 2011
Yes - ignore the .s79 file then - it is just part of the standard files received from Atmel, but not used in that particular demo.

Regards.

RE: Linker Script for C++ on SAM7

Posted by sven-de on August 8, 2011
Hi, currently I'm swopping the demo's linker-script and startup-code with the aforementioned code by Martin Thomas (second link). While doing this I stumbled upon this section in the original linker-script of the SAM7 GCC-Demo:
prog : 
{
*(.text)
*(.rodata)
*(.rodata*)
*(.glue_7)
*(.glue_7t)
} >flash

It's the prog that puzzles me. From other linkerscripts I'd expect an .text (note the dot) in it's location instead. Since I couldn't find anything about this on the net, I assume it's some sort of custom section (which doesn't matter as long it's places in the right location). But is there any reason for not using the common .text here?

(sorry for questions this far from the actual rtos)

RE: Linker Script for C++ on SAM7

Posted by Johan Christiansen on August 9, 2011
Here's a script that works for C++.

OUTPUT_FORMAT(elf32-littlearm)
OUTPUT_ARCH(arm)
ENTRY(_start)

MEMORY
{
sram : ORIGIN = 0x00000000,LENGTH = 0x1000
rom : ORIGIN = 0x40000000,LENGTH = 0x400000
flash : ORIGIN = 0x48000000,LENGTH = 0x400000
ram : ORIGIN = 0x50100000,LENGTH = 0x100000
}

SECTIONS
{

. = 0;
_sfixed = .;

.text :
{
KEEP(*(.init))
. = 0x100;
KEEP(*(.jump))
*(.text)
*(.text.*)
*(.rodata*)
. = ALIGN(8);
PROVIDE (__init_array_start = .);
KEEP(*(.init_array))
PROVIDE (__init_array_end = .);
} >rom

.ARM.extab (NOLOAD) : {
*(.ARM.extab* .gnu.linkonce.armextab.*)
} >rom

__exidx_start = .;
.ARM.exidx (NOLOAD) : {
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > rom
__exidx_end = .;
_efixed = .;

.data : {
_data_lma = LOADADDR(.data);
_data_start = .;
*(.ramfunc)
*(.data)
*(.data.*)
_data_end = .;
} >ram AT> rom

.sram 0x40 : {
_sram_lma = LOADADDR(.sram);
_sram_start = .;
*(.sram.text)
*(.sram.data)
_sram_end = .;
} >sram AT> rom

.bss (NOLOAD) : {
_szero = .;
*(.bss)
*(.bss.*)
. = ALIGN(8);
_ezero = .;
} >ram

__heap_start__ = .;
__heap_end__ = 0x50200000 - 8 - 40000;

.ram_persist __heap_end__ (NOLOAD) : {
*(.ram_persist)
} > ram

_sstack = 0x50200000 - 8;

}
[/code

Then before starting a C++ function, or even before main do this:


/* C++ static constructors */
extern void (*__init_array_start []) (void) __attribute__((weak));
extern void (*__init_array_end []) (void) __attribute__((weak));
int count = __init_array_end - __init_array_start, i;
for (i = 0; i < count; i++)
__init_array_start();

RE: Linker Script for C++ on SAM7

Posted by sven-de on September 5, 2011
Thank you all for your kind help. I finally took the abovementioned files from Martin Thomas an merged them mit the demo from FreeRTOS.org. Acutally I completely replaced the linker script, kept CstartupSAM7.c and just joined the two startup-files boot.s and Cstartup.S which resulted in the code below. It's working.
/*------------------------------------------------------------------------------
//*- ATMEL Microcontroller Software Support - ROUSSET -
//*-----------------------------------------------------------------------------
//* The software is delivered "AS IS" without warranty or condition of any
//* kind, either express, implied or statutory. This includes without
//* limitation any warranty or condition with respect to merchantability or
//* fitness for any particular purpose, or against the infringements of
//* intellectual property rights of others.
//*-----------------------------------------------------------------------------
//*- File source : Cstartup.s
//*- Object : Generic CStartup for KEIL and GCC
//*- Compilation flag : None
//*
//*- 1.0 18/Oct/04 JPP : Creation
//*- 1.1 21/Feb/05 JPP : Set Interrupt
//*- 1.1 01/Apr/05 JPP : save SPSR
//*
//* This file (along with the linker script and Cstartup_SAM7.c) was taken from
//* Martin Thomas due to it's support for C++. Originally it also allowed to
//* place parts of code as well as the vectors in ROM. This functionality was
//* removed by Sven Gruener in Aug/2011 while adapting it to FreeRTOS
//*---------------------------------------------------------------------------*/

.print "ROM-Version: Vectors at start of Code, just variables in RAM"

/*-----------------------------------------------------------------------------
//*- Exception vectors
//*--------------------
//*- These vectors can be read at address 0 or at RAM address
//*- They ABSOLUTELY requires to be in relative addresssing mode in order to
//*- guarantee a valid jump. For the moment, all are just looping.
//*- If an exception occurs before remap, this would result in an infinite loop.
//*- To ensure if a exeption occurs before start application to infinite loop.
//*--------------------------------------------------------------------------*/

.print "Vectors in section .vectorg -> .text"
.section .vectorg, "ax"

LDR PC,Reset_Addr/* 0x00 Reset handler */
LDR PC,Undef_Addr/* 0x04 Undefined Instruction */
LDR PC,SWI_Addr/* 0x08 Software Interrupt */
LDR PC,PAbt_Addr/* 0x0C Prefetch Abort */
LDR PC,DAbt_Addr/* 0x10 Data Abort */
NOP /* 0x14 reserved */
LDR PC,[PC,#-0xF20]/* 0x18 IRQ */
LDRPC,FIQ_Addr/* 0x1c FIQ */

Reset_Addr:.wordInitReset
Undef_Addr:.wordUndef_Handler
SWI_Addr:.wordvPortYieldProcessor /* in portISR.c */
PAbt_Addr:.wordPAbt_Handler
DAbt_Addr:.wordDAbt_Handler
/*IRQ_Addr:.wordIRQ_Handler_Entry*/
FIQ_Addr:.wordFIQ_Handler

Undef_Handler:BUndef_Handler
PAbt_Handler:BPAbt_Handler
DAbt_Handler:BDAbt_Handler
FIQ_Handler:BFIQ_Handler


/*--- End of exception vectors ----------------------------------------------*/

.arm
.section .init, "ax"
.global _startup
.func _startup

_startup:
reset:

.RAM_TOP:
.word__TOP_STACK

InitReset:

/*-----------------------------------------------------------------------------
/*- Low level Init (PMC, AIC, ? ....) by C function AT91F_LowLevelInit
/*---------------------------------------------------------------------------*/
/*- minumum C initialization, call AT91F_LowLevelInit( void) */
.extern AT91F_LowLevelInit

ldr sp, .RAM_TOP/* temporary stack in internal RAM (**) */

/*--Call Low level init function in ABSOLUTE through the Interworking*/
ldrr0,=AT91F_LowLevelInit
movlr, pc
bxr0

/*------------------------------------------------------------------------------
//*- Stack size and location Definition
//*------------------------------------
//*- Interrupt Stack requires 2 words x 8 priority level x 4 bytes when using
//*- the vectoring. This assume that the IRQ management.
//*- The Interrupt Stack must be adjusted depending on the interrupt handlers.
//*- The System stack size is not defined and is limited by the free internal
//*- SRAM.
//*---------------------------------------------------------------------------*/

/* Stack Sizes */
.equ UND_STACK_SIZE, 0x00000004
.equ ABT_STACK_SIZE, 0x00000004
.equ FIQ_STACK_SIZE, 0x00000004
.equ IRQ_STACK_SIZE, 0X00000400
.equ SVC_STACK_SIZE, 0x00000400

/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs */
.equ MODE_USR, 0x10 /* User Mode */
.equ MODE_FIQ, 0x11 /* FIQ Mode */
.equ MODE_IRQ, 0x12 /* IRQ Mode */
.equ MODE_SVC, 0x13 /* Supervisor Mode */
.equ MODE_ABT, 0x17 /* Abort Mode */
.equ MODE_UND, 0x1B /* Undefined Mode */
.equ MODE_SYS, 0x1F /* System Mode */

.equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */
.equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */

/*------------------------------------------------------------------------------
//*- Setup the stack for each mode
//*-------------------------------*/
mov r0, sp /* see (**) */

msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction Mode */
mov sp, r0
sub r0, r0, #UND_STACK_SIZE
msr CPSR_c, #MODE_ABT|I_BIT|F_BIT /* Abort Mode */
mov sp, r0
sub r0, r0, #ABT_STACK_SIZE
msr CPSR_c, #MODE_FIQ|I_BIT|F_BIT /* FIQ Mode */
mov sp, r0
sub r0, r0, #FIQ_STACK_SIZE
msr CPSR_c, #MODE_IRQ|I_BIT|F_BIT /* IRQ Mode */
mov sp, r0
sub r0, r0, #IRQ_STACK_SIZE
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT /* Supervisor Mode */
mov sp, r0
sub r0, r0, #SVC_STACK_SIZE
msr CPSR_c, #MODE_SYS|I_BIT|F_BIT /* System Mode */
mov sp, r0

/* We want to start in supervisor mode. Operation will switch to system
mode when the first task starts. */
msr CPSR_c, #MODE_SVC|I_BIT|F_BIT

mov sp, r0/* Init stack Sup */

/*------------------------------------------------------------------------------
//*- Relocation of .data section (ROM->RAM)
//*---------------------------------------*/
/* Relocate .data section (Copy from ROM to RAM)
This will also copy the .vectmapped and .fastrun */
LDR R1, =_etext
LDR R2, =_data
LDR R3, =_edata
LoopRel: CMP R2, R3
LDRLO R0, [R1], #4
STRLO R0, [R2], #4
BLO LoopRel

/*------------------------------------------------------------------------------
//*- Clear .bss section (Zero init)
//*-------------------------------*/
MOV R0, #0
LDR R1, =__bss_start__
LDR R2, =__bss_end__
LoopZI: CMP R1, R2
STRLO R0, [R1], #4
BLO LoopZI

/*------------------------------------------------------------------------------
//*- call C++ constructors of global objects
//*----------------------------------------*/
LDR r0, =__ctors_start__
LDR r1, =__ctors_end__
ctor_loop:
CMP r0, r1
BEQ ctor_end
LDR r2, [r0], #4
STMFD sp!, {r0-r1}
MOV lr, pc
/*MOV pc, r2 */
BX r2 /* mthomas 8/2006 */
LDMFD sp!, {r0-r1}
B ctor_loop
ctor_end:

/*------------------------------------------------------------------------------
//*- call main()
//*------------*/
ldrlr,=exit
ldrr0,=main
bxr0

.size _startup, . - _startup
.endfunc

/* "exit" dummy added by mthomas to avoid sbrk write read etc. needed
by the newlib default "exit" */
.global exit
.func exit
exit:
b .
.size exit, . - exit
.endfunc

/*----------------------------------------------------------------------------*/
.end


[ Back to the top ]    [ About FreeRTOS ]    [ Sitemap ]    [ ]




Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS