| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 | ;/*****************************************************************************/;/* 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 PSRsMode_USR        EQU     0x10Mode_FIQ        EQU     0x11Mode_IRQ        EQU     0x12Mode_SVC        EQU     0x13Mode_ABT        EQU     0x17Mode_UND        EQU     0x1BMode_SYS        EQU     0x1FI_Bit           EQU     0x80            ; when I bit is set, IRQ is disabledF_Bit           EQU     0x40            ; when F bit is set, FIQ is disabled; Internal Memory Base AddressesFLASH_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     0x00000000SVC_Stack_Size  EQU     0x00000100ABT_Stack_Size  EQU     0x00000000FIQ_Stack_Size  EQU     0x00000000IRQ_Stack_Size  EQU     0x00000100USR_Stack_Size  EQU     0x00000100ISR_Stack_Size  EQU     (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \                         FIQ_Stack_Size + IRQ_Stack_Size)                AREA    STACK, NOINIT, READWRITE, ALIGN=3Stack_Mem       SPACE   USR_Stack_Size__initial_sp    SPACE   ISR_Stack_SizeStack_Top;// <h> Heap Configuration;//   <o>  Heap Size (in Bytes) <0x0-0xFFFFFFFF>;// </h>Heap_Size       EQU     0x00000000                AREA    HEAP, NOINIT, READWRITE, ALIGN=3__heap_baseHeap_Mem        SPACE   Heap_Size__heap_limit; Reset Controller (RSTC) definitionsRSTC_BASE       EQU     0xFFFFFD00      ; RSTC Base AddressRSTC_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     1RSTC_MR_Val     EQU     0xA5000401; Embedded Flash Controller (EFC) definitionsEFC_BASE        EQU     0xFFFFFF00      ; EFC Base AddressEFC0_FMR        EQU     0x60            ; EFC0_FMR OffsetEFC1_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     1EFC0_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     0EFC1_FMR_Val    EQU     0x00320100; Watchdog Timer (WDT) definitionsWDT_BASE        EQU     0xFFFFFD40      ; WDT Base AddressWDT_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     1WDT_MR_Val      EQU     0x00008000; Power Mangement Controller (PMC) definitionsPMC_BASE        EQU     0xFFFFFC00      ; PMC Base AddressPMC_MOR         EQU     0x20            ; PMC_MOR OffsetPMC_MCFR        EQU     0x24            ; PMC_MCFR OffsetPMC_PLLR        EQU     0x2C            ; PMC_PLLR OffsetPMC_MCKR        EQU     0x30            ; PMC_MCKR OffsetPMC_SR          EQU     0x68            ; PMC_SR OffsetPMC_MOSCEN      EQU     (1<<0)          ; Main Oscillator EnablePMC_OSCBYPASS   EQU     (1<<1)          ; Main Oscillator BypassPMC_OSCOUNT     EQU     (0xFF<<8)       ; Main OScillator Start-up TimePMC_DIV         EQU     (0xFF<<0)       ; PLL DividerPMC_PLLCOUNT    EQU     (0x3F<<8)       ; PLL Lock CounterPMC_OUT         EQU     (0x03<<14)      ; PLL Clock Frequency RangePMC_MUL         EQU     (0x7FF<<16)     ; PLL MultiplierPMC_USBDIV      EQU     (0x03<<28)      ; USB Clock DividerPMC_CSS         EQU     (3<<0)          ; Clock Source SelectionPMC_PRES        EQU     (7<<2)          ; Prescaler SelectionPMC_MOSCS       EQU     (1<<0)          ; Main Oscillator StablePMC_LOCK        EQU     (1<<2)          ; PLL Lock StatusPMC_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     1PMC_MOR_Val     EQU     0x00000601PMC_PLLR_Val    EQU     0x00191C05PMC_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                LDR     PC,FIQ_AddrReset_Addr      DCD     Reset_HandlerUndef_Addr      DCD     Undef_HandlerSWI_Addr        DCD     SWI_HandlerPAbt_Addr       DCD     PAbt_HandlerDAbt_Addr       DCD     DAbt_Handler                DCD     0                      ; Reserved AddressIRQ_Addr        DCD     IRQ_HandlerFIQ_Addr        DCD     FIQ_HandlerUndef_Handler   B       Undef_HandlerSWI_Handler     B       SWI_HandlerPAbt_Handler    B       PAbt_HandlerDAbt_Handler    B       DAbt_HandlerFIQ_Handler     B       FIQ_Handler; Reset Handler                EXPORT  Reset_HandlerReset_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) != 0MOSCS_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 stabilizedPLL_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 0MC_BASE EQU     0xFFFFFF00      ; MC Base AddressMC_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                ; No usr mode stack here.                ;MOV     SP, R0                ;SUB     SL, SP, #USR_Stack_Size                ENDIF; Enter the C code                IMPORT  __main                LDR     R0, =__main                BX      R0				IMPORT rt_interrupt_enter				IMPORT rt_interrupt_leave				IMPORT rt_thread_switch_interrupt_flag				IMPORT rt_interrupt_from_thread				IMPORT rt_interrupt_to_thread				IMPORT rt_hw_trap_irqIRQ_Handler		PROC				EXPORT IRQ_Handler				STMFD	sp!, {r0-r12,lr}				BL	rt_interrupt_enter				BL	rt_hw_trap_irq				BL	rt_interrupt_leave				; if rt_thread_switch_interrupt_flag set, jump to				; rt_hw_context_switch_interrupt_do and don't return				LDR	r0, =rt_thread_switch_interrupt_flag				LDR	r1, [r0]				CMP	r1, #1				BEQ	rt_hw_context_switch_interrupt_do				LDMFD	sp!, {r0-r12,lr}				SUBS	pc, lr, #4				ENDP; /*; * void rt_hw_context_switch_interrupt_do(rt_base_t flag); */rt_hw_context_switch_interrupt_do	PROC				EXPORT rt_hw_context_switch_interrupt_do				MOV		r1,  #0			; clear flag				STR		r1,  [r0]				LDMFD	sp!, {r0-r12,lr}; reload saved registers				STMFD	sp!, {r0-r3}	; save r0-r3				MOV		r1,  sp				ADD		sp,  sp, #16	; restore sp				SUB		r2,  lr, #4		; save old task's pc to r2				MRS		r3,  spsr		; get cpsr of interrupt thread				; switch to SVC mode and no interrupt                MSR     cpsr_c, #I_Bit|F_Bit|Mode_SVC				STMFD	sp!, {r2}		; push old task's pc				STMFD	sp!, {r4-r12,lr}; push old task's lr,r12-r4				MOV		r4,  r1			; Special optimised code below				MOV		r5,  r3				LDMFD	r4!, {r0-r3}				STMFD	sp!, {r0-r3}	; push old task's r3-r0				STMFD	sp!, {r5}		; push old task's cpsr				MRS		r4,  spsr				STMFD	sp!, {r4}		; push old task's spsr				LDR		r4,  =rt_interrupt_from_thread				LDR		r5,  [r4]				STR		sp,  [r5]		; store sp in preempted tasks's TCB				LDR		r6,  =rt_interrupt_to_thread				LDR		r6,  [r6]				LDR		sp,  [r6]		; get new task's stack pointer							LDMFD	sp!, {r4}		; pop new task's spsr				MSR		spsr_cxsf, r4				LDMFD	sp!, {r4}		; pop new task's psr				MSR		cpsr_cxsf, r4				LDMFD	sp!, {r0-r12,lr,pc}	; pop new task's r0-r12,lr & pc				ENDP                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 + IRQ_Stack_Size)                LDR     R2, = (Heap_Mem +      Heap_Size)                LDR     R3, = Stack_Mem                BX      LR                ENDIF                END
 |