1*10465441SEvalZero;/*****************************************************************************/ 2*10465441SEvalZero;/* SAM7.S: Startup file for Atmel AT91SAM7 device series */ 3*10465441SEvalZero;/*****************************************************************************/ 4*10465441SEvalZero;/* <<< Use Configuration Wizard in Context Menu >>> */ 5*10465441SEvalZero;/*****************************************************************************/ 6*10465441SEvalZero;/* This file is part of the uVision/ARM development tools. */ 7*10465441SEvalZero;/* Copyright (c) 2005-2006 Keil Software. All rights reserved. */ 8*10465441SEvalZero;/* This software may only be used under the terms of a valid, current, */ 9*10465441SEvalZero;/* end user licence from KEIL for a compatible version of KEIL software */ 10*10465441SEvalZero;/* development tools. Nothing else gives you the right to use this software. */ 11*10465441SEvalZero;/*****************************************************************************/ 12*10465441SEvalZero 13*10465441SEvalZero 14*10465441SEvalZero;/* 15*10465441SEvalZero; * The SAM7.S code is executed after CPU Reset. This file may be 16*10465441SEvalZero; * translated with the following SET symbols. In uVision these SET 17*10465441SEvalZero; * symbols are entered under Options - ASM - Define. 18*10465441SEvalZero; * 19*10465441SEvalZero; * REMAP: when set the startup code remaps exception vectors from 20*10465441SEvalZero; * on-chip RAM to address 0. 21*10465441SEvalZero; * 22*10465441SEvalZero; * RAM_INTVEC: when set the startup code copies exception vectors 23*10465441SEvalZero; * from on-chip Flash to on-chip RAM. 24*10465441SEvalZero; */ 25*10465441SEvalZero 26*10465441SEvalZero 27*10465441SEvalZero; Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs 28*10465441SEvalZero 29*10465441SEvalZeroMode_USR EQU 0x10 30*10465441SEvalZeroMode_FIQ EQU 0x11 31*10465441SEvalZeroMode_IRQ EQU 0x12 32*10465441SEvalZeroMode_SVC EQU 0x13 33*10465441SEvalZeroMode_ABT EQU 0x17 34*10465441SEvalZeroMode_UND EQU 0x1B 35*10465441SEvalZeroMode_SYS EQU 0x1F 36*10465441SEvalZero 37*10465441SEvalZeroI_Bit EQU 0x80 ; when I bit is set, IRQ is disabled 38*10465441SEvalZeroF_Bit EQU 0x40 ; when F bit is set, FIQ is disabled 39*10465441SEvalZero 40*10465441SEvalZero 41*10465441SEvalZero; Internal Memory Base Addresses 42*10465441SEvalZeroFLASH_BASE EQU 0x00100000 43*10465441SEvalZeroRAM_BASE EQU 0x00200000 44*10465441SEvalZero 45*10465441SEvalZero 46*10465441SEvalZero;// <h> Stack Configuration (Stack Sizes in Bytes) 47*10465441SEvalZero;// <o0> Undefined Mode <0x0-0xFFFFFFFF:8> 48*10465441SEvalZero;// <o1> Supervisor Mode <0x0-0xFFFFFFFF:8> 49*10465441SEvalZero;// <o2> Abort Mode <0x0-0xFFFFFFFF:8> 50*10465441SEvalZero;// <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:8> 51*10465441SEvalZero;// <o4> Interrupt Mode <0x0-0xFFFFFFFF:8> 52*10465441SEvalZero;// <o5> User/System Mode <0x0-0xFFFFFFFF:8> 53*10465441SEvalZero;// </h> 54*10465441SEvalZero 55*10465441SEvalZeroUND_Stack_Size EQU 0x00000000 56*10465441SEvalZeroSVC_Stack_Size EQU 0x00000100 57*10465441SEvalZeroABT_Stack_Size EQU 0x00000000 58*10465441SEvalZeroFIQ_Stack_Size EQU 0x00000000 59*10465441SEvalZeroIRQ_Stack_Size EQU 0x00000100 60*10465441SEvalZeroUSR_Stack_Size EQU 0x00000100 61*10465441SEvalZero 62*10465441SEvalZeroISR_Stack_Size EQU (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + \ 63*10465441SEvalZero FIQ_Stack_Size + IRQ_Stack_Size) 64*10465441SEvalZero 65*10465441SEvalZero AREA STACK, NOINIT, READWRITE, ALIGN=3 66*10465441SEvalZero 67*10465441SEvalZeroStack_Mem SPACE USR_Stack_Size 68*10465441SEvalZero__initial_sp SPACE ISR_Stack_Size 69*10465441SEvalZeroStack_Top 70*10465441SEvalZero 71*10465441SEvalZero 72*10465441SEvalZero;// <h> Heap Configuration 73*10465441SEvalZero;// <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF> 74*10465441SEvalZero;// </h> 75*10465441SEvalZero 76*10465441SEvalZeroHeap_Size EQU 0x00000000 77*10465441SEvalZero 78*10465441SEvalZero AREA HEAP, NOINIT, READWRITE, ALIGN=3 79*10465441SEvalZero__heap_base 80*10465441SEvalZeroHeap_Mem SPACE Heap_Size 81*10465441SEvalZero__heap_limit 82*10465441SEvalZero 83*10465441SEvalZero 84*10465441SEvalZero; Reset Controller (RSTC) definitions 85*10465441SEvalZeroRSTC_BASE EQU 0xFFFFFD00 ; RSTC Base Address 86*10465441SEvalZeroRSTC_MR EQU 0x08 ; RSTC_MR Offset 87*10465441SEvalZero 88*10465441SEvalZero;/* 89*10465441SEvalZero;// <e> Reset Controller (RSTC) 90*10465441SEvalZero;// <o1.0> URSTEN: User Reset Enable 91*10465441SEvalZero;// <i> Enables NRST Pin to generate Reset 92*10465441SEvalZero;// <o1.8..11> ERSTL: External Reset Length <0-15> 93*10465441SEvalZero;// <i> External Reset Time in 2^(ERSTL+1) Slow Clock Cycles 94*10465441SEvalZero;// </e> 95*10465441SEvalZero;*/ 96*10465441SEvalZeroRSTC_SETUP EQU 1 97*10465441SEvalZeroRSTC_MR_Val EQU 0xA5000401 98*10465441SEvalZero 99*10465441SEvalZero 100*10465441SEvalZero; Embedded Flash Controller (EFC) definitions 101*10465441SEvalZeroEFC_BASE EQU 0xFFFFFF00 ; EFC Base Address 102*10465441SEvalZeroEFC0_FMR EQU 0x60 ; EFC0_FMR Offset 103*10465441SEvalZeroEFC1_FMR EQU 0x70 ; EFC1_FMR Offset 104*10465441SEvalZero 105*10465441SEvalZero;// <e> Embedded Flash Controller 0 (EFC0) 106*10465441SEvalZero;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255> 107*10465441SEvalZero;// <i> Number of Master Clock Cycles in 1us 108*10465441SEvalZero;// <o1.8..9> FWS: Flash Wait State 109*10465441SEvalZero;// <0=> Read: 1 cycle / Write: 2 cycles 110*10465441SEvalZero;// <1=> Read: 2 cycle / Write: 3 cycles 111*10465441SEvalZero;// <2=> Read: 3 cycle / Write: 4 cycles 112*10465441SEvalZero;// <3=> Read: 4 cycle / Write: 4 cycles 113*10465441SEvalZero;// </e> 114*10465441SEvalZeroEFC0_SETUP EQU 1 115*10465441SEvalZeroEFC0_FMR_Val EQU 0x00320100 116*10465441SEvalZero 117*10465441SEvalZero;// <e> Embedded Flash Controller 1 (EFC1) 118*10465441SEvalZero;// <o1.16..23> FMCN: Flash Microsecond Cycle Number <0-255> 119*10465441SEvalZero;// <i> Number of Master Clock Cycles in 1us 120*10465441SEvalZero;// <o1.8..9> FWS: Flash Wait State 121*10465441SEvalZero;// <0=> Read: 1 cycle / Write: 2 cycles 122*10465441SEvalZero;// <1=> Read: 2 cycle / Write: 3 cycles 123*10465441SEvalZero;// <2=> Read: 3 cycle / Write: 4 cycles 124*10465441SEvalZero;// <3=> Read: 4 cycle / Write: 4 cycles 125*10465441SEvalZero;// </e> 126*10465441SEvalZeroEFC1_SETUP EQU 0 127*10465441SEvalZeroEFC1_FMR_Val EQU 0x00320100 128*10465441SEvalZero 129*10465441SEvalZero 130*10465441SEvalZero; Watchdog Timer (WDT) definitions 131*10465441SEvalZeroWDT_BASE EQU 0xFFFFFD40 ; WDT Base Address 132*10465441SEvalZeroWDT_MR EQU 0x04 ; WDT_MR Offset 133*10465441SEvalZero 134*10465441SEvalZero;// <e> Watchdog Timer (WDT) 135*10465441SEvalZero;// <o1.0..11> WDV: Watchdog Counter Value <0-4095> 136*10465441SEvalZero;// <o1.16..27> WDD: Watchdog Delta Value <0-4095> 137*10465441SEvalZero;// <o1.12> WDFIEN: Watchdog Fault Interrupt Enable 138*10465441SEvalZero;// <o1.13> WDRSTEN: Watchdog Reset Enable 139*10465441SEvalZero;// <o1.14> WDRPROC: Watchdog Reset Processor 140*10465441SEvalZero;// <o1.28> WDDBGHLT: Watchdog Debug Halt 141*10465441SEvalZero;// <o1.29> WDIDLEHLT: Watchdog Idle Halt 142*10465441SEvalZero;// <o1.15> WDDIS: Watchdog Disable 143*10465441SEvalZero;// </e> 144*10465441SEvalZeroWDT_SETUP EQU 1 145*10465441SEvalZeroWDT_MR_Val EQU 0x00008000 146*10465441SEvalZero 147*10465441SEvalZero 148*10465441SEvalZero; Power Mangement Controller (PMC) definitions 149*10465441SEvalZeroPMC_BASE EQU 0xFFFFFC00 ; PMC Base Address 150*10465441SEvalZeroPMC_MOR EQU 0x20 ; PMC_MOR Offset 151*10465441SEvalZeroPMC_MCFR EQU 0x24 ; PMC_MCFR Offset 152*10465441SEvalZeroPMC_PLLR EQU 0x2C ; PMC_PLLR Offset 153*10465441SEvalZeroPMC_MCKR EQU 0x30 ; PMC_MCKR Offset 154*10465441SEvalZeroPMC_SR EQU 0x68 ; PMC_SR Offset 155*10465441SEvalZeroPMC_MOSCEN EQU (1<<0) ; Main Oscillator Enable 156*10465441SEvalZeroPMC_OSCBYPASS EQU (1<<1) ; Main Oscillator Bypass 157*10465441SEvalZeroPMC_OSCOUNT EQU (0xFF<<8) ; Main OScillator Start-up Time 158*10465441SEvalZeroPMC_DIV EQU (0xFF<<0) ; PLL Divider 159*10465441SEvalZeroPMC_PLLCOUNT EQU (0x3F<<8) ; PLL Lock Counter 160*10465441SEvalZeroPMC_OUT EQU (0x03<<14) ; PLL Clock Frequency Range 161*10465441SEvalZeroPMC_MUL EQU (0x7FF<<16) ; PLL Multiplier 162*10465441SEvalZeroPMC_USBDIV EQU (0x03<<28) ; USB Clock Divider 163*10465441SEvalZeroPMC_CSS EQU (3<<0) ; Clock Source Selection 164*10465441SEvalZeroPMC_PRES EQU (7<<2) ; Prescaler Selection 165*10465441SEvalZeroPMC_MOSCS EQU (1<<0) ; Main Oscillator Stable 166*10465441SEvalZeroPMC_LOCK EQU (1<<2) ; PLL Lock Status 167*10465441SEvalZeroPMC_MCKRDY EQU (1<<3) ; Master Clock Status 168*10465441SEvalZero 169*10465441SEvalZero;// <e> Power Mangement Controller (PMC) 170*10465441SEvalZero;// <h> Main Oscillator 171*10465441SEvalZero;// <o1.0> MOSCEN: Main Oscillator Enable 172*10465441SEvalZero;// <o1.1> OSCBYPASS: Oscillator Bypass 173*10465441SEvalZero;// <o1.8..15> OSCCOUNT: Main Oscillator Startup Time <0-255> 174*10465441SEvalZero;// </h> 175*10465441SEvalZero;// <h> Phase Locked Loop (PLL) 176*10465441SEvalZero;// <o2.0..7> DIV: PLL Divider <0-255> 177*10465441SEvalZero;// <o2.16..26> MUL: PLL Multiplier <0-2047> 178*10465441SEvalZero;// <i> PLL Output is multiplied by MUL+1 179*10465441SEvalZero;// <o2.14..15> OUT: PLL Clock Frequency Range 180*10465441SEvalZero;// <0=> 80..160MHz <1=> Reserved 181*10465441SEvalZero;// <2=> 150..220MHz <3=> Reserved 182*10465441SEvalZero;// <o2.8..13> PLLCOUNT: PLL Lock Counter <0-63> 183*10465441SEvalZero;// <o2.28..29> USBDIV: USB Clock Divider 184*10465441SEvalZero;// <0=> None <1=> 2 <2=> 4 <3=> Reserved 185*10465441SEvalZero;// </h> 186*10465441SEvalZero;// <o3.0..1> CSS: Clock Source Selection 187*10465441SEvalZero;// <0=> Slow Clock 188*10465441SEvalZero;// <1=> Main Clock 189*10465441SEvalZero;// <2=> Reserved 190*10465441SEvalZero;// <3=> PLL Clock 191*10465441SEvalZero;// <o3.2..4> PRES: Prescaler 192*10465441SEvalZero;// <0=> None 193*10465441SEvalZero;// <1=> Clock / 2 <2=> Clock / 4 194*10465441SEvalZero;// <3=> Clock / 8 <4=> Clock / 16 195*10465441SEvalZero;// <5=> Clock / 32 <6=> Clock / 64 196*10465441SEvalZero;// <7=> Reserved 197*10465441SEvalZero;// </e> 198*10465441SEvalZeroPMC_SETUP EQU 1 199*10465441SEvalZeroPMC_MOR_Val EQU 0x00000601 200*10465441SEvalZeroPMC_PLLR_Val EQU 0x00191C05 201*10465441SEvalZeroPMC_MCKR_Val EQU 0x00000007 202*10465441SEvalZero 203*10465441SEvalZero 204*10465441SEvalZero PRESERVE8 205*10465441SEvalZero 206*10465441SEvalZero 207*10465441SEvalZero; Area Definition and Entry Point 208*10465441SEvalZero; Startup Code must be linked first at Address at which it expects to run. 209*10465441SEvalZero 210*10465441SEvalZero AREA RESET, CODE, READONLY 211*10465441SEvalZero ARM 212*10465441SEvalZero 213*10465441SEvalZero 214*10465441SEvalZero; Exception Vectors 215*10465441SEvalZero; Mapped to Address 0. 216*10465441SEvalZero; Absolute addressing mode must be used. 217*10465441SEvalZero; Dummy Handlers are implemented as infinite loops which can be modified. 218*10465441SEvalZero 219*10465441SEvalZeroVectors LDR PC,Reset_Addr 220*10465441SEvalZero LDR PC,Undef_Addr 221*10465441SEvalZero LDR PC,SWI_Addr 222*10465441SEvalZero LDR PC,PAbt_Addr 223*10465441SEvalZero LDR PC,DAbt_Addr 224*10465441SEvalZero NOP ; Reserved Vector 225*10465441SEvalZero LDR PC,IRQ_Addr 226*10465441SEvalZero LDR PC,FIQ_Addr 227*10465441SEvalZero 228*10465441SEvalZeroReset_Addr DCD Reset_Handler 229*10465441SEvalZeroUndef_Addr DCD Undef_Handler 230*10465441SEvalZeroSWI_Addr DCD SWI_Handler 231*10465441SEvalZeroPAbt_Addr DCD PAbt_Handler 232*10465441SEvalZeroDAbt_Addr DCD DAbt_Handler 233*10465441SEvalZero DCD 0 ; Reserved Address 234*10465441SEvalZeroIRQ_Addr DCD IRQ_Handler 235*10465441SEvalZeroFIQ_Addr DCD FIQ_Handler 236*10465441SEvalZero 237*10465441SEvalZeroUndef_Handler B Undef_Handler 238*10465441SEvalZeroSWI_Handler B SWI_Handler 239*10465441SEvalZeroPAbt_Handler B PAbt_Handler 240*10465441SEvalZeroDAbt_Handler B DAbt_Handler 241*10465441SEvalZeroFIQ_Handler B FIQ_Handler 242*10465441SEvalZero 243*10465441SEvalZero 244*10465441SEvalZero; Reset Handler 245*10465441SEvalZero 246*10465441SEvalZero EXPORT Reset_Handler 247*10465441SEvalZeroReset_Handler 248*10465441SEvalZero 249*10465441SEvalZero 250*10465441SEvalZero; Setup RSTC 251*10465441SEvalZero IF RSTC_SETUP != 0 252*10465441SEvalZero LDR R0, =RSTC_BASE 253*10465441SEvalZero LDR R1, =RSTC_MR_Val 254*10465441SEvalZero STR R1, [R0, #RSTC_MR] 255*10465441SEvalZero ENDIF 256*10465441SEvalZero 257*10465441SEvalZero 258*10465441SEvalZero; Setup EFC0 259*10465441SEvalZero IF EFC0_SETUP != 0 260*10465441SEvalZero LDR R0, =EFC_BASE 261*10465441SEvalZero LDR R1, =EFC0_FMR_Val 262*10465441SEvalZero STR R1, [R0, #EFC0_FMR] 263*10465441SEvalZero ENDIF 264*10465441SEvalZero 265*10465441SEvalZero; Setup EFC1 266*10465441SEvalZero IF EFC1_SETUP != 0 267*10465441SEvalZero LDR R0, =EFC_BASE 268*10465441SEvalZero LDR R1, =EFC1_FMR_Val 269*10465441SEvalZero STR R1, [R0, #EFC1_FMR] 270*10465441SEvalZero ENDIF 271*10465441SEvalZero 272*10465441SEvalZero; Setup WDT 273*10465441SEvalZero IF WDT_SETUP != 0 274*10465441SEvalZero LDR R0, =WDT_BASE 275*10465441SEvalZero LDR R1, =WDT_MR_Val 276*10465441SEvalZero STR R1, [R0, #WDT_MR] 277*10465441SEvalZero ENDIF 278*10465441SEvalZero 279*10465441SEvalZero 280*10465441SEvalZero; Setup PMC 281*10465441SEvalZero IF PMC_SETUP != 0 282*10465441SEvalZero LDR R0, =PMC_BASE 283*10465441SEvalZero 284*10465441SEvalZero; Setup Main Oscillator 285*10465441SEvalZero LDR R1, =PMC_MOR_Val 286*10465441SEvalZero STR R1, [R0, #PMC_MOR] 287*10465441SEvalZero 288*10465441SEvalZero; Wait until Main Oscillator is stablilized 289*10465441SEvalZero IF (PMC_MOR_Val:AND:PMC_MOSCEN) != 0 290*10465441SEvalZeroMOSCS_Loop LDR R2, [R0, #PMC_SR] 291*10465441SEvalZero ANDS R2, R2, #PMC_MOSCS 292*10465441SEvalZero BEQ MOSCS_Loop 293*10465441SEvalZero ENDIF 294*10465441SEvalZero 295*10465441SEvalZero; Setup the PLL 296*10465441SEvalZero IF (PMC_PLLR_Val:AND:PMC_MUL) != 0 297*10465441SEvalZero LDR R1, =PMC_PLLR_Val 298*10465441SEvalZero STR R1, [R0, #PMC_PLLR] 299*10465441SEvalZero 300*10465441SEvalZero; Wait until PLL is stabilized 301*10465441SEvalZeroPLL_Loop LDR R2, [R0, #PMC_SR] 302*10465441SEvalZero ANDS R2, R2, #PMC_LOCK 303*10465441SEvalZero BEQ PLL_Loop 304*10465441SEvalZero ENDIF 305*10465441SEvalZero 306*10465441SEvalZero; Select Clock 307*10465441SEvalZero IF (PMC_MCKR_Val:AND:PMC_CSS) == 1 ; Main Clock Selected 308*10465441SEvalZero LDR R1, =PMC_MCKR_Val 309*10465441SEvalZero AND R1, #PMC_CSS 310*10465441SEvalZero STR R1, [R0, #PMC_MCKR] 311*10465441SEvalZeroWAIT_Rdy1 LDR R2, [R0, #PMC_SR] 312*10465441SEvalZero ANDS R2, R2, #PMC_MCKRDY 313*10465441SEvalZero BEQ WAIT_Rdy1 314*10465441SEvalZero LDR R1, =PMC_MCKR_Val 315*10465441SEvalZero STR R1, [R0, #PMC_MCKR] 316*10465441SEvalZeroWAIT_Rdy2 LDR R2, [R0, #PMC_SR] 317*10465441SEvalZero ANDS R2, R2, #PMC_MCKRDY 318*10465441SEvalZero BEQ WAIT_Rdy2 319*10465441SEvalZero ELIF (PMC_MCKR_Val:AND:PMC_CSS) == 3 ; PLL Clock Selected 320*10465441SEvalZero LDR R1, =PMC_MCKR_Val 321*10465441SEvalZero AND R1, #PMC_PRES 322*10465441SEvalZero STR R1, [R0, #PMC_MCKR] 323*10465441SEvalZeroWAIT_Rdy1 LDR R2, [R0, #PMC_SR] 324*10465441SEvalZero ANDS R2, R2, #PMC_MCKRDY 325*10465441SEvalZero BEQ WAIT_Rdy1 326*10465441SEvalZero LDR R1, =PMC_MCKR_Val 327*10465441SEvalZero STR R1, [R0, #PMC_MCKR] 328*10465441SEvalZeroWAIT_Rdy2 LDR R2, [R0, #PMC_SR] 329*10465441SEvalZero ANDS R2, R2, #PMC_MCKRDY 330*10465441SEvalZero BEQ WAIT_Rdy2 331*10465441SEvalZero ENDIF ; Select Clock 332*10465441SEvalZero ENDIF ; PMC_SETUP 333*10465441SEvalZero 334*10465441SEvalZero 335*10465441SEvalZero; Copy Exception Vectors to Internal RAM 336*10465441SEvalZero 337*10465441SEvalZero IF :DEF:RAM_INTVEC 338*10465441SEvalZero ADR R8, Vectors ; Source 339*10465441SEvalZero LDR R9, =RAM_BASE ; Destination 340*10465441SEvalZero LDMIA R8!, {R0-R7} ; Load Vectors 341*10465441SEvalZero STMIA R9!, {R0-R7} ; Store Vectors 342*10465441SEvalZero LDMIA R8!, {R0-R7} ; Load Handler Addresses 343*10465441SEvalZero STMIA R9!, {R0-R7} ; Store Handler Addresses 344*10465441SEvalZero ENDIF 345*10465441SEvalZero 346*10465441SEvalZero 347*10465441SEvalZero; Remap on-chip RAM to address 0 348*10465441SEvalZero 349*10465441SEvalZeroMC_BASE EQU 0xFFFFFF00 ; MC Base Address 350*10465441SEvalZeroMC_RCR EQU 0x00 ; MC_RCR Offset 351*10465441SEvalZero 352*10465441SEvalZero IF :DEF:REMAP 353*10465441SEvalZero LDR R0, =MC_BASE 354*10465441SEvalZero MOV R1, #1 355*10465441SEvalZero STR R1, [R0, #MC_RCR] ; Remap 356*10465441SEvalZero ENDIF 357*10465441SEvalZero 358*10465441SEvalZero 359*10465441SEvalZero; Setup Stack for each mode 360*10465441SEvalZero 361*10465441SEvalZero LDR R0, =Stack_Top 362*10465441SEvalZero 363*10465441SEvalZero; Enter Undefined Instruction Mode and set its Stack Pointer 364*10465441SEvalZero MSR CPSR_c, #Mode_UND:OR:I_Bit:OR:F_Bit 365*10465441SEvalZero MOV SP, R0 366*10465441SEvalZero SUB R0, R0, #UND_Stack_Size 367*10465441SEvalZero 368*10465441SEvalZero; Enter Abort Mode and set its Stack Pointer 369*10465441SEvalZero MSR CPSR_c, #Mode_ABT:OR:I_Bit:OR:F_Bit 370*10465441SEvalZero MOV SP, R0 371*10465441SEvalZero SUB R0, R0, #ABT_Stack_Size 372*10465441SEvalZero 373*10465441SEvalZero; Enter FIQ Mode and set its Stack Pointer 374*10465441SEvalZero MSR CPSR_c, #Mode_FIQ:OR:I_Bit:OR:F_Bit 375*10465441SEvalZero MOV SP, R0 376*10465441SEvalZero SUB R0, R0, #FIQ_Stack_Size 377*10465441SEvalZero 378*10465441SEvalZero; Enter IRQ Mode and set its Stack Pointer 379*10465441SEvalZero MSR CPSR_c, #Mode_IRQ:OR:I_Bit:OR:F_Bit 380*10465441SEvalZero MOV SP, R0 381*10465441SEvalZero SUB R0, R0, #IRQ_Stack_Size 382*10465441SEvalZero 383*10465441SEvalZero; Enter Supervisor Mode and set its Stack Pointer 384*10465441SEvalZero MSR CPSR_c, #Mode_SVC:OR:I_Bit:OR:F_Bit 385*10465441SEvalZero MOV SP, R0 386*10465441SEvalZero SUB R0, R0, #SVC_Stack_Size 387*10465441SEvalZero 388*10465441SEvalZero; Enter User Mode and set its Stack Pointer 389*10465441SEvalZero ; MSR CPSR_c, #Mode_USR 390*10465441SEvalZero IF :DEF:__MICROLIB 391*10465441SEvalZero 392*10465441SEvalZero EXPORT __initial_sp 393*10465441SEvalZero 394*10465441SEvalZero ELSE 395*10465441SEvalZero 396*10465441SEvalZero ; No usr mode stack here. 397*10465441SEvalZero ;MOV SP, R0 398*10465441SEvalZero ;SUB SL, SP, #USR_Stack_Size 399*10465441SEvalZero 400*10465441SEvalZero ENDIF 401*10465441SEvalZero 402*10465441SEvalZero 403*10465441SEvalZero; Enter the C code 404*10465441SEvalZero 405*10465441SEvalZero IMPORT __main 406*10465441SEvalZero LDR R0, =__main 407*10465441SEvalZero BX R0 408*10465441SEvalZero 409*10465441SEvalZero IMPORT rt_interrupt_enter 410*10465441SEvalZero IMPORT rt_interrupt_leave 411*10465441SEvalZero IMPORT rt_thread_switch_interrupt_flag 412*10465441SEvalZero IMPORT rt_interrupt_from_thread 413*10465441SEvalZero IMPORT rt_interrupt_to_thread 414*10465441SEvalZero IMPORT rt_hw_trap_irq 415*10465441SEvalZero 416*10465441SEvalZeroIRQ_Handler PROC 417*10465441SEvalZero EXPORT IRQ_Handler 418*10465441SEvalZero STMFD sp!, {r0-r12,lr} 419*10465441SEvalZero BL rt_interrupt_enter 420*10465441SEvalZero BL rt_hw_trap_irq 421*10465441SEvalZero BL rt_interrupt_leave 422*10465441SEvalZero 423*10465441SEvalZero ; if rt_thread_switch_interrupt_flag set, jump to 424*10465441SEvalZero ; rt_hw_context_switch_interrupt_do and don't return 425*10465441SEvalZero LDR r0, =rt_thread_switch_interrupt_flag 426*10465441SEvalZero LDR r1, [r0] 427*10465441SEvalZero CMP r1, #1 428*10465441SEvalZero BEQ rt_hw_context_switch_interrupt_do 429*10465441SEvalZero 430*10465441SEvalZero LDMFD sp!, {r0-r12,lr} 431*10465441SEvalZero SUBS pc, lr, #4 432*10465441SEvalZero ENDP 433*10465441SEvalZero 434*10465441SEvalZero; /* 435*10465441SEvalZero; * void rt_hw_context_switch_interrupt_do(rt_base_t flag) 436*10465441SEvalZero; */ 437*10465441SEvalZerort_hw_context_switch_interrupt_do PROC 438*10465441SEvalZero EXPORT rt_hw_context_switch_interrupt_do 439*10465441SEvalZero MOV r1, #0 ; clear flag 440*10465441SEvalZero STR r1, [r0] 441*10465441SEvalZero 442*10465441SEvalZero LDMFD sp!, {r0-r12,lr}; reload saved registers 443*10465441SEvalZero STMFD sp!, {r0-r3} ; save r0-r3 444*10465441SEvalZero MOV r1, sp 445*10465441SEvalZero ADD sp, sp, #16 ; restore sp 446*10465441SEvalZero SUB r2, lr, #4 ; save old task's pc to r2 447*10465441SEvalZero 448*10465441SEvalZero MRS r3, spsr ; get cpsr of interrupt thread 449*10465441SEvalZero 450*10465441SEvalZero ; switch to SVC mode and no interrupt 451*10465441SEvalZero MSR cpsr_c, #I_Bit|F_Bit|Mode_SVC 452*10465441SEvalZero 453*10465441SEvalZero STMFD sp!, {r2} ; push old task's pc 454*10465441SEvalZero STMFD sp!, {r4-r12,lr}; push old task's lr,r12-r4 455*10465441SEvalZero MOV r4, r1 ; Special optimised code below 456*10465441SEvalZero MOV r5, r3 457*10465441SEvalZero LDMFD r4!, {r0-r3} 458*10465441SEvalZero STMFD sp!, {r0-r3} ; push old task's r3-r0 459*10465441SEvalZero STMFD sp!, {r5} ; push old task's cpsr 460*10465441SEvalZero MRS r4, spsr 461*10465441SEvalZero STMFD sp!, {r4} ; push old task's spsr 462*10465441SEvalZero 463*10465441SEvalZero LDR r4, =rt_interrupt_from_thread 464*10465441SEvalZero LDR r5, [r4] 465*10465441SEvalZero STR sp, [r5] ; store sp in preempted tasks's TCB 466*10465441SEvalZero 467*10465441SEvalZero LDR r6, =rt_interrupt_to_thread 468*10465441SEvalZero LDR r6, [r6] 469*10465441SEvalZero LDR sp, [r6] ; get new task's stack pointer 470*10465441SEvalZero 471*10465441SEvalZero LDMFD sp!, {r4} ; pop new task's spsr 472*10465441SEvalZero MSR spsr_cxsf, r4 473*10465441SEvalZero LDMFD sp!, {r4} ; pop new task's psr 474*10465441SEvalZero MSR cpsr_cxsf, r4 475*10465441SEvalZero 476*10465441SEvalZero LDMFD sp!, {r0-r12,lr,pc} ; pop new task's r0-r12,lr & pc 477*10465441SEvalZero ENDP 478*10465441SEvalZero 479*10465441SEvalZero IF :DEF:__MICROLIB 480*10465441SEvalZero 481*10465441SEvalZero EXPORT __heap_base 482*10465441SEvalZero EXPORT __heap_limit 483*10465441SEvalZero 484*10465441SEvalZero ELSE 485*10465441SEvalZero; User Initial Stack & Heap 486*10465441SEvalZero AREA |.text|, CODE, READONLY 487*10465441SEvalZero 488*10465441SEvalZero IMPORT __use_two_region_memory 489*10465441SEvalZero EXPORT __user_initial_stackheap 490*10465441SEvalZero__user_initial_stackheap 491*10465441SEvalZero 492*10465441SEvalZero LDR R0, = Heap_Mem 493*10465441SEvalZero LDR R1, = (Stack_Mem + IRQ_Stack_Size) 494*10465441SEvalZero LDR R2, = (Heap_Mem + Heap_Size) 495*10465441SEvalZero LDR R3, = Stack_Mem 496*10465441SEvalZero BX LR 497*10465441SEvalZero ENDIF 498*10465441SEvalZero 499*10465441SEvalZero END 500