ARM926ej-s reset handler - does it overwrite itself?

1

I know that ARM926ej-s is using full descending stack. Now I have this startup code in which i have comented using /**/ on lines that are relevant for this question.

.global __start
.global arm926ejs_reset
.global dcache_flush
.global __gnu_bssstart
.global __gnu_bssend
.global __image_size


.EQU MODE_USR,    0x010
.EQU MODE_FIQ,    0x011
.EQU MODE_IRQ,    0x012
.EQU MODE_SVC,    0x013
.EQU MODE_SVC_NI, 0x0D3
.EQU MODE_ABORT,  0x017
.EQU MODE_UNDEF,  0x01b
.EQU MODE_SYSTEM, 0x01f
.EQU MODE_BITS,   0x01f
.EQU I_MASK,      0x080
.EQU F_MASK,      0x040
.EQU IF_MASK,     0x0C0

.EQU BROM_MMU_BASE_ADDR, 0x1201C000 

.EQU MMU_DISABLE_MASK,   0xFFFFEFFA
.EQU MMU_ENABLE_MASK,    0x00001005

.EQU FIQ_STACK_SIZE,     128
.EQU IRQ_STACK_SIZE,     256
.EQU ABORT_STACK_SIZE,   32
.EQU UNDEF_STACK_SIZE,   32
.EQU SYSTEM_STACK_SIZE,  64

.text
.code 32
.align 2

__start:
arm926ejs_reset:
    B     arm926ejs_reset_handler     /*reset vector*/

.word   0x41676d69
.word   0,0,0,0,0
image_type:
.word   0x0000000A
sizeOfPermanentCode:    
    .word   (__image_size)
    .word   0,0
bootparameter:  
    .word   0
    .word   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0

arm926ejs_reset_handler:

    MOV   r0, #MODE_SVC_NI
    MSR   cpsr_cxsf, r0

    MRC   p15, 0, r1, c1, c0, 0
    LDR   r2,=MMU_DISABLE_MASK
    AND   r1, r1, r2
    MCR   p15, 0, r1, c1, c0, 0

    MOV   r1,#0
    MCR   p15, 0, r1, c8, c7, 0

    MCR   p15, 0, r1, c7, c7, 0

    MRC   p15, 0, r1, c1, c0, 0
    LDR   r2,=0x1000
    ORR   r1, r1, r2
    MCR   p15, 0, r1, c1, c0, 0

    MVN   r1, #0
    MCR   p15, 0, r1, c3, c0, 0

    LDR   r3, =BROM_MMU_BASE_ADDR
    MCR   p15, 0, r3, c2, c0, 0

    LDR   r5, =inVirtMem

    MRC   p15, 0, r1, c1, c0, 0
    LDR   r2,=MMU_ENABLE_MASK
    ORR   r1, r1, r2
    MCR   p15, 0, r1, c1, c0, 0

    MOV   pc, r5

    NOP
    NOP
    NOP

inVirtMem:
    ADR   r3, arm926ejs_reset         /*we store the reset vector address*/
    SUB   r3, r3, #4                  /*why do we then substract 4 bytes?*/
    MOV   r1, #IF_MASK

    ORR   r0, r1, #MODE_FIQ           /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3                 
    SUB   r3, r3, #FIQ_STACK_SIZE


    ORR   r0, r1, #MODE_IRQ           /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3
    SUB   r3, r3, #IRQ_STACK_SIZE

    ORR   r0, r1, #MODE_ABORT         /*sets stack for MCPU mode*/ 
    MSR   cpsr_cxsf, r0
    MOV   sp, r3
    SUB   r3, r3, #ABORT_STACK_SIZE

    ORR   r0, r1, #MODE_UNDEF         /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3
    SUB   r3, r3, #UNDEF_STACK_SIZE

    ORR   r0, r1, #MODE_SYSTEM        /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3
    SUB   r3, r3, #SYSTEM_STACK_SIZE

    ORR   r0, r1, #MODE_SVC           /*sets stack for MCPU mode*/
    MSR   cpsr_cxsf, r0
    MOV   sp, r3

    LDR   r0, =__gnu_bssstart
    LDR   r1, =__gnu_bssend
    MOV   r2, #0

clearzi:
    CMP   r0, r1
    BEQ   clearzi_exit
    STR   r2, [r0]
    ADD   r0, r0, #4
    B clearzi

clearzi_exit:

load_entry:
    LDR   pc, =c_entry
    NOP

dcache_flush:
    CMP   r0, #0
    BNE   inval

flushonly:
    MRC  p15, 0, r15, c7, c10, 3
    BNE  flushonly
    MOV  pc, lr

inval:
    MRC  p15, 0, r15, c7, c14, 3
    BNE  inval
    MOV  pc, lr

.END

In the code above the first comment shows a reset vector (a branching instruction B arm926ejs_reset_handler) immediately followed by a header and some commands to prepare the mcu...

Now take a look at the next comment where we store the reset vector's address into register r3 and in the next line we substract the 4 bytes from this address.

Q1: Why do we do this? Does this address now show at the location of the .word 0x41676d69 ?

In next lines there are multiple simmilar blocks and each sets the stack for different mcpu modes. Lets take a look at the first one where stack pointer sp is loaded with register r3 and then the size of the stack is substracted from this address to get the stack size for this mcpu mode.

Q2: Does this stack overwrite the header from .word 0x41676d69 on and all the instructions used to prepare the mcu? Does reset vector B arm926ejs_reset_handler stay intact? Why do we owerwrite header? Don't we need it anymore?

assembly
stack
arm
asked on Stack Overflow Nov 26, 2013 by 71GA • edited Nov 26, 2013 by 71GA

1 Answer

2

Now take a look at the next comment where we store the reset vector's address into register r3 and in the next line we substract the 4 bytes from this address.

Q1: Why do we do this? Does this address now show at the location of the .word 0x41676d69 ?

Generally code increments. So the value .word 0x41676d69 is after or *arm926ejs_reset+4*. When you subtract, you put the start of the descending stack just before the code memory.

Q2: Does this stack overwrite the header from .word 0x41676d69 on and all the instructions used to prepare the mcu? Does reset vector B arm926ejs_reset_handler stay intact? Why do we owerwrite header? Don't we need it anymore?

No, it is not over-written. The memory before the image is used for the stacks.

answered on Stack Overflow Nov 27, 2013 by artless noise

User contributions licensed under CC BY-SA 3.0