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