| Author |
Message |
Paul Marcel
Guest
|
Posted:
Tue Dec 07, 2004 7:41 am Post subject:
Need help with ARM linker file |
|
|
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 |
|
|
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 |
|
|
"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 |
|
|
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 |
|
|
"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 |
|
 |
|
|
|
|