blob: 70bc79ba450626b50cc344c08bc89e02c6ae930c [file] [log] [blame]
/* ----------------------------------------------------------------------------
* SAM Software Package License
* ----------------------------------------------------------------------------
* Copyright (c) 2014, Atmel Corporation
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the disclaimer below.
*
* Atmel's name may not be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT ARE
* DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
* OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* ----------------------------------------------------------------------------
*/
//------------------------------------------------------------------------------
// Definitions
//------------------------------------------------------------------------------
#define AIC 0xFC06E000
#define AIC_IVR 0x10
#define AIC_EOICR 0x38
#define SAIC 0xFC068400
#define AIC_FVR 0x14
#define IRQ_STACK_SIZE 8*3*4
#define FIQ_STACK_SIZE 8*3*4
#define MODE_MSK 0x1F
#define ARM_MODE_ABT 0x17
#define ARM_MODE_FIQ 0x11
#define ARM_MODE_IRQ 0x12
#define ARM_MODE_SVC 0x13
#define ARM_MODE_SYS 0x1F
#define I_BIT 0x80
#define F_BIT 0x40
#define REG_SFR_AICREDIR 0xF8028054
#define REG_SFR_UID 0xF8028050
#define AICREDIR_KEY 0x5F67B102
//------------------------------------------------------------------------------
// Startup routine
//------------------------------------------------------------------------------
.align 4
.arm
/* Exception vectors
*******************/
.section .vectors, "a", %progbits
resetVector:
ldr pc, =resetHandler /* Reset */
undefVector:
b undefVector /* Undefined instruction */
swiVector:
b swiVector /* Software interrupt */
prefetchAbortVector:
b prefetchAbortVector /* Prefetch abort */
dataAbortVector:
b dataAbortVector /* Data abort */
reservedVector:
b reservedVector /* Reserved for future use */
irqVector:
b irqHandler /* Interrupt */
fiqVector:
b fiqHandler /* Fast interrupt */
//------------------------------------------------------------------------------
/// Handles a fast interrupt request by branching to the address defined in the
/// AIC.
//------------------------------------------------------------------------------
fiqHandler:
SUB lr, lr, #4
STMFD sp!, {lr}
/* MRS lr, SPSR */
STMFD sp!, {r0}
/* Write in the IVR to support Protect Mode */
LDR lr, =SAIC
LDR r0, [r14, #AIC_IVR]
STR lr, [r14, #AIC_IVR]
/* Branch to interrupt handler in Supervisor mode */
MSR CPSR_c, #ARM_MODE_SVC
STMFD sp!, {r1-r3, r4, r12, lr}
MOV r14, pc
BX r0
LDMIA sp!, {r1-r3, r4, r12, lr}
MSR CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT
/* Acknowledge interrupt */
LDR lr, =SAIC
STR lr, [r14, #AIC_EOICR]
/* Restore interrupt context and branch back to calling code */
LDMIA sp!, {r0}
/* MSR SPSR_cxsf, lr*/
LDMIA sp!, {pc}^
//------------------------------------------------------------------------------
/// Handles incoming interrupt requests by branching to the corresponding
/// handler, as defined in the AIC. Supports interrupt nesting.
//------------------------------------------------------------------------------
irqHandler:
/* Save interrupt context on the stack to allow nesting */
/* Save interrupt context on the stack to allow nesting */
SUB lr, lr, #4
STMFD sp!, {lr}
MRS lr, SPSR
STMFD sp!, {r0, lr}
/* Write in the IVR to support Protect Mode */
LDR lr, =AIC
LDR r0, [r14, #AIC_IVR]
STR lr, [r14, #AIC_IVR]
/* Branch to interrupt handler in Supervisor mode */
MSR CPSR_c, #ARM_MODE_SVC
STMFD sp!, {r1-r3, r4, r12, lr}
/* Check for 8-byte alignment and save lr plus a */
/* word to indicate the stack adjustment used (0 or 4) */
AND r1, sp, #4
SUB sp, sp, r1
STMFD sp!, {r1, lr}
BLX r0
LDMIA sp!, {r1, lr}
ADD sp, sp, r1
LDMIA sp!, {r1-r3, r4, r12, lr}
MSR CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT
/* Acknowledge interrupt */
LDR lr, =AIC
STR lr, [r14, #AIC_EOICR]
/* Restore interrupt context and branch back to calling code */
LDMIA sp!, {r0, lr}
MSR SPSR_cxsf, lr
LDMIA sp!, {pc}^
//------------------------------------------------------------------------------
/// Initializes the chip and branches to the main() function.
//------------------------------------------------------------------------------
.section .textEntry
.global entry
entry:
resetHandler:
CPSIE A
/* Enable VFP */
/* - Enable access to CP10 and CP11 in CP15.CACR */
//mrc p15, 0, r0, c1, c0, 2
//orr r0, r0, #0xf00000
//mcr p15, 0, r0, c1, c0, 2
/* - Enable access to CP10 and CP11 in CP15.NSACR */
/* - Set FPEXC.EN (B30) */
//fmrx r0, fpexc
//orr r0, r0, #0x40000000
//fmxr fpexc, r0
/* Useless instruction for referencing the .vectors section */
ldr r0, =resetVector
/* Set pc to actual code location (i.e. not in remap zone) */
ldr pc, =1f
/* Initialize the prerelocate segment */
1:
ldr r0, =_efixed
ldr r1, =_sprerelocate
ldr r2, =_eprerelocate
1:
cmp r1, r2
ldrcc r3, [r0], #4
strcc r3, [r1], #4
bcc 1b
/* Perform low-level initialization of the chip using LowLevelInit() */
ldr sp, =_cstack
stmfd sp!, {r0}
ldr r0, =LowLevelInit
blx r0
/* Initialize the postrelocate segment */
ldmfd sp!, {r0}
ldr r1, =_spostrelocate
ldr r2, =_epostrelocate
1:
cmp r1, r2
ldrcc r3, [r0], #4
strcc r3, [r1], #4
bcc 1b
/* Clear the zero segment */
ldr r0, =_szero
ldr r1, =_ezero
mov r2, #0
1:
cmp r0, r1
strcc r2, [r0], #4
bcc 1b
MRS r0, cpsr
/* Set up the fast interrupt stack pointer.*/
bic r0, r0, #MODE_MSK
orr r0, r0, #ARM_MODE_FIQ
msr cpsr_c, r0
ldr sp, =_fiqstack
bic sp,sp,#0x7
/* Set up the normal interrupt stack pointer.*/
bic r0, r0, #MODE_MSK
orr r0, r0, #ARM_MODE_IRQ
msr cpsr_c, r0
ldr sp, =_irqstack
bic sp,sp,#0x7
/* Set up the stack pointer.*/
bic r0 ,r0, #MODE_MSK
orr r0 ,r0, #ARM_MODE_SYS
msr cpsr_c, r0
ldr sp, =_sysstack
bic sp,sp,#0x7
bic r0 ,r0, #MODE_MSK
orr r0 ,r0, #ARM_MODE_SVC
msr cpsr_c, r0
ldr sp, =_cstack
bic sp,sp,#0x7
// Redirect FIQ to IRQ
LDR r0, =AICREDIR_KEY
LDR r1, = REG_SFR_UID
LDR r2, = REG_SFR_AICREDIR
LDR r3,[r1]
EORS r0, r0, r3
ORRS r0, r0, #0x01
STR r0, [r2]
/*Initialize the C library */
ldr r3, =__libc_init_array
mov lr, pc
bx r3
/* Branch to main()
******************/
ldr r0, =main
blx r0
/* Loop indefinitely when program is finished */
1:
b 1b