Last active
October 29, 2015 12:06
-
-
Save thewisenerd/860e78c36551b6daff9b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;/*****************************************************************************/ | |
;/* SAM7.S: Startup file for Atmel AT91SAM7 device series */ | |
;/*****************************************************************************/ | |
;/* <<< Use Configuration Wizard in Context Menu >>> */ | |
;/*****************************************************************************/ | |
;/* This file is part of the uVision/ARM development tools. */ | |
;/* Copyright (c) 2005-2006 Keil Software. All rights reserved. */ | |
;/* This software may only be used under the terms of a valid, current, */ | |
;/* end user licence from KEIL for a compatible version of KEIL software */ | |
;/* development tools. Nothing else gives you the right to use this software. */ | |
;/*****************************************************************************/ | |
;/* | |
; * The SAM7.S code is executed after CPU Reset. This file may be | |
; * translated with the following SET symbols. In uVision these SET | |
; * symbols are entered under Options - ASM - Define. | |
; * | |
; * REMAP: when set the startup code remaps exception vectors from | |
; * on-chip RAM to address 0. | |
; * | |
; * RAM_INTVEC: when set the startup code copies exception vectors | |
; * from on-chip Flash to on-chip RAM. | |
; */ | |
; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs | |
Mode_USR EQU 0x10 | |
Mode_FIQ EQU 0x11 | |
Mode_IRQ EQU 0x12 | |
Mode_SVC EQU 0x13 | |
Mode_ABT EQU 0x17 | |
Mode_UND EQU 0x1B | |
Mode_SYS EQU 0x1F | |
I_Bit EQU 0x80 ; when I bit is set, IRQ is disabled | |
F_Bit EQU 0x40 ; when F bit is set, FIQ is disabled | |
; Internal Memory Base Addresses | |
FLASH_BASE EQU 0x00100000 | |
RAM_BASE EQU 0x00200000 | |
;// <h> Stack Configuration (Stack Sizes in Bytes) | |
;// <o0> Undefined Mode <0x0-0xFFFFFFFF:8> | |
;// <o1> Supervisor Mode <0x0-0xFFFFFFFF:8> | |
;// <o2> Abort Mode <0x0-0xFFFFFFFF:8> | |
;// <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:8> | |
;// <o4> Interrupt Mode <0x0-0xFFFFFFFF:8> | |
;// <o5> User/System Mode <0x0-0xFFFFFFFF:8> | |
;// </h> | |
UND_Stack_Size EQU 0x00000000 | |
SVC_Stack_Size EQU 0x00000100 | |
ABT_Stack_Size EQU 0x00000000 | |
FIQ_Stack_Size EQU 0x00000000 | |
IRQ_Stack_Size EQU 0x00000080 | |
USR_Stack_Size EQU 0x00000400 | |
ISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ | |
FIQ_Stack_Size + IRQ_Stack_Size) | |
AREA STACK, NOINIT, READWRITE, ALIGN=3 | |
Stack_Mem SPACE USR_Stack_Size | |
__initial_sp SPACE ISR_Stack_Size | |
Stack_Top | |
;// <h> Heap Configuration | |
;// <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF> | |
;// </h> | |
Heap_Size EQU 0x00000000 | |
AREA HEAP, NOINIT, READWRITE, ALIGN=3 | |
__heap_base | |
Heap_Mem SPACE Heap_Size | |
__heap_limit | |
; Reset Controller (RSTC) definitions | |
RSTC_BASE EQU 0xFFFFFD00 ; RSTC Base Address | |
RSTC_MR EQU 0x08 ; RSTC_MR Offset | |
;/* | |
;// <e> Reset Controller (RSTC) | |
;// <o1.0> URSTEN: User Reset Enable | |
;// <i> Enables NRST Pin to generate Reset | |
;// <o1.8..11> ERSTL: External Reset Length <0-15> | |
;// <i> External Reset Time in 2^(ERSTL+1) Slow Clock Cycles | |
;// </e> | |
;*/ | |
RSTC_SETUP EQU 1 | |
RSTC_MR_Val EQU 0xA5000401 | |
; Embedded Flash Controller (EFC) definitions | |
EFC_BASE EQU 0xFFFFFF00 ; EFC Base Address | |
EFC0_FMR EQU 0x60 ; EFC0_FMR Offset | |
EFC1_FMR EQU 0x70 ; EFC1_FMR Offset | |
;// <e> Embedded Flash Controller 0 (EFC0) | |
;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255> | |
;// <i> Number of Master Clock Cycles in 1us | |
;// <o1.8..9> FWS: Flash Wait State | |
;// <0=> Read: 1 cycle / Write: 2 cycles | |
;// <1=> Read: 2 cycle / Write: 3 cycles | |
;// <2=> Read: 3 cycle / Write: 4 cycles | |
;// <3=> Read: 4 cycle / Write: 4 cycles | |
;// </e> | |
EFC0_SETUP EQU 1 | |
EFC0_FMR_Val EQU 0x00320100 | |
;// <e> Embedded Flash Controller 1 (EFC1) | |
;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255> | |
;// <i> Number of Master Clock Cycles in 1us | |
;// <o1.8..9> FWS: Flash Wait State | |
;// <0=> Read: 1 cycle / Write: 2 cycles | |
;// <1=> Read: 2 cycle / Write: 3 cycles | |
;// <2=> Read: 3 cycle / Write: 4 cycles | |
;// <3=> Read: 4 cycle / Write: 4 cycles | |
;// </e> | |
EFC1_SETUP EQU 1 | |
EFC1_FMR_Val EQU 0x00320100 | |
; Watchdog Timer (WDT) definitions | |
WDT_BASE EQU 0xFFFFFD40 ; WDT Base Address | |
WDT_MR EQU 0x04 ; WDT_MR Offset | |
;// <e> Watchdog Timer (WDT) | |
;// <o1.0..11> WDV: Watchdog Counter Value <0-4095> | |
;// <o1.16..27> WDD: Watchdog Delta Value <0-4095> | |
;// <o1.12> WDFIEN: Watchdog Fault Interrupt Enable | |
;// <o1.13> WDRSTEN: Watchdog Reset Enable | |
;// <o1.14> WDRPROC: Watchdog Reset Processor | |
;// <o1.28> WDDBGHLT: Watchdog Debug Halt | |
;// <o1.29> WDIDLEHLT: Watchdog Idle Halt | |
;// <o1.15> WDDIS: Watchdog Disable | |
;// </e> | |
WDT_SETUP EQU 1 | |
WDT_MR_Val EQU 0x00008000 | |
; Power Mangement Controller (PMC) definitions | |
PMC_BASE EQU 0xFFFFFC00 ; PMC Base Address | |
PMC_MOR EQU 0x20 ; PMC_MOR Offset | |
PMC_MCFR EQU 0x24 ; PMC_MCFR Offset | |
PMC_PLLR EQU 0x2C ; PMC_PLLR Offset | |
PMC_MCKR EQU 0x30 ; PMC_MCKR Offset | |
PMC_SR EQU 0x68 ; PMC_SR Offset | |
PMC_MOSCEN EQU (1<<0) ; Main Oscillator Enable | |
PMC_OSCBYPASS EQU (1<<1) ; Main Oscillator Bypass | |
PMC_OSCOUNT EQU (0xFF<<8) ; Main OScillator Start-up Time | |
PMC_DIV EQU (0xFF<<0) ; PLL Divider | |
PMC_PLLCOUNT EQU (0x3F<<8) ; PLL Lock Counter | |
PMC_OUT EQU (0x03<<14) ; PLL Clock Frequency Range | |
PMC_MUL EQU (0x7FF<<16) ; PLL Multiplier | |
PMC_USBDIV EQU (0x03<<28) ; USB Clock Divider | |
PMC_CSS EQU (3<<0) ; Clock Source Selection | |
PMC_PRES EQU (7<<2) ; Prescaler Selection | |
PMC_MOSCS EQU (1<<0) ; Main Oscillator Stable | |
PMC_LOCK EQU (1<<2) ; PLL Lock Status | |
PMC_MCKRDY EQU (1<<3) ; Master Clock Status | |
;// <e> Power Mangement Controller (PMC) | |
;// <h> Main Oscillator | |
;// <o1.0> MOSCEN: Main Oscillator Enable | |
;// <o1.1> OSCBYPASS: Oscillator Bypass | |
;// <o1.8..15> OSCCOUNT: Main Oscillator Startup Time <0-255> | |
;// </h> | |
;// <h> Phase Locked Loop (PLL) | |
;// <o2.0..7> DIV: PLL Divider <0-255> | |
;// <o2.16..26> MUL: PLL Multiplier <0-2047> | |
;// <i> PLL Output is multiplied by MUL+1 | |
;// <o2.14..15> OUT: PLL Clock Frequency Range | |
;// <0=> 80..160MHz <1=> Reserved | |
;// <2=> 150..220MHz <3=> Reserved | |
;// <o2.8..13> PLLCOUNT: PLL Lock Counter <0-63> | |
;// <o2.28..29> USBDIV: USB Clock Divider | |
;// <0=> None <1=> 2 <2=> 4 <3=> Reserved | |
;// </h> | |
;// <o3.0..1> CSS: Clock Source Selection | |
;// <0=> Slow Clock | |
;// <1=> Main Clock | |
;// <2=> Reserved | |
;// <3=> PLL Clock | |
;// <o3.2..4> PRES: Prescaler | |
;// <0=> None | |
;// <1=> Clock / 2 <2=> Clock / 4 | |
;// <3=> Clock / 8 <4=> Clock / 16 | |
;// <5=> Clock / 32 <6=> Clock / 64 | |
;// <7=> Reserved | |
;// </e> | |
PMC_SETUP EQU 1 | |
PMC_MOR_Val EQU 0x00000601 | |
PMC_PLLR_Val EQU 0x00191C05 | |
PMC_MCKR_Val EQU 0x00000007 | |
PRESERVE8 | |
; Area Definition and Entry Point | |
; Startup Code must be linked first at Address at which it expects to run. | |
AREA RESET, CODE, READONLY | |
ARM | |
; Exception Vectors | |
; Mapped to Address 0. | |
; Absolute addressing mode must be used. | |
; Dummy Handlers are implemented as infinite loops which can be modified. | |
Vectors LDR PC,Reset_Addr | |
LDR PC,Undef_Addr | |
LDR PC,SWI_Addr | |
LDR PC,PAbt_Addr | |
LDR PC,DAbt_Addr | |
NOP ; Reserved Vector | |
; LDR PC,IRQ_Addr | |
IRQ_Handler B irqhandler | |
; LDR PC,FIQ_Addr | |
LDR PC,[PC,#-0xF20] ; Vector From AIC_FVR | |
Reset_Addr DCD Reset_Handler | |
Undef_Addr DCD Undef_Handler | |
SWI_Addr DCD SWI_Handler | |
PAbt_Addr DCD PAbt_Handler | |
DAbt_Addr DCD DAbt_Handler | |
DCD 0 ; Reserved Address | |
FIQ_Addr DCD FIQ_Handler | |
Undef_Handler B Undef_Handler | |
SWI_Handler B SWI_Handler | |
PAbt_Handler B PAbt_Handler | |
DAbt_Handler B DAbt_Handler | |
FIQ_Handler B FIQ_Handler | |
AT91C_BASE_AIC EQU 0xFFFFF000 | |
AIC_IVR EQU 0x100 | |
AIC_EOICR EQU 0x130 | |
irqhandler | |
; Save interrupt context on the stack to allow nesting */ | |
SUB lr, lr, #4 | |
STMFD sp!, {lr} | |
MRS lr, SPSR | |
STMFD sp!, {r0,r1,lr} | |
; Write in the IVR to support Protect Mode */ | |
LDR lr, =AT91C_BASE_AIC | |
LDR r0, [r14, #AIC_IVR] | |
STR lr, [r14, #AIC_IVR] | |
; Branch to interrupt handler in Supervisor mode */ | |
MSR CPSR_c, #Mode_SVC | |
STMFD sp!, {r1-r4, r12, lr} | |
MOV lr, pc | |
BX r0 | |
LDMIA sp!, {r1-r4, r12, lr} | |
MSR CPSR_c, #Mode_IRQ:OR:I_Bit | |
; Acknowledge interrupt */ | |
LDR lr, =AT91C_BASE_AIC | |
STR lr, [r14, #AIC_EOICR] | |
; Restore interrupt context and branch back to calling code | |
LDMIA sp!, {r0,r1,lr} | |
MSR SPSR_cxsf, lr | |
LDMIA sp!, {pc}^ | |
; irqhandler (end) | |
; Reset Handler | |
EXPORT Reset_Handler | |
Reset_Handler | |
; Setup RSTC | |
IF RSTC_SETUP != 0 | |
LDR R0, =RSTC_BASE | |
LDR R1, =RSTC_MR_Val | |
STR R1, [R0, #RSTC_MR] | |
ENDIF | |
; Setup EFC0 | |
IF EFC0_SETUP != 0 | |
LDR R0, =EFC_BASE | |
LDR R1, =EFC0_FMR_Val | |
STR R1, [R0, #EFC0_FMR] | |
ENDIF | |
; Setup EFC1 | |
IF EFC1_SETUP != 0 | |
LDR R0, =EFC_BASE | |
LDR R1, =EFC1_FMR_Val | |
STR R1, [R0, #EFC1_FMR] | |
ENDIF | |
; Setup WDT | |
IF WDT_SETUP != 0 | |
LDR R0, =WDT_BASE | |
LDR R1, =WDT_MR_Val | |
STR R1, [R0, #WDT_MR] | |
ENDIF | |
; Setup PMC | |
IF PMC_SETUP != 0 | |
LDR R0, =PMC_BASE | |
; Setup Main Oscillator | |
LDR R1, =PMC_MOR_Val | |
STR R1, [R0, #PMC_MOR] | |
; Wait until Main Oscillator is stablilized | |
IF (PMC_MOR_Val:AND:PMC_MOSCEN) != 0 | |
MOSCS_Loop LDR R2, [R0, #PMC_SR] | |
ANDS R2, R2, #PMC_MOSCS | |
BEQ MOSCS_Loop | |
ENDIF | |
; Setup the PLL | |
IF (PMC_PLLR_Val:AND:PMC_MUL) != 0 | |
LDR R1, =PMC_PLLR_Val | |
STR R1, [R0, #PMC_PLLR] | |
; Wait until PLL is stabilized | |
PLL_Loop LDR R2, [R0, #PMC_SR] | |
ANDS R2, R2, #PMC_LOCK | |
BEQ PLL_Loop | |
ENDIF | |
; Select Clock | |
IF (PMC_MCKR_Val:AND:PMC_CSS) == 1 ; Main Clock Selected | |
LDR R1, =PMC_MCKR_Val | |
AND R1, #PMC_CSS | |
STR R1, [R0, #PMC_MCKR] | |
WAIT_Rdy1 LDR R2, [R0, #PMC_SR] | |
ANDS R2, R2, #PMC_MCKRDY | |
BEQ WAIT_Rdy1 | |
LDR R1, =PMC_MCKR_Val | |
STR R1, [R0, #PMC_MCKR] | |
WAIT_Rdy2 LDR R2, [R0, #PMC_SR] | |
ANDS R2, R2, #PMC_MCKRDY | |
BEQ WAIT_Rdy2 | |
ELIF (PMC_MCKR_Val:AND:PMC_CSS) == 3 ; PLL Clock Selected | |
LDR R1, =PMC_MCKR_Val | |
AND R1, #PMC_PRES | |
STR R1, [R0, #PMC_MCKR] | |
WAIT_Rdy1 LDR R2, [R0, #PMC_SR] | |
ANDS R2, R2, #PMC_MCKRDY | |
BEQ WAIT_Rdy1 | |
LDR R1, =PMC_MCKR_Val | |
STR R1, [R0, #PMC_MCKR] | |
WAIT_Rdy2 LDR R2, [R0, #PMC_SR] | |
ANDS R2, R2, #PMC_MCKRDY | |
BEQ WAIT_Rdy2 | |
ENDIF ; Select Clock | |
ENDIF ; PMC_SETUP | |
; Copy Exception Vectors to Internal RAM | |
IF :DEF:RAM_INTVEC | |
ADR R8, Vectors ; Source | |
LDR R9, =RAM_BASE ; Destination | |
LDMIA R8!, {R0-R7} ; Load Vectors | |
STMIA R9!, {R0-R7} ; Store Vectors | |
LDMIA R8!, {R0-R7} ; Load Handler Addresses | |
STMIA R9!, {R0-R7} ; Store Handler Addresses | |
ENDIF | |
; Remap on-chip RAM to address 0 | |
MC_BASE EQU 0xFFFFFF00 ; MC Base Address | |
MC_RCR EQU 0x00 ; MC_RCR Offset | |
IF :DEF:REMAP | |
LDR R0, =MC_BASE | |
MOV R1, #1 | |
STR R1, [R0, #MC_RCR] ; Remap | |
ENDIF | |
; Setup Stack for each mode | |
LDR R0, =Stack_Top | |
; Enter Undefined Instruction Mode and set its Stack Pointer | |
MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit | |
MOV SP, R0 | |
SUB R0, R0, #UND_Stack_Size | |
; Enter Abort Mode and set its Stack Pointer | |
MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit | |
MOV SP, R0 | |
SUB R0, R0, #ABT_Stack_Size | |
; Enter FIQ Mode and set its Stack Pointer | |
MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit | |
MOV SP, R0 | |
SUB R0, R0, #FIQ_Stack_Size | |
; Enter IRQ Mode and set its Stack Pointer | |
MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit | |
MOV SP, R0 | |
SUB R0, R0, #IRQ_Stack_Size | |
; Enter Supervisor Mode and set its Stack Pointer | |
MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit | |
MOV SP, R0 | |
SUB R0, R0, #SVC_Stack_Size | |
; Enter User Mode and set its Stack Pointer | |
MSR CPSR_c, #Mode_USR | |
IF :DEF:__MICROLIB | |
EXPORT __initial_sp | |
ELSE | |
MOV SP, R0 | |
SUB SL, SP, #USR_Stack_Size | |
ENDIF | |
; Enter the C code | |
IMPORT __main | |
LDR R0, =__main | |
BX R0 | |
IF :DEF:__MICROLIB | |
EXPORT __heap_base | |
EXPORT __heap_limit | |
ELSE | |
; User Initial Stack & Heap | |
AREA |.text|, CODE, READONLY | |
IMPORT __use_two_region_memory | |
EXPORT __user_initial_stackheap | |
__user_initial_stackheap | |
LDR R0, = Heap_Mem | |
LDR R1, =(Stack_Mem + USR_Stack_Size) | |
LDR R2, = (Heap_Mem + Heap_Size) | |
LDR R3, = Stack_Mem | |
BX LR | |
ENDIF | |
END |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment