#___________________________________startup.s______________________________________________________ # --------------------------------------------- # Include startup macros # --------------------------------------------- .include "source//startup_generic.s" .include "source//startup_philips.s" # --------------------------------------------- # Application specific constants # --------------------------------------------- # Stack definitions # size in words! .equ UND_Stack_Size , 4 .equ SVC_Stack_Size , 4 .equ ABT_Stack_Size , 4 .equ FIQ_Stack_Size , 10 .equ IRQ_Stack_Size , 50 .equ USR_Stack_Size , 64 # --------------------------------------------- # Hardware specific constants # --------------------------------------------- # Checksum, to avoid calling the bootloader after reset # must be adjusted by user! .equ CheckSum , 0xB9205F88 # --------------------------------------------- # Import external symbols # --------------------------------------------- # reference to main .extern main # reference to linker symbols .extern __data_start__ .extern __data_end__ .extern __bss_start__ .extern __bss_end__ .extern __bss2_start__ .extern __bss2_end__ # reference to external interrupt handlers .extern SWI_Handler .extern PAbt_Handler .extern DAbt_Handler .extern Undef_Handler .extern FIQ_Handler # --------------------------------------------- # export global symbols # --------------------------------------------- .global ResetEntry .global _startup # --------------------------------------------- # Start of Code # --------------------------------------------- .text .arm .func _startup _startup: # --------------------------------------------- # Interrupt vector table at address 0 # --------------------------------------------- Reset_Vec: LDR PC, _ResetEntry LDR PC, _Undef_Addr LDR PC, _SWI_Addr LDR PC, _PAbt_Addr LDR PC, _DAbt_Addr .word CheckSum /* Reserved Vector */ LDR PC, [PC,#-0xFF0] LDR PC, _FIQ_Addr /* Calling the FIQ handler */ # --------------------------------------------- _ResetEntry: .word ResetEntry _Undef_Addr: .word Undef_Handler _SWI_Addr: .word SWI_Handler _PAbt_Addr: .word PAbt_Handler _DAbt_Addr: .word DAbt_Handler _FIQ_Addr: .word FIQ_Handler # --------------------------------------------- # From here HardReset and SoftReset executes # the same code # --------------------------------------------- ResetEntry: StartupDelay 300000 # --------------------------------------------- # Micro controller specific code # --------------------------------------------- setup_PLL 5, __PLLDIV2 setup_VPBDIV __VPBDIV_4 setup_MAM __MAM_disabled, 3 # --------------------------------------------- # Setup stacks for the operating modes # --------------------------------------------- setup_stack UND_Stack, UND_Stack_Size, #Mode_UND|I_BIT|F_BIT setup_stack SVC_Stack, SVC_Stack_Size, #Mode_SVC|I_BIT|F_BIT setup_stack ABT_Stack, ABT_Stack_Size, #Mode_ABT|I_BIT|F_BIT setup_stack FIQ_Stack, FIQ_Stack_Size, #Mode_FIQ|I_BIT|F_BIT setup_stack IRQ_Stack, IRQ_Stack_Size, #Mode_IRQ|I_BIT|F_BIT setup_stack USR_Stack, USR_Stack_Size, #Mode_USR # Setup a default Stack Limit (when compiled with -mapcs-stack-check) SUB SL, SP, #USR_Stack_Size # enable interrupts mrs r1, CPSR bic r1, r1, #0x80 msr CPSR, r1 # --------------------------------------------- # copy sections # --------------------------------------------- copy_section2 data, _etext, __data_start__, _edata # --------------------------------------------- # Micro controller specific code # --------------------------------------------- # --------------------------------------------- # Clear .bss section # --------------------------------------------- clear_section bss, __bss_start__, __bss_end__ clear_section bss2, __bss2_start__, __bss2_end__ # --------------------------------------------- # Enter the C code # --------------------------------------------- b main # --------------------------------------------- # Table with data # --------------------------------------------- stack_adr UND_Stack stack_adr SVC_Stack stack_adr ABT_Stack stack_adr FIQ_Stack stack_adr IRQ_Stack stack_adr USR_Stack .end #________________________________________starup_generic.s______________________ # *** Startup Code (executed after Reset) *** # Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs .equ Mode_USR, 0x10 .equ Mode_FIQ, 0x11 .equ Mode_IRQ, 0x12 .equ Mode_SVC, 0x13 .equ Mode_ABT, 0x17 .equ Mode_UND, 0x1B .equ Mode_SYS, 0x1F .equ T_BIT, 0x20 /* when T bit is set, thumb mode active */ .equ I_BIT, 0x80 /* when I bit is set, IRQ is disabled */ .equ F_BIT, 0x40 /* when F bit is set, FIQ is disabled */ # --------------------------------------------- # macro definition for stack memory reservation # --------------------------------------------- # use this macro to setup the stack .macro setup_stack label1, size, mode_bits .lcomm __range_\label1, (\size - 1) * 4 .global \label1 .lcomm \label1, 4 ldr r0, adr_\label1 msr CPSR_c, \mode_bits mov r13, r0 .endm # use this macro to define the label for the setup_stack mcaro! .macro stack_adr label1 adr_\label1: .word \label1 .endm # --------------------------------------------- # copy section # use this macro to copy a section # parameters: # - individual name, used to create labels # - source pointer # - destination pointer # - source pointer + length > end address of source # --------------------------------------------- .macro copy_section sec_name, source, destination, source_end ldr R1, =\source ldr R2, =\destination ldr R3, =\source_end _cplp_\sec_name: cmp R1, R3 ldrlo R0, [R1], #4 strlo R0, [R2], #4 blo _cplp_\sec_name .endm # --------------------------------------------- # copy section 2 # use this macro to copy a section # parameters: # - individual name, used to create labels # - source pointer # - destination pointer # - destination pointer + length > end address of destination # --------------------------------------------- .macro copy_section2 sec_name, source, destination, destination_end ldr R1, =\source ldr R2, =\destination ldr R3, =\destination_end _cplp_\sec_name: cmp R2, R3 ldrlo R0, [R1], #4 strlo R0, [R2], #4 blo _cplp_\sec_name .endm # --------------------------------------------- # clear section # use this macro to clear bss sections # --------------------------------------------- .macro clear_section sec_name, source, source_end mov R0, #0 ldr R1, =\source ldr R2, =\source_end _cllp_\sec_name: cmp R1, R2 strlo R0, [R1], #4 blo _cllp_\sec_name .endm # --------------------------------------------- # examples how to use the macros # --------------------------------------------- # Setup stacks for the operating modes # --------------------------------------------- # setup_stack UND_Stack, UND_Stack_Size, #Mode_UND|I_BIT|F_BIT # setup_stack SVC_Stack, SVC_Stack_Size, #Mode_SVC|I_BIT|F_BIT # setup_stack ABT_Stack, ABT_Stack_Size, #Mode_ABT|I_BIT|F_BIT # setup_stack FIQ_Stack, FIQ_Stack_Size, #Mode_FIQ|I_BIT|F_BIT # setup_stack IRQ_Stack, IRQ_Stack_Size, #Mode_IRQ|I_BIT|F_BIT # setup_stack USR_Stack, USR_Stack_Size, #Mode_USR # --------------------------------------------- # copy sections # --------------------------------------------- # copy code into internal ram # copy_section code, __code_start__, RAM_Base_Boot, __code_end__ # Relocate .data section (Copy from ROM to RAM) # copy_section data, __data_start__, __data_start__+RAM_Base_Boot, __data_end__ # --------------------------------------------- # Clear .bss section # --------------------------------------------- # Clear .bss section (Zero init) # clear_section bss, __bss_start__, __bss_end__ # --------------------------------------------- # startup delay # use this macro if you are working with an debugger # the startup delay avoid problems while # the application start before the debug interface # becomes controled by the debugger # --------------------------------------------- # a goodf choice for the delay value is # cpu clock / 100 with ATMEL controllers # cpu clock / 40 with Philips controllers .macro StartupDelay delay_value ldr R1, =\delay_value ldr R2, =0 __StartDelay: sub R1, R1, #1 cmp R1, R2 bhi __StartDelay .endm # --------------------------------------------- #____________________________startup_philips.s___________________________________ # This file provide some special definitions and macros # which brings advantages with a philips lpc2xxx device # Phase Locked Loop (PLL) definitions .equ PLL_BASE, 0xE01FC080 /* PLL Base Address */ .equ PLLCON_OFS, 0x00 /* PLL Control Offset*/ .equ PLLCFG_OFS, 0x04 /* PLL Configuration Offset */ .equ PLLSTAT_OFS, 0x08 /* PLL Status Offset */ .equ PLLFEED_OFS, 0x0C /* PLL Feed Offset */ .equ PLLCON_PLLE, (1<<0) /* PLL Enable */ .equ PLLCON_PLLC, (1<<1) /* PLL Connect */ .equ PLLCFG_MSEL, (0x1F<<0) /* PLL Multiplier */ .equ PLLCFG_PSEL, (0x03<<5) /* PLL Divider */ .equ PLLSTAT_PLOCK, (1<<10) /* PLL Lock Status */ .equ VICVECT, 0xFFFFF030 .equ REMAP_REG, 0xE01FC040 /* remap register */ # Constants for EMC configuration .equ EMC_base, 0xFFE00000 .equ WP_Disabled, 0x00000000 .equ WP_Enabled, 0x04000000 .equ MW_8, 0x00000000 .equ MW_16, 0x10000000 .equ MW_32, 0x20000000 .equ RBLE_Disabled, 0x00000000 .equ RBLE_Enabled, 0x00000400 .equ PINSEL2, 0xE002C014 .equ DBW_None, 0x30 .equ DBW_8, 0x00 .equ DBW_16, 0x10 .equ DBW_32, 0x20 .equ CS1_Disabled, 0x0 .equ CS1_Enabled, 0x800 .equ CS2_Disabled, 0x0 .equ CS2_Enabled, 0x4000 .equ CS3_Disabled, 0x0 .equ CS3_Enabled, 0x10000 .equ WE_Disabled, 0x0 .equ WE_Enabled, 0x100 .equ AL_None, 0x0 .equ AL_A3_2, 0x02000000 .equ AL_A5_2, 0x04000000 .equ AL_A7_2, 0x06000000 .equ AL_A11_2, 0x08000000 .equ AL_A15_2, 0x0A000000 .equ AL_A19_2, 0x0C000000 .equ AL_A23_2, 0x0E000000 # --------------------------------------------- # macro definition for PLL setup # --------------------------------------------- .equ __PLLDIV1, 0x00000000 .equ __PLLDIV2, 0x00000020 .equ __PLLDIV4, 0x00000040 .equ __PLLDIV8, 0x00000060 # use this macro to setup the PLL .macro setup_PLL PLL_M, PLL_P # Valid parameter values: # PLL_M 1-32 # PLL_P _PLLDIV1, __PLLDIV2, __PLLDIV4, __PLLDIV8 # Example: setup_PLL 5, __PLLDIV2 # test parameters and abort if they ar out of range LDR R0, =PLL_BASE MOV R1, #0xAA MOV R2, #0x55 # Configure and Enable PLL .equ PLLCFG_Val, \PLL_P|((\PLL_M-1)&0x1F) # .equ PLLCFG_Val, 0x00000024 MOV R3, #PLLCFG_Val STR R3, [R0, #PLLCFG_OFS] MOV R3, #PLLCON_PLLE STR R3, [R0, #PLLCON_OFS] STR R1, [R0, #PLLFEED_OFS] STR R2, [R0, #PLLFEED_OFS] # Wait until PLL Locked __PLL_Loop: LDR R3, [R0, #PLLSTAT_OFS] ANDS R3, R3, #PLLSTAT_PLOCK BEQ __PLL_Loop # Switch to PLL Clock MOV R3, #(PLLCON_PLLE | PLLCON_PLLC) STR R3, [R0, #PLLCON_OFS] STR R1, [R0, #PLLFEED_OFS] STR R2, [R0, #PLLFEED_OFS] .endm # --------------------------------------------- # macro definition for VPB divider settings # --------------------------------------------- .equ VPBDIV, 0xE01FC100 /* VPB divider */ # divider values .equ __VPBDIV_4, 0x00 /* divide by 4 */ .equ __VPBDIV_2, 0x02 /* divide by 2 */ .equ __VPBDIV_1, 0x01 /* divide by 1 */ .macro setup_VPBDIV div_value LDR R0, =VPBDIV MOV R1, #\div_value STR R1, [R0] .endm # --------------------------------------------- # macro definition for Memory Accelerator module # --------------------------------------------- .equ MAMCR, 0xE01FC000 .equ MAMTIM, 0xE01FC004 # use this constants to define the operating mode .equ __MAM_disabled, 0x00 .equ __MAM_partly_enabled, 0x01 .equ __MAM_fully_enabled, 0x02 # use a value between 1..7 for the number of clock cycles to read the flash .macro setup_MAM mam_mode, mam_timing LDR R0, =MAMCR MOV R1, #0 MOV R2, #\mam_mode MOV R3, #(\mam_timing&0x07) STR R1, [R0] STR R3, [R0, #4] STR R2, [R0] .endm # --------------------------------------------- # macro definition generic interrupt handler # --------------------------------------------- # this macro must be inserted direct behind the interrupt vector # table. The calculated offset is wrong if other location is changed! # this handler spand time to have a generic behaviour which can be # used from C without assembler programming. .macro __generic_interrupt_handler irq_label ################################################### # # generic interrupt service handler # ################################################### \irq_label: #save work registers stmfd sp!,{r0-r3,lr} /* load address from VIC hwile interrupts are disabled */ LDR r3, [PC, #-0xFFC] mrs r1,spsr stmfd sp!,{r1} # switch to system-mode, interrupts enabled msr CPSR_c,#Mode_SYS # enter ISR, load from VicVECAddr!! stmfd sp!,{lr} bl __philips_fetch_irq /* branch to isr */ ldmfd sp!,{lr} # switch back to IRQ-mode, irq disabled msr CPSR_c,#Mode_IRQ|I_BIT # reset VIC mov r0,#0x0 ldr r1,=VICVECT str r0,[r1,#0x0] # restore work registers and return to saved operating mode ldmfd sp!,{r1} msr SPSR_csxf,r1 ldmfd sp!,{r0-r3,lr} subs pc,lr,#4 # use this fetch to branch to the real isr. # the fetch must be stored here, becausse of the ofset! __philips_fetch_irq: mov pc, r3 /* Vector from VicVECAddr */ .endm