EmbDev.net

Forum: ARM programming with GCC/GNU tools Linker problem for Function in ram


von Jacopo C. (jacopo)


Rate this post
useful
not useful
I'm using an AT91SAM7SE256 and I'm trying to write in flash using the
ramfunc attribute for functions like:
__ramfunc int AT91F_Flash_Write( u32 Flash_Address ,int size ,u32 *
buff)

I use the following definition for ramfunc attribute
#define _ramfunc __attribute_ ((long_call, section (".fastrun")))

The compiler makes no errors.
But when i try to link the following error appears:
c:/programmi/yagarto/bin/../lib/gcc/arm-elf/4.2.1/../../../../arm-elf/bi 
n/ld.exe:
section .fastrun [0020fbb0 -> 00210073] overlaps section .data [0020fbb0
-> 002104c3]

I use the following makefile:

ifndef CROSS_COMPILE
CROSS_COMPILE=arm-elf-
endif

TOOLCHAIN=gcc

OUTFILE_FLASH=OH_GW_flash

TARGET=AT91SAM7SE256

INCL=./include
#INCL=./Includes
# Comment the line below for debug mode
#OPTIM=-Os

ifeq ($(TOOLCHAIN), gcc)

AS=$(CROSS_COMPILE)gcc
CC=$(CROSS_COMPILE)gcc
LD=$(CROSS_COMPILE)gcc
NM= $(CROSS_COMPILE)nm
SIZE=$(CROSS_COMPILE)size
OBJCOPY=$(CROSS_COMPILE)objcopy
OBJDUMP=$(CROSS_COMPILE)objdump
CCFLAGS=-g -mcpu=arm7tdmi $(OPTIM) -Wall -I$(INCL) -D$(TARGET) -DGATEWAY
ASFLAGS=-D__ASSEMBLY__ -D$(TARGET) -g -mcpu=arm7tdmi -c $(OPTIM) -Wall
-I$(INCL)

# Linker flags.
#  -Wl,...:     tell GCC to pass this to linker.
#    -Map:      create map file
#    --cref:    add cross reference to map file
#  -lc      :   tells the linker to tie in newlib
#  -lgcc   :   tells the linker to tie in newlib
LDFLAGS+=-nostartfiles -Wl,--cref,-Map map.txt
LDFLAGS+=-lc -lgcc
LDFLAGS+=-T elf32-littlearm.lds
OBJS=cstartup.o

endif


OBJS+= main.o lib_SAM7SE.o  flash.o

rebuild: clean all

all: flash


flash: $(OBJS)
  $(LD) $(LDFLAGS) -Ttext 0x100000 -Tdata 0x200000 -n -o
$(OUTFILE_FLASH).elf $(OBJS)
  $(OBJCOPY) --strip-debug --strip-unneeded $(OUTFILE_FLASH).elf -O
binary $(OUTFILE_FLASH).bin



Do I have to modify the .section part in cstartup.s file or I have to
modify the makefile?

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
> flash: $(OBJS)
>   $(LD) $(LDFLAGS) -Ttext 0x100000 -Tdata 0x200000 -n -o
> $(OUTFILE_FLASH).elf $(OBJS)

It seems that you are using the default linker-script of the toolchain
(shown with arm-elf-ld --verbose) which does not include entries for the
extra section. Either use your own linker-script or try to modify the
define to
#define _ramfunc __attribute_ ((long_call, section (".data")))
so the functions will be placed in the "well known" .data-section

It is possible to add a option for the start-address to the liker-call
but it's a little difficult to keep this start-address up-to-date.

> Do I have to modify the .section part in cstartup.s file or I have to
> modify the makefile?

The linker assigns addresses so you have to modify the linker-script
first if a special section like .fastrun should be used.

von Jacopo C. (jacopo)


Rate this post
useful
not useful
Martin Thomas wrote:
>> flash: $(OBJS)
>>   $(LD) $(LDFLAGS) -Ttext 0x100000 -Tdata 0x200000 -n -o
>> $(OUTFILE_FLASH).elf $(OBJS)
>
> It seems that you are using the default linker-script of the toolchain
> (shown with arm-elf-ld --verbose) which does not include entries for the
> extra section. Either use your own linker-script or try to modify the
> define to
> #define _ramfunc __attribute_ ((long_call, section (".data")))
> so the functions will be placed in the "well known" .data-section
>
> It is possible to add a option for the start-address to the liker-call
> but it's a little difficult to keep this start-address up-to-date.
>
>> Do I have to modify the .section part in cstartup.s file or I have to
>> modify the makefile?
>
> The linker assigns addresses so you have to modify the linker-script
> first if a special section like .fastrun should be used.

I've tried to modify the define try to modify the define to:
#define _ramfunc __attribute_ ((long_call, section (".data")))
so the functions should be placed in the "well known" .data-section, but
appears the following warning:
Severity and Description
"C:\...\Temp/ccWqjaaa.s ignoring changed section attributes for .data"
and it doesn't work. Can you explain me why?

Thankyou.

von Jim K. (ancaritha)


Rate this post
useful
not useful
Martin Thomas wrote:

> The linker assigns addresses so you have to modify the linker-script
> first if a special section like .fastrun should be used.


Modify linker script like so:


 /* .data section which is used for initialized data */
  .data : AT (_etext)
  {
    _data = .;

    *(.data)
  *(.data.*)
  *(.gnu.linkonce.d*)
  SORT(CONSTRUCTORS) /* mt 4/2005 */
  . = ALIGN(4);
  *(.fastrun)         /* "RAM-Functions" */ /* added by mthomas */
  } > RAM

von Jacopo C. (jacopo)


Rate this post
useful
not useful
Jim Kaz wrote:
> Martin Thomas wrote:
>
>> The linker assigns addresses so you have to modify the linker-script
>> first if a special section like .fastrun should be used.
>
>
> Modify linker script like so:
>
>
>  /* .data section which is used for initialized data */
>   .data : AT (_etext)
>   {
>     _data = .;
>
>     *(.data)
>   *(.data.*)
>   *(.gnu.linkonce.d*)
>   SORT(CONSTRUCTORS) /* mt 4/2005 */
>   . = ALIGN(4);
>   *(.fastrun)         /* "RAM-Functions" */ /* added by mthomas */
>   } > RAM


Thank you for your help.
First I have to change the first line of your answer in
.section .data : AT (_etext)

but after that the compiler doesn't recognize hte symbol { or * and
tells me:

bad instruction `sort(CONSTRUCTORS)'  cstartup.S  line 250
junk at end of line, first unrecognized character is `('cstartup.S  line
251
junk at end of line, first unrecognized character is `{'cstartup.S  line
244
junk at end of line, first unrecognized character is `}'cstartup.S  line
253
junk at end of line, first unrecognized character is `*'cstartup.S  line
247
junk at end of line, first unrecognized character is `*'cstartup.S  line
248
junk at end of line, first unrecognized character is `*'cstartup.S  line
249
junk at end of line, first unrecognized character is `*'cstartup.S  line
252

do you know why?

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Please show your complete linker-script

von Jacopo C. (jacopo)


Rate this post
useful
not useful
Martin Thomas wrote:
> Please show your complete linker-script

Here it is (is the Cstartup.S file):

#define TOP_OF_MEMORY    (AT91C_ISRAM + AT91C_ISRAM_SIZE)
#define ABT_STACK_SIZE   8*3*4
#define IRQ_STACK_SIZE   8*3*4

#define ARM_MODE_ABT     0x17
#define ARM_MODE_FIQ     0x11
#define ARM_MODE_IRQ     0x12
#define ARM_MODE_SVC     0x13

#define I_BIT            0x80
#define F_BIT            0x40


/* Application startup entry point */
        .globl reset_handler
        .align 4

.section .vectors
.arm


/* Exception vectors (should be a branch to be detected as a valid code
by the rom */
_exception_vectors:
reset_vector:
        ldr      pc, =reset_handler
undef_vector:
        b        undef_vector    /* Undefined Instruction */
swi_vector:
        b        swi_vector      /* Software Interrupt */
pabt_vector:
        ldr      pc, =pabt_handler     /* Prefetch Abort */
dabt_vector:
        ldr      pc, =dabt_handler     /* Data Abort */
rsvd_vector:
        b        rsvd_vector     /* reserved */
irq_vector:
        b        irq_handler     /* IRQ : read the AIC */
fiq_vector:
/*---------------------------------------------------------------------- 
--------
 *- Function             : fiq_handler
 *- Treatments           : FIQ Interrupt Handler.
 *- Called Functions     :
 *----------------------------------------------------------------------- 
-------*/
fiq_handler:
  b        fiq_handler

/*---------------------------------------------------------------------- 
--------
 *- Function             : irq_handler
 *- Treatments           : IRQ Controller Interrupt Handler.
 *- Called Functions     : AIC_IVR[interrupt]
 *----------------------------------------------------------------------- 
-------*/
irq_handler:
/*- Manage Exception Entry */
/*- Adjust and save LR_irq in IRQ stack */
        sub      lr, lr, #4
        stmfd    sp!, {lr}
/*- Save r0 and SPSR in IRQ stack */
        mrs      r14, SPSR
        stmfd    sp!, {r0,r14}

/*- Write in the IVR to support Protect Mode */
/*- No effect in Normal Mode */
/*- De-assert the NIRQ and clear the source in Protect Mode */
        ldr      r14, =AT91C_BASE_AIC
        ldr      r0 , [r14, #AIC_IVR]
        str      r14, [r14, #AIC_IVR]

/*- Enable Interrupt and Switch in Supervisor Mode */
        msr      CPSR_c, #ARM_MODE_SVC

/*- Save scratch/used registers and LR in User Stack */
        stmfd    sp!, {r1-r3, r12, r14}

/*- Branch to the routine pointed by the AIC_IVR */
        mov      r14, pc
        bx       r0

/*- Restore scratch/used registers and LR from User Stack */
        ldmia    sp!, {r1-r3, r12, r14}

/*- Disable Interrupt and switch back in IRQ mode */
        msr      CPSR_c, #ARM_MODE_IRQ | I_BIT

/*- Mark the End of Interrupt on the AIC */
        ldr      r14, =AT91C_BASE_AIC
        str      r14, [r14, #AIC_EOICR]

/*- Restore SPSR_irq and r0 from IRQ stack */
        ldmia    sp!, {r0,r14}
        msr      SPSR_cxsf, r14

/*- Restore adjusted  LR_irq from IRQ stack directly in the PC */
        ldmia    sp!, {pc}^

/*---------------------------------------------------------------------- 
--------
 *- Function             : reset_handler
 *- Treatments           : Reset Interrupt Handler.
 *- Called Functions     : lowlevel_init
 *                         main
 *----------------------------------------------------------------------- 
-------*/
.section .text
reset_handler:
  ldr     pc, =_low_level_init

/*---------------------------------------------------------------------- 
--------
 *- Low level Init is performed in a C function: lowlevel_init
 *- Init Stack Pointer to a valid memory area before calling
lowlevel_init
 *----------------------------------------------------------------------- 
-------*/
/*- Temporary stack in internal RAM for Low Level Init execution */
_low_level_init:
  ldr      r2, =_lp_ll_init
        ldmia    r2, {r0, r1}
        mov      sp, r1
        mov      lr, pc
        bx       r0                      /* Branch on C function
(interworking) */

/*---------------------------------------------------------------------- 
--------
 *- Remap SRAM at 0x0
 *----------------------------------------------------------------------- 
-------*/
_remap:
        ldr r2, _lp_remap
        mov r0, #AT91C_MC_RCB
        str r0, [r2]

/*---------------------------------------------------------------------- 
--------
 *- Setup the stack for each mode
 *----------------------------------------------------------------------- 
-------*/
_stack_init:
  ldr      r2, =_lp_stack_init
        ldmia    r2, {r0, r1, r2}

/*- Set up Abort Mode and set ABT Mode Stack */
        msr      CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT
        mov      sp, r0
        sub      r0, r0, r1

/*- Set up Interrupt Mode and set IRQ Mode Stack */
        msr      CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT
        mov      sp, r0
        sub      r0, r0, r2

/*- Enable interrupt & Set up Supervisor Mode and set Supervisor Mode
Stack */
        msr      CPSR_c, #ARM_MODE_SVC | F_BIT
        mov      sp, r0

/*---------------------------------------------------------------------- 
--------
 *- Segments initialization
 *----------------------------------------------------------------------- 
-------*/
/* Copy the data section in RAM at 0x0000 */
_init_data:
  ldr      r2, =_lp_data
        ldmia    r2, {r1, r3, r4}
1:
        cmp      r3, r4
        ldrcc    r2, [r1], #4
        strcc    r2, [r3], #4
        bcc      1b

/* Clear the bss segment */
_init_bss:
  ldr      r2, =_lp_bss
        ldmia    r2, {r3, r4}
        mov      r2, #0
1:
        cmp      r3, r4
        strcc    r2, [r3], #4
        bcc      1b

/*---------------------------------------------------------------------- 
--------
 *- Branch to the main
 *----------------------------------------------------------------------- 
-------*/
_branch_main:
        ldr      r0, =main
        mov      lr, pc
        bx       r0

/*---------------------------------------------------------------------- 
--------
 *- Litteral pools
 *----------------------------------------------------------------------- 
-------*/
_lp_ll_init:
        .word    lowlevel_init
        .word    TOP_OF_MEMORY              /* Default SVC stack after
power up */

_lp_remap:
        .word    AT91C_MC_RCR

_lp_stack_init:
        .word    TOP_OF_MEMORY             /* Top of the stack */
        .word    ABT_STACK_SIZE            /* ABT stack size */
        .word    IRQ_STACK_SIZE            /* IRQ stack size */

_lp_bss:
        .word    _sbss
        .word    _ebss

_lp_data:
        .word    _etext
        .word    _sdata
        .word    _edata

von Martin T. (mthomas) (Moderator)


Rate this post
useful
not useful
Jacopo Charmet wrote:
> Martin Thomas wrote:
>> Please show your complete linker-script
>
> Here it is (is the Cstartup.S file):

This is not the linker-script. As the filename implies it's the
startup-code. Please read the "ARM bare-metal"-tutorial at embedded.com
or Jim Lynchs tutorial from atmel.com for a basic introduction esp. what
linker-scripts are and for what they are used (no need to understand
every entry in such a script, but at least the basics).

You may just take the startup-code and linker-script from either the
embedded.com "bare-metal" tutorial, the software-packages from atmel.com
or from a WinARM example (IRC "RAM-functions" are not covered in J.
Lynch's tutorial and not used in the software-packages from Atmel). At
least in the "bare-metal" example and my "AT91SAM7S gamma"-example you
should find enough information which you could use as templates. Both
prepared for "RAM-functions". A little different but the basic approach
is the same.

von Jacopo C. (jacopo)


Rate this post
useful
not useful
Martin Thomas wrote:
> Jacopo Charmet wrote:
>> Martin Thomas wrote:
>>> Please show your complete linker-script
>>
>> Here it is (is the Cstartup.S file):
>
> This is not the linker-script. As the filename implies it's the
> startup-code. Please read the "ARM bare-metal"-tutorial at embedded.com
> or Jim Lynchs tutorial from atmel.com for a basic introduction esp. what
> linker-scripts are and for what they are used (no need to understand
> every entry in such a script, but at least the basics).
>
> You may just take the startup-code and linker-script from either the
> embedded.com "bare-metal" tutorial, the software-packages from atmel.com
> or from a WinARM example (IRC "RAM-functions" are not covered in J.
> Lynch's tutorial and not used in the software-packages from Atmel). At
> least in the "bare-metal" example and my "AT91SAM7S gamma"-example you
> should find enough information which you could use as templates. Both
> prepared for "RAM-functions". A little different but the basic approach
> is the same.

Thank you for your suggests and sorry for misunderstanding... now I
modify the linker script as follow

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(reset_handler)

/*#include "project.h"*/


SECTIONS
{
  .text : {
    _stext = .;
    *(.text)
    *(.rodata)                 /* read-only data (constants) */
    *(.rodata*)
    . = ALIGN(4);
     _etext = . ;
  }

  /* collect all initialized .data sections that go into FLASH  */
  .data : AT ( ADDR (.text) + SIZEOF (.text) ) {
        _sdata = .;
       *(.vectors)
    *(.data)
    *(.data.*)
       *(.gnu.linkonce.d*)
       SORT(CONSTRUCTORS) /* mt 4/2005 */
       . = ALIGN(4);
       *(.fastrun)         /* "RAM-Functions" */ /* added by mthomas */
    _edata = .;
  }

  /* collect all uninitialized .bss sections that go into FLASH  */
  .bss (NOLOAD) : {
    . = ALIGN(4);
    _sbss = .;
    *(.bss)
    _ebss = .;
  }
}
end = .;



and it seems good (there are no warnings in the linker).
But when writing to the flash, the write loop generates a Data Abort
exception.
(If I use the debugger and go step by step it works fine, in run mode it
goes in Data Abort exception)
Why?

von Jim K. (ancaritha)


Rate this post
useful
not useful
Jacopo Charmet wrote:
> and it seems good (there are no warnings in the linker).
> But when writing to the flash, the write loop generates a Data Abort
> exception.
> (If I use the debugger and go step by step it works fine, in run mode it
> goes in Data Abort exception)
> Why?


The first thing that comes to mind is to have to write to flash in
chunks of 4 bytes.  There should be a basic flash example up on the at91
website (www.at91.com).  All of the SAM7 series are pretty similar so if
you find an example for any of them it should be fine.

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.