From 8983fcb5f2687b22b2cba68573f839ff2800e3c9 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Mon, 30 Mar 2009 12:20:47 +0000 Subject: Initial commit for the "Lyre prototype 1" port by Jorge Pinto from FS#10045. Bootloader builds, normal does not. git-svn-id: svn://svn.rockbox.org/rockbox/trunk@20574 a1c6a512-1295-4272-9138-f99709370657 --- firmware/target/arm/at91sam/lyre_proto1/crt0.S | 274 +++++++++++++++++++++++++ 1 file changed, 274 insertions(+) create mode 100644 firmware/target/arm/at91sam/lyre_proto1/crt0.S (limited to 'firmware/target/arm/at91sam/lyre_proto1/crt0.S') diff --git a/firmware/target/arm/at91sam/lyre_proto1/crt0.S b/firmware/target/arm/at91sam/lyre_proto1/crt0.S new file mode 100644 index 0000000000..0146a8409c --- /dev/null +++ b/firmware/target/arm/at91sam/lyre_proto1/crt0.S @@ -0,0 +1,274 @@ +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * + * + * Copyright (C) 2009 by Jorge Pinto + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +#include "at91sam9260.h" + +#define DRAMORIG AT91C_EBI_SDRAM_32BIT +#define DRAMSIZE (MEMORYSIZE * 0x100000) +#define IRAM0ORIG AT91C_IRAM_1 +#define IRAM0SIZE AT91C_IRAM_1_SIZE +#define TOP_OF_MEMORY (IRAM0ORIG + IRAM0SIZE) +#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 (Fast Interrupt) Interrupt Handler. + *- Called Functions : + *---------------------------------------------------------------------------*/ +fiq_handler: +pabt_handler: +dabt_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 - (LR - Link Register) */ + sub lr, lr, #4 + stmfd sp!, {lr} +/*- Save r0 and SPSR (Saved Program Status Register) in IRQ stack */ + mrs r14, SPSR + stmfd sp!, {r0,r14} + +/*- Write in the IVR (Interrupt Vector Register) 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: +/*----------------------------------------------------------------------------- + *- Low level Init is performed in a C function: lowlevel_init + *- Init Stack Pointer to a valid memory area before calling lowlevel_init + * + * Put Stack Pointer on end of IRAM 1 and branches to lowlevel_init function. + *---------------------------------------------------------------------------*/ +/*- Temporary stack in internal RAM for Low Level Init execution */ +_low_level_init: + ldr r2, =_litteral_pool_lowlevel_init /* Load r2 with the address of + * _litteral_pool_lowlevel_init + */ + ldmia r2, {r0, r1} /* r0 = lowlevel_init and r1 = TOP_OF_MEMORY */ + mov sp, r1 /* sp (Stack Pointer) = TOP_OF_MEMORY (end of IRAM 1) */ + mov lr, pc /* lr (Link register) = pc (Program Counter) */ + bx r0 /* Branch on C function (interworking) -- branch to + * lowlevel_init + */ + +/*----------------------------------------------------------------------------- + *- Setup the stack for each mode + * + * Executes this code after returning from lowlevel_init fucntion. + * Configures Abort Mode Stack + Interrupt Mode Stack + Supervisor Mode Stack, + * reserves 3 blocks, one for each mode and they start at end of IRAM 1. + *---------------------------------------------------------------------------*/ +_stack_init: + ldr r2, =_litteral_pool_stack_init + ldmia r2, {r0, r1, r2} /* r0 = TOP_OF_MEMORY (end of IRAM 1); + * r1 = ABT_STACK_SIZE; + * r2 = IRQ_STACK_SIZE + */ + + /*- Set up Abort Mode and set ABT Mode Stack */ + msr CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT /* Enter in Mode Abort + * and disable IRQ (Interrupt) and FIQ (Fast Interrupt) + */ + + mov sp, r0 /* sp (ABT Mode Stack Pointer) = TOP_OF_MEMORY + * (end of IRAM 1) + */ + + /* put r0 with value of the new address for next Stack */ + sub r0, r0, r1 /* r0 = r0 - r1 --> r0 = (end of IRAM 1) - + * (ABT_STACK_SIZE) + */ + + /*- Set up Interrupt Mode and set IRQ Mode Stack */ + msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT /* Enter in Mode Interrupt + * and disable IRQ (Interrupt) and FIQ (Fast Interrupt) + */ + + mov sp, r0 /* sp (Interrupt Mode Stack Pointer) = + * TOP_OF_MEMORY (end of IRAM 1) - (ABT_STACK_SIZE) + */ + + sub r0, r0, r2 /* Put on r0 the new address for next + * Stack (Supervisor Mode) + */ + +/*- 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 vectors section code from the LMA address to the LVA address */ +_init_vectors: + ldr r1, =_litteral_pool_vectors /* Load r1 with the address of + * _litteral_pool_vectors + */ + ldmia r1, {r2, r3, r4} /* r2 = DRAMORIG; r3 = _start_vectors_section; + * r4 = _end_vectors_section; + */ +1: + cmp r3, r4 /* Compare r3 with r4 (r3 - r4) */ + ldrcc r5, [r2], #4 /* if (_start_vectors_section < _end_vectors_section) + * { r5 = [r2]; r2 = r2 + 4; } + */ + strcc r5, [r3], #4 /* if (_start_vectors_section < _end_vectors_section) + * { [r3] = r5; r3 = r3 + 4; } + */ + bcc 1b /* loop while (_start_vectors_section < _end_vectors_section) */ + +/* Clear the bss segment */ +_init_bss: + ldr r2, =_litteral_pool_bss + ldmia r2, {r3, r4} /* r3 = _start_bss_section; r4 = _end_bss_section */ + mov r2, #0 /* r2 = 0 */ +1: + cmp r3, r4 /* Compare --> (_start_bss_section - _end_bss_section) */ + strcc r2, [r3], #4 /* if (_start_bss_section < _end_bss_section) { + * [r3] = 0; r3 = r3 + 4; } + */ + bcc 1b /* loop while _start_bss_section < _end_bss_section */ + +/* Set up some stack and munge it with 0xdeadbeef */ + ldr sp, =stackend + mov r3, sp + ldr r2, =stackbegin + ldr r4, =0xdeadbeef + +stackmunge: + cmp r3, r2 + strhi r4, [r2], #4 + bhi stackmunge + +/*----------------------------------------------------------------------------- + *- Branch to the main + *---------------------------------------------------------------------------*/ +_branch_main: + ldr r0, =main + mov lr, pc + bx r0 + +/*----------------------------------------------------------------------------- + *- Litteral pools + *---------------------------------------------------------------------------*/ +_litteral_pool_lowlevel_init: + .word lowlevel_init + .word TOP_OF_MEMORY /* Default SVC stack after power up */ + +_litteral_pool_stack_init: + .word TOP_OF_MEMORY /* Top of the stack */ + .word ABT_STACK_SIZE /* ABT stack size */ + .word IRQ_STACK_SIZE /* IRQ stack size */ + +_litteral_pool_bss: + .word _start_bss_section + .word _end_bss_section + +_litteral_pool_vectors: +#if defined(BOOTLOADER) + .word (DRAMORIG + DRAMSIZE - 0x100000) /* LMA address of vectors are at + * end of DRAM minus 1MByte + */ +#else + .word DRAMORIG /* LMA address of vectors are at DRAMORIG */ +#endif + .word _start_vectors_section + .word _end_vectors_section -- cgit v1.2.3