wz2b wrote on Sunday, May 27, 2007:
Good point. Yes I am setting up USR – I will fix that next. I also set up an abort stack that I probably also don’t need, since abort does nothing but loop to itself. (Maybe later I will want abort to do something more useful).
I noticed some questions about initialization elsewhere on the forums. I will post my startup for the LPC2129/GCC in case it is useful for others. There are two snippets attached: my startup.s as well as lpc2129.x (linker script). I tried to make the linker configuration reasonably minimal. It allows for placement and location of initialized data at separate locations (ram and flash) and all of that seems to work well for me so far.
— cut here —
#define RAM_BASE 0x40000000
#define RAM_SIZE 16*1024
#define USR_STACK_SIZE 2048
#define USR_STACK_POINTER (RAM_BASE + RAM_SIZE)
#define Mode_USR 0x10
#define Mode_FIQ 0x11
#define Mode_IRQ 0x12
#define Mode_SVC 0x13
#define Mode_ABT 0x17
#define Mode_UNDEF 0x1B
#define Mode_SYS 0x1F
#define I_Bit 0x80
#define F_Bit 0x40
.text
.global _start
.global undef_routine
.global data_abort
.global prefetch_abort
.global startup_routine
_start:
startup_routine:
// set the SYS, I, and F bits in the CONTROL field of the CPU status register
// I is the interrupt mask
// F is the fast irq mask
// T indicates if we are in thumb mode … it is bit 0x20
// The lower 5 bits are the MODE bits. Mode 0x1F is System mode.
msr cpsr_c, #Mode_SYS | I_Bit | F_Bit
// Load the static pointer to top of ram
ldr SP,=USR_STACK_POINTER
// Call the low level initialization
bl lowlevelinit
// switch to irq mode and set his stack pointer too
msr cpsr_c, #Mode_IRQ | F_Bit | I_Bit
ldr SP,=(USR_STACK_POINTER-USR_STACK_SIZE-4)
// switch to undefined mode and set his stack pointer
msr cpsr_c, #Mode_UNDEF | F_Bit | I_Bit
ldr SP,=(USR_STACK_POINTER-USR_STACK_SIZE-USR_STACK_SIZE-4)
// switch to fast irq mode and set his stack pointer
msr cpsr_c, #Mode_FIQ | F_Bit | I_Bit
ldr SP,=(USR_STACK_POINTER-USR_STACK_SIZE-USR_STACK_SIZE-USR_STACK_SIZE-4)
// switch to abort mode and set his stack pointer
msr cpsr_c, #Mode_ABT | F_Bit | I_Bit
ldr SP,=(USR_STACK_POINTER-USR_STACK_SIZE-USR_STACK_SIZE-USR_STACK_SIZE-USR_STACK_SIZE-4)
// switch to supervisor mode and set his stack pointer
msr cpsr_c, #Mode_SVC | F_Bit | I_Bit
ldr SP,=(USR_STACK_POINTER-USR_STACK_SIZE-USR_STACK_SIZE-USR_STACK_SIZE-USR_STACK_SIZE-USR_STACK_SIZE-4)
// Switch back to supervisor
msr cpsr_c, #Mode_SVC
ldr SP,=USR_STACK_POINTER
bl clear_bss
bl initialize_sdata
mov a2, #0 /* Fill value */
mov fp, a2 /* Null frame pointer */
mov r7, a2 /* Null frame pointer for Thumb */
mov r0, #0 /* no arguments */
mov r1, #0 /* no argv either */
b main
/////////////////////////////////////////////////////////////////////////////
//
// Clear BSS
//
/////////////////////////////////////////////////////////////////////////////
clear_bss:
ldr r1, =__bss_start__
ldr r3, =__bss_end__
subs r3, r3, r1
beq .end_clear_loop
mov r2, #0
.clear_loop:
strb r2, [r1], #1
subs r3, r3, #1
bgt .clear_loop
.end_clear_loop:
mov pc, lr
/////////////////////////////////////////////////////////////////////////////
//
// Initialize data section
//
/////////////////////////////////////////////////////////////////////////////
initialize_sdata:
ldr r1, =_etext
ldr r2, =__data_start__
ldr r3, =__data_end__
loopdat:
cmp r2, r3
ldrlo r0, [r1], #4
strlo r0, [r2], #4
blo loopdat
// done
mov pc, lr
— end —
Now, in order to use this you have to have the corresponding linker configuration file, that defines the correct symbols for various pieces of memory. Here’s what I came up with:
— cut here —
/* Default linker script, for normal executables */
MEMORY
{
/*
* Code space is 256KB minus 8KB for the bootloader area
* that cannot be used
*/
text (rx) : ORIGIN = 0x00000000, LENGTH = 0x3E000
/*
* RealMonitor (if present) uses 0x40000040 - 0x4000011F
* In System Programming uses 0x40000120 - 0x400001FF
* Flash programming commands use the top 32 bytes of on-chip RAM.
*
* The resulting useful ram is 0x40000200 through 0x40003FE0
*/
data (rwx) : ORIGIN = 0x40000200, LENGTH = 0x3DE0
}
/* OUTPUT_FORMAT("elf32-littlearm") */
OUTPUT_ARCH(arm7tdmi)
ENTRY(_start)
SECTIONS
{
.text :
{
_start_of_text_ = .;
*(.vectors)
*(.text .stub .text.*)
*(.glue_7t) *(.glue_7)
*(.rodata)
} > text
_etext = .;
/* RAM */
.data : AT ( ADDR(.text) + SIZEOF(.text) )
{
__data_start__ = . ;
. = ALIGN(2);
*(.data .data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
. = ALIGN(2);
__data_end__ = . ;
} > data
.data1 : { *(.data1) }
.tdata : { *(.tdata .tdata.* .gnu.linkonce.td.*) }
.tbss : { *(.tbss .tbss.* .gnu.linkonce.tb.*) *(.tcommon) }
.eh_frame : { KEEP (*(.eh_frame)) }
.gcc_except_table : { *(.gcc_except_table) }
.dynamic : { *(.dynamic) }
_edata = .;
PROVIDE (edata = .);
/* Uninitialized data */
__bss_start = .;
__bss_start__ = .;
.bss :
{
*(.dynbss)
*(.bss .bss.* .gnu.linkonce.b.*)
*(COMMON)
/* Align here to ensure that the .bss section occupies space up to
_end. Align after .bss to ensure correct alignment even if the
.bss section disappears because there are no input sections. */
. = ALIGN(32 / 8);
}
. = ALIGN(32 / 8);
_end = .;
_bss_end__ = . ; __bss_end__ = . ; __end__ = . ;
PROVIDE (end = .);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.stack 0x40003FDC :
{
_stack = .;
*(.stack)
}
.note.gnu.arm.ident 0 : { KEEP (*(.note.gnu.arm.ident)) }
/DISCARD/ : { *(.note.GNU-stack) }
PROVIDE (__stack__ = 0xa00) ;
}
— end —