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