Need help with ARM linker file
CASTalk.com Forum Index CASTalk.com
Discussion of DSP, FPGA, storage and embedded system.
 
 FAQFAQ   MemberlistMemberlist     RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 
 
Google
 
Web castalk.com
Need help with ARM linker file

 
Post new topic   Reply to topic    CASTalk.com Forum Index -> Embedded System
Author Message
Paul Marcel
Guest





Posted: Tue Dec 07, 2004 7:41 am    Post subject: Need help with ARM linker file Reply with quote

Hi,

I need to know how to set up a IRQ stack for the Atmel arm7tdmi ARM
processor. I'm not sure where / how to do it. I think that I need to
set it up in boot.s and in ram.ld.

I'm embedding mininal code to illustrate what I'm trying to do:
boot.s, irq.s, main.c, ram.ld, makefile.

I haven't been able to find any example of how this is done. I hope
someone knows.

thank you,
Paul


BOOT.S:
-----------

..section .text
..code 32
..global vectors
vectors:
b reset @ 0x00 Reset
b exception @ 0x04 Undefined instruction
b exception @ 0x08 SWI
b exception @ 0xc0 Prefetch abort
b exception @ 0x10 Data abort
b exception @ 0x14 reserved vector
ldr pc, [pc, # -0xF20] @ 0x18 irqs fffff100
(AIC_IVR)
@ldr pc, [pc, #0xfffff100] @ 0x18 irqs fffff100
(AIC_IVR)
b exception @ 0x1c fast irqs
exception: @ 0x20
b exception
reset: ldr r1, bss_start @ defined in ram.ld 0x4c
ldr r2, bss_end @ defined in ram.ld 0x50
ldr r3, =0
loop: cmp r1,r2
strne r3,[r1],#+4
bne loop
ldr r13,stack_pointer @ Initialize the stack
pointer
bl main
b vectors
stack_pointer: .word _stack_top @ defined in ram.ld
bss_start: .word __bss_start__ @ defined in ram.ld 0x4c
bss_end: .word __bss_end__ @ defined in ram.ld 0x50
.end

IRQ.S
=========
.section .text
.code 32
irq: b 0
.end

MAIN.C
=========
int main ( void ) {
return 0;
}

RAM.LD:
=================

ENTRY(vectors)
SEARCH_DIR(.)
MEMORY {
sram : org = 0x00000000, len = 256K
}
SECTIONS {
.text : {
*(.text);
. = ALIGN(4);
} > sram
.data ADDR(.text) + SIZEOF(.text) : {
datastart = .;
__data_start__ = . ;
*(.data)
. = ALIGN(4);
__data_end__ = . ;
edata = .;
_edata = .;
} > sram
.bss ADDR(.data) + SIZEOF(.data) : {
__bss_start__ = . ;
*(.bss); *(COMMON)
__bss_end__ = . ;
_stack_bottom = . ;
. += 0x800 ;
_stack_top = . ;
} > sram
end = .;
_end = .;
__end__ = .;

/* Symbols */
.stab 0 (NOLOAD) : {
[ .stab ]
}
.stabstr 0 (NOLOAD) : {
[ .stabstr ]
}
}

MAKEFILE:
============

LD = ram.ld
CFLAGS = -g -I. -IC:\flo4\logger\gnu -mcpu=arm7tdmi
ASFLAGS = -mcpu=arm7tdmi -gstabs
LDFLAGS = -Tram.ld -nostartfiles -Lgcc -L.
OBJS = boot.o irq.o main.o
EXE = test.elf
BIN = test.bin
DIS = test.lst
HEX = test.hex
S = test.srec
MAP = test.map
$(BIN): $(EXE)
arm-none-elf-objcopy -O binary $(EXE) $(BIN)
arm-none-elf-objcopy -O ihex $(EXE) $(HEX)
arm-none-elf-objcopy -O srec $(EXE) $(S)
arm-none-elf-nm $(EXE) >$(MAP)
arm-none-elf-objdump -D -S $(EXE) >$(DIS)
ls -l test.*
$(EXE): $(OBJS)
arm-none-elf-gcc $(LDFLAGS) -o $(EXE) $(OBJS)
$(OBJS): $(LD)
$(OBJS): Makefile
%.o:%.c
arm-none-elf-gcc -c $(CFLAGS) $< -o $@
%.o:%.s
arm-none-elf-as $(ASFLAGS) $< -o $@
clean:
rm -f $(OBJS)
rm -f $(EXE)
rm -f $(BIN)
rm -f $(DIS)
rm -f $(HEX)
rm -f $(S)
rm -f $(MAP)
Back to top
Tauno Voipio
Guest





Posted: Tue Dec 07, 2004 12:31 pm    Post subject: Re: Need help with ARM linker file Reply with quote

Paul Marcel wrote:
Quote:
Hi,

I need to know how to set up a IRQ stack for the Atmel arm7tdmi ARM
processor. I'm not sure where / how to do it. I think that I need to
set it up in boot.s and in ram.ld.

I'm embedding mininal code to illustrate what I'm trying to do:
boot.s, irq.s, main.c, ram.ld, makefile.

I haven't been able to find any example of how this is done. I hope
someone knows.

thank you,
Paul


Setting up the IRQ stack pointer needs you to be in IRQ mode.

To do this:

- set PSR so that IRQ and FIQ are forbidden
- change mode in PSR to IRQ
- load r13 (sp)
- restore PSR

Please note that the CPU is in supervisor mode after reset.
This is OK if you're not going to use software interrupts,
else change mode to system mode at start. User mode won't go:
you cannot manipulate the mode and interrupt bits in user mode.

If you run a simple non-nestable interrupt service in system
mode, you might get by without using an IRQ stack at all,

----

irqentry:

@@ Keep the following instructions, if the interrupt disable
@@ timing patch is needed, see Atmel application note 1156A

mrs r13,spsr @ get saved PSR
tst r13,#0x80 @ interrupts enabled?
subnes pc,lr,#4 @ yes - immediate interrupt dismiss

@@ end if timing patch

ldr r13,=save_area
stm r13,{r0-r14}^ @ save user registers

mrs r0,cpsr
orr r0,r0,#0x1f @ system mode
msr cpsr,r0

@ handle the interrupt in system mode,
@ could e.g. bl to a C routine to do it
@ remember to send EOI to interrupt controller

mrs 0,cpsr
bic r0,r0,#0x1f
orr r0,r0,#0x12 @ IRQ mode
msr cpsr,r0

ldm r13,{r0-r14}^ @ restore user registers
nop @ banked ldm recovery delay
subs pc,lr,#4 @ dismiss the interrupt

----

Disclaimer: Code manually copied from working kernel. All bugs
are guaranteed.

HTH

--

Tauno Voipio
tauno voipio (at) iki fi
Back to top
Richard
Guest





Posted: Tue Dec 07, 2004 2:05 pm    Post subject: Re: Need help with ARM linker file Reply with quote

"Paul Marcel" <paulmarcell@charter.net> wrote in message
news:906ar0ledgmfra42gcap9i0l4p6c0ucikb@4ax.com...
Quote:

Hi,

I need to know how to set up a IRQ stack for the Atmel arm7tdmi ARM
processor. I'm not sure where / how to do it. I think that I need to
set it up in boot.s and in ram.ld.

I'm embedding mininal code to illustrate what I'm trying to do:
boot.s, irq.s, main.c, ram.ld, makefile.

I haven't been able to find any example of how this is done. I hope
someone knows.

thank you,
Paul

snip


You need to setup the stacks in your startup code as follows:

First define the size of the stack for each mode:
..set UND_STACK_SIZE, 0x00000004
..set ABT_STACK_SIZE, 0x00000004
..set FIQ_STACK_SIZE, 0x00000004
..set IRQ_STACK_SIZE, 0X00000400
..set SVC_STACK_SIZE, 0x00000400

A few other constants just for ease of reading.
..set MODE_USR, 0x10 /* User Mode */
..set MODE_FIQ, 0x11 /* FIQ Mode */
..set MODE_IRQ, 0x12 /* IRQ Mode */
..set MODE_SVC, 0x13 /* Supervisor Mode */
..set MODE_ABT, 0x17 /* Abort Mode */
..set MODE_UND, 0x1B /* Undefined Mode */
..set MODE_SYS, 0x1F /* System Mode */



////// CODE ///////

/* Load R0 with the address for the first stack */
ldr r0, .START_ADDRESS
/* Switch to the mode for which you are going to setup the stack. */
msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction mode */
/* Move the stack address into the stack pointer. */
mov sp, r0
/* Move the address past the stack just setup. */
sub r0, r0, #UND_STACK_SIZE
/* Repeat for every mode. */
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

///// CODE END //////

This holds the RAM address to use for the stack in R0. For each mode you
switch to the MODE, then copy the value from R0 into the stack pointer.
Then modifiy R0 by however many bytes you want to be available for that
stack, before moving onto the next mode and repeating.

Hope this helps.

Richard.

http://www.FreeRTOS.org
Back to top
Paul Marcel
Guest





Posted: Tue Dec 07, 2004 9:30 pm    Post subject: Re: Need help with ARM linker file Reply with quote

On Tue, 07 Dec 2004 09:05:04 GMT, "Richard" <Nowhere@Nowhere.com>
wrote:

Quote:

You need to setup the stacks in your startup code as follows:

First define the size of the stack for each mode:
.set UND_STACK_SIZE, 0x00000004
.set ABT_STACK_SIZE, 0x00000004
.set FIQ_STACK_SIZE, 0x00000004
.set IRQ_STACK_SIZE, 0X00000400
.set SVC_STACK_SIZE, 0x00000400

A few other constants just for ease of reading.
.set MODE_USR, 0x10 /* User Mode */
.set MODE_FIQ, 0x11 /* FIQ Mode */
.set MODE_IRQ, 0x12 /* IRQ Mode */
.set MODE_SVC, 0x13 /* Supervisor Mode */
.set MODE_ABT, 0x17 /* Abort Mode */
.set MODE_UND, 0x1B /* Undefined Mode */
.set MODE_SYS, 0x1F /* System Mode */



////// CODE ///////

/* Load R0 with the address for the first stack */
ldr r0, .START_ADDRESS
/* Switch to the mode for which you are going to setup the stack. */
msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction mode */
/* Move the stack address into the stack pointer. */
mov sp, r0
/* Move the address past the stack just setup. */
sub r0, r0, #UND_STACK_SIZE
/* Repeat for every mode. */
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

///// CODE END //////

This holds the RAM address to use for the stack in R0. For each mode you
switch to the MODE, then copy the value from R0 into the stack pointer.
Then modifiy R0 by however many bytes you want to be available for that
stack, before moving onto the next mode and repeating.

Hope this helps.

Richard.

http://www.FreeRTOS.org



I think that I'm finally starting to see how this works. I added most
of your code and this still builds. I only modified boot.s. But I
still need clarification of ".START_ADDRESS" and the relation between
boot.s and ram.ld. I've left in my old stack initialization stuff from
a non-interrupt example. I'll remove that eventually. What do I need
to do in ram.ld to make this work? Do all the stacks go in the .bss
section? Also should I zero each stack after setting the sp? Can I
just set the stacks up in boot.s and not have to mess with ram.ld?

Paul


BOOT.S:
=============


..section .text
..code 32
..global vectors

@ define the size of the stack for each mode:
..set UND_STACK_SIZE, 0x00000004
..set ABT_STACK_SIZE, 0x00000004
..set FIQ_STACK_SIZE, 0x00000004
..set IRQ_STACK_SIZE, 0X00000400
..set SVC_STACK_SIZE, 0x00000400

@ A few other constants just for ease of reading

..set MODE_USR, 0x10 @ User Mode
..set MODE_FIQ, 0x11 @ FIQ Mode
..set MODE_IRQ, 0x12 @ IRQ Mode
..set MODE_SVC, 0x13 @ Supervisor Mode
..set MODE_ABT, 0x17 @ Abort Mode
..set MODE_UND, 0x1B @ Undefined Mode
..set MODE_SYS, 0x1F @ System Mode

..equ F_BIT, 0x40
..equ I_BIT, 0x80


vectors:
b reset @ 0x00 Reset
b exception @ 0x04 Undefined instruction
b exception @ 0x08 SWI
b exception @ 0xc0 Prefetch abort
b exception @ 0x10 Data abort
b exception @ 0x14 reserved vector
ldr pc, [pc, # -0xF20] @ 0x18 irqs fffff100 (AIC_IVR)
@ldr pc, [pc, #0xfffff100] @ 0x18 irqs fffff100 (AIC_IVR)
b exception @ 0x1c fast irqs

exception: @ 0x20
b exception

reset:

@ old code (((((((((((((((((((((
@ Begin by clearing out the .bss section defined in ram.ld
ldr r1, bss_start @ defined in ram.ld 0x4c
ldr r2, bss_end @ defined in ram.ld 0x50
ldr r3, =0
clear_bss:
cmp r1,r2
strne r3,[r1],#+4
bne clear_bss
@))))))))))))))))))))))))))))) old code

/***
@ old code:
@ldr r13,stack_pointer @ Initialize the stack pointer
@ldr r0, .START_ADDRESS @ Load R0 with the
address for the first stack
***/

ldr r0, start_address @ Load R0 with the address for
the first stack

@ Switch to the mode for which you are going to setup the
stack

msr CPSR_c, #MODE_UND|I_BIT|F_BIT @ Undefined
Instruction mode
mov sp, r0 @ Move the stack
address into the stack pointer
sub r0, r0, #UND_STACK_SIZE @ Move the address
past the stack just setup

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

bl main

b vectors

stack_pointer: .word _stack_top @ defined in ram.ld
bss_start: .word __bss_start__ @ defined in ram.ld 0x4c
bss_end: .word __bss_end__ @ defined in ram.ld 0x50

start_address:

.end


RAM.LD:
==========

ENTRY(vectors)

SEARCH_DIR(.)

MEMORY {
sram : org = 0x00000000, len = 256K
}

SECTIONS {
.text : {
*(.text);
. = ALIGN(4);
} > sram

.data ADDR(.text) + SIZEOF(.text) : {
datastart = .;
__data_start__ = . ;
*(.data)
. = ALIGN(4);
__data_end__ = . ;
edata = .;
_edata = .;
} > sram


.bss ADDR(.data) + SIZEOF(.data) : {
__bss_start__ = . ;
*(.bss); *(COMMON)
__bss_end__ = . ;
_stack_bottom = . ;
. += 0x800 ;
_stack_top = . ;
} > sram

end = .;
_end = .;
__end__ = .;

/* Symbols */
.stab 0 (NOLOAD) : {
[ .stab ]
}

.stabstr 0 (NOLOAD) : {
[ .stabstr ]
}
}
Back to top
Richard
Guest





Posted: Tue Dec 07, 2004 10:05 pm    Post subject: Re: Need help with ARM linker file Reply with quote

"Paul Marcel" <paulmarcell@charter.net> wrote in message
news:43mbr0lbgdadvo5jum6c2t6jldjremp2o0@4ax.com...
Quote:
On Tue, 07 Dec 2004 09:05:04 GMT, "Richard" <Nowhere@Nowhere.com
wrote:


You need to setup the stacks in your startup code as follows:

First define the size of the stack for each mode:
.set UND_STACK_SIZE, 0x00000004
.set ABT_STACK_SIZE, 0x00000004
.set FIQ_STACK_SIZE, 0x00000004
.set IRQ_STACK_SIZE, 0X00000400
.set SVC_STACK_SIZE, 0x00000400

A few other constants just for ease of reading.
.set MODE_USR, 0x10 /* User Mode */
.set MODE_FIQ, 0x11 /* FIQ Mode */
.set MODE_IRQ, 0x12 /* IRQ Mode */
.set MODE_SVC, 0x13 /* Supervisor Mode */
.set MODE_ABT, 0x17 /* Abort Mode */
.set MODE_UND, 0x1B /* Undefined Mode */
.set MODE_SYS, 0x1F /* System Mode */



////// CODE ///////

/* Load R0 with the address for the first stack */
ldr r0, .START_ADDRESS
/* Switch to the mode for which you are going to setup the stack. */
msr CPSR_c, #MODE_UND|I_BIT|F_BIT /* Undefined Instruction mode */
/* Move the stack address into the stack pointer. */
mov sp, r0
/* Move the address past the stack just setup. */
sub r0, r0, #UND_STACK_SIZE
/* Repeat for every mode. */
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

///// CODE END //////

This holds the RAM address to use for the stack in R0. For each mode you
switch to the MODE, then copy the value from R0 into the stack pointer.
Then modifiy R0 by however many bytes you want to be available for that
stack, before moving onto the next mode and repeating.

Hope this helps.

Richard.

http://www.FreeRTOS.org



I think that I'm finally starting to see how this works. I added most
of your code and this still builds. I only modified boot.s. But I
still need clarification of ".START_ADDRESS" and the relation between
boot.s and ram.ld. I've left in my old stack initialization stuff from
a non-interrupt example. I'll remove that eventually. What do I need
to do in ram.ld to make this work? Do all the stacks go in the .bss
section? Also should I zero each stack after setting the sp? Can I
just set the stacks up in boot.s and not have to mess with ram.ld?

Paul


Using my boot file .START_ADDRESS gets set to .LC6 - I changed it in demo
code I posted to .START_ADDRESS to make it more explicit. This is basically
the very top of the on chip RAM (minus 4 bytes for some reason).

..LC6 is then set to __stack_end__ as per:

// code from boot.s
.align 0

.LC1:
.word __bss_beg__
.LC2:
.word __bss_end__
.LC3:
.word __data_beg__
.LC4:
.word __data_beg_src__
.LC5:
.word __data_end__
.LC6:
.word __stack_end__
// end of code

If you want a full buildable demo you can download the FreeRTOS source code
(link below) and look in the FreeRTOS/Demo/ARM7 directory where you will
find a boot.s, linker scripts and a makefile. Unfortunately not for an
Atmel device but the principals are the same.

Regards.

http://www.FreeRTOS.org
Back to top
 
Post new topic   Reply to topic    CASTalk.com Forum Index -> Embedded System All times are GMT
Page 1 of 1

 
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum




VoIP Electronics Powered by phpBB