diff options
Diffstat (limited to 'openpicc/os/boot/Cstartup.S')
-rw-r--r-- | openpicc/os/boot/Cstartup.S | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/openpicc/os/boot/Cstartup.S b/openpicc/os/boot/Cstartup.S new file mode 100644 index 0000000..83e7696 --- /dev/null +++ b/openpicc/os/boot/Cstartup.S @@ -0,0 +1,450 @@ +/* AT91SAM7 low-level startup outines for OpenPCD / OpenPICC DFU loader + * (C) 2006 by Harald Welte <hwelte@hmw-consulting.de> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ + +/*------------------------------------------------------------------------------ +//*- ATMEL Microcontroller Software Support - ROUSSET - +//*------------------------------------------------------------------------------ +//* The software is delivered "AS IS" without warranty or condition of any +//* kind, either express, implied or statutory. This includes without +//* limitation any warranty or condition with respect to merchantability or +//* fitness for any particular purpose, or against the infringements of +//* intellectual property rights of others. +//*----------------------------------------------------------------------------- +//*- File source : Cstartup.s +//*- Object : Generic CStartup for KEIL and GCC No Use REMAP +//*- Compilation flag : None +//*- +//*- 1.0 18/Oct/04 JPP : Creation +//*- 1.1 21/Feb/05 JPP : Set Interrupt +//*- 1.1 01/Apr/05 JPP : save SPSR +//*-----------------------------------------------------------------------------*/ + +/* Enable DFU by press of hardware POI_BOOTLDR switch */ +#define CONFIG_DFU_SWITCH + +/* Enable DFU by magic value in RAM and software reset */ +#define CONFIG_DFU_MAGIC + +//#define DEBUG_LL + +#define PIOA_PER 0xFFFFF400 +#define PIOA_OER 0xFFFFF410 +#define PIOA_SODR 0xFFFFF430 +#define PIOA_CODR 0xFFFFF434 +#define LED1 25 /* this only works on OpenPICC, not Olimex */ + +#ifdef DEBUG_LL +/* Debugging macros for switching on/off LED1 (green) */ + .macro led1on + ldr r2, =PIOA_CODR + mov r1, #(1 << LED1) + str r1, [r2] + .endm + .macro led1off + ldr r2, =PIOA_SODR + mov r1, #(1 << LED1) + str r1, [r2] + .endm + .macro ledinit + ldr r2, =PIOA_PER + mov r1, #(1 << LED1) + str r1, [r2] + ldr r2, =PIOA_OER + str r1, [r2] + led1off + .endm +#else + .macro ledinit + .endm + .macro led1on + .endm + .macro led1off + .endm +#endif + + .equ IRQ_Stack_Size, 0x00000400 + .equ FIQ_Stack_Size, 0x00000400 + + .equ AIC_IVR, (256) + .equ AIC_FVR, (260) + .equ AIC_EOICR, (304) + .equ AIC_MCR_RCR, (0xf00) + .equ AT91C_BASE_AIC, (0xFFFFF000) + .equ AT91C_PMC_PCER, (0xFFFFFC10) + .equ AT91C_BASE_PIOA, (0xFFFFF400) + .equ AT91C_ID_PIOA, (2) + .equ PIOA_PDSR, (0x3c) +#if defined(PCD) + .equ PIO_BOOTLDR, (1 << 27) +#elif defined(PICC) + .equ PIO_BOOTLDR, (1 << 6) +#elif defined(OLIMEX) + .equ PIO_BOOTLDR, (1 << 19) +#else +#error please define PIO_BOOTLDR +#endif + + +/* #include "AT91SAM7S64_inc.h" */ + +/* Exception Vectors in RAM */ + + .text + .arm + .section .vectram, "ax" + + .global _remap_call_dfu + .func _remap_call_dfu +_remap_call_dfu: + led1on + /* Remap RAM to 0x00000000 for DFU */ + ldr r1, =AT91C_BASE_AIC + mov r2, #0x01 + str r2, [r1, #AIC_MCR_RCR] + + ldr r4, =dfu_main + bx r4 + + .size _remap_call_dfu, . - _remap_call_dfu + .endfunc + + +#;------------------------------------------------------------------------------ +#;- Section Definition +#;----------------- +#;- Section +#;- .internal_ram_top Top_Stack: used by the cstartup for vector initalisation +#;- management defined by ld and affect from ldscript +#;------------------------------------------------------------------------------ + .section .internal_ram_top + .code 32 + .align 0 + .global Top_Stack +Top_Stack: + +/*------------------------------------------------------------------------------ +*- Area Definition +*------------------------------------------------------------------------------ +* .text is used instead of .section .text so it works with arm-aout too. */ + .section .reset + .text +reset: +/*------------------------------------------------------------------------------ +//*- Exception vectors +//*-------------------- +//*- These vectors can be read at address 0 or at RAM address +//*- They ABSOLUTELY requires to be in relative addresssing mode in order to +//*- guarantee a valid jump. For the moment, all are just looping. +//*- If an exception occurs before remap, this would result in an infinite loop. +//*- To ensure if a exeption occurs before start application to infinite loop. +//*------------------------------------------------------------------------------*/ + + B InitReset /* 0x00 Reset handler */ +undefvec: + B undefvec /* 0x04 Undefined Instruction */ +swivec: + B swivec /* 0x08 Software Interrupt */ +pabtvec: + B pabtvec /* 0x0C Prefetch Abort */ +dabtvec: + b dabtvec /* 0x10 Data Abort */ +rsvdvec: + b rsvdvec /* 0x14 reserved */ +irqvec: + b IRQ_Handler_Entry /* 0x18 IRQ */ +fiqvec: + ldr pc, [pc, #-0xF20] /* 0x1c FIQ */ + +dfu_state_dummy: + .word 0 + + .global IRQ_Handler_Entry + .func IRQ_Handler_Entry + +FIQ_Handler_Entry: + +/*- Switch in SVC/User Mode to allow User Stack access for C code */ +/* because the FIQ is not yet acknowledged*/ + +/*- Save and r0 in FIQ_Register */ + mov r9, r0 + ldr r0, [r8, #AIC_FVR] + msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_SVC + + /*- Save scratch/used registers and LR in User Stack */ + stmfd sp!, { r1-r3, r12, lr} + + /*- Branch to the routine pointed by the AIC_FVR */ + mov r14, pc + bx r0 + + /*- Restore scratch/used registers and LR from User Stack */ + ldmia sp!, { r1-r3, r12, lr} + + /*- Leave Interrupts disabled and switch back in FIQ mode */ + msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ + + /*- Restore the R0 ARM_MODE_SVC register */ + mov r0,r9 + + /*- Restore the Program Counter using the LR_fiq directly in the PC */ + subs pc, lr, #4 + +IRQ_Handler_Entry: + + /*- Manage Exception Entry */ + /*- Adjust and save LR_irq in IRQ stack */ + sub lr, lr, #4 + stmfd sp!, {lr} + + /*- Save SPSR need to be saved for nested interrupt */ + mrs r14, SPSR + stmfd sp!, {r14} + + /*- Save and r0 in IRQ stack */ + stmfd sp!, {r0} + + /*- Write in the IVR to support Protect Mode */ + /*- No effect in Normal Mode */ + /*- De-assert the NIRQ and clear the source in Protect Mode */ + ldr r14, =AT91C_BASE_AIC + ldr r0 , [r14, #AIC_IVR] + str r14, [r14, #AIC_IVR] + + /*- Enable Interrupt and Switch in Supervisor Mode */ + msr CPSR_c, #ARM_MODE_SVC + + /*- Save scratch/used registers and LR in User Stack */ + stmfd sp!, { r1-r3, r12, r14} + + /*- Branch to the routine pointed by the AIC_IVR */ + mov r14, pc + bx r0 + + /*- Restore scratch/used registers and LR from User Stack*/ + ldmia sp!, { r1-r3, r12, r14} + + /*- Disable Interrupt and switch back in IRQ mode */ + msr CPSR_c, #I_BIT | ARM_MODE_IRQ + + /*- Mark the End of Interrupt on the AIC */ + ldr r14, =AT91C_BASE_AIC + str r14, [r14, #AIC_EOICR] + + /*- Restore SPSR_irq and r0 from IRQ stack */ + ldmia sp!, {r0} + + /*- Restore SPSR_irq and r0 from IRQ stack */ + ldmia sp!, {r14} + msr SPSR_cxsf, r14 + + /*- Restore adjusted LR_irq from IRQ stack directly in the PC */ + ldmia sp!, {pc}^ + + .size IRQ_Handler_Entry, . - IRQ_Handler_Entry + .endfunc + .align 0 +.RAM_TOP: + .word Top_Stack + + .global _startup + .func _startup +InitReset: +/*------------------------------------------------------------------------------ +/*- Low level Init (PMC, AIC, ? ....) by C function AT91F_LowLevelInit +/*------------------------------------------------------------------------------*/ + .extern AT91F_LowLevelInit +/*- minumum C initialization */ +/*- call AT91F_LowLevelInit( void) */ + + ldr r13,.RAM_TOP /* temporary stack in internal RAM */ +/*--Call Low level init function in ABSOLUTE through the Interworking */ + ldr r0,=AT91F_LowLevelInit + mov lr, pc + bx r0 + ledinit + +/*------------------------------------------------------------------------------ +//*- Top of Stack Definition +//*------------------------- +//*- Interrupt and Supervisor Stack are located at the top of internal memory in +//*- order to speed the exception handling context saving and restoring. +//*- ARM_MODE_SVC (Application, C) Stack is located at the top of the external memory. +//*------------------------------------------------------------------------------*/ + + .EQU ARM_MODE_FIQ, 0x11 + .EQU ARM_MODE_IRQ, 0x12 + .EQU ARM_MODE_SVC, 0x13 + + .EQU I_BIT, 0x80 + .EQU F_BIT, 0x40 + + +#define AT91C_RSTC_RSR 0xFFFFFD04 +#define AT91C_RSTC_RSTTYP_SOFTWARE (0x03 << 8) +#define DFU_STATE_appDETACH 1 + + +/*------------------------------------------------------------------------------ +//*- Setup the stack for each mode +//*-------------------------------*/ + mov r0,r13 + +/*- Set up Fast Interrupt Mode and set FIQ Mode Stack*/ + msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT + mov r13, r0 + sub r0, r0, #FIQ_Stack_Size + +/*- Init the FIQ register*/ + ldr r8, =AT91C_BASE_AIC + +/*- Set up Interrupt Mode and set IRQ Mode Stack*/ + msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT + mov r13, r0 /* Init stack IRQ */ + sub r0, r0, #IRQ_Stack_Size + +/*- Set up Supervisor Mode and set Supervisor Mode Stack*/ + msr CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT + mov r13, r0 /* Init stack Sup */ + +/* - Enable Interrupts and FIQ */ + msr CPSR_c, #ARM_MODE_SVC + +#ifdef CONFIG_DFU_MAGIC + ldr r1, =AT91C_RSTC_RSR + ldr r2, [r1] + #and r2, r2, AT91C_RSTC_RSTTYP + tst r2, #AT91C_RSTC_RSTTYP_SOFTWARE + beq dfu_magic_end + + ldr r1, =dfu_state + ldr r2, [r1] + cmp r2, #DFU_STATE_appDETACH + beq _reloc_dfu +dfu_magic_end: +#endif + +# Relocate DFU .data.shared section (Copy from ROM to RAM) + LDR R1, =_etext + LDR R2, =_data_shared + LDR R3, =_edata_shared +LoopRelDS: CMP R2, R3 + LDRLO R0, [R1], #4 + STRLO R0, [R2], #4 + BLO LoopRelDS + +/* +# Clear DFU .bss section (Zero init) + MOV R0, #0 + LDR R1, =__bss_start__ + LDR R2, =__bss_end__ +LoopZI: CMP R1, R2 + STRLO R0, [R1], #4 + BLO LoopZI +*/ + + /* prepare c function call to main */ + mov r0, #0 /* argc = 0 */ + ldr lr, =exit + ldr r10, =0x00104000 + +#ifdef CONFIG_DFU_SWITCH + /* check whether bootloader button is pressed */ + ldr r1, =AT91C_PMC_PCER + mov r2, #(1 << AT91C_ID_PIOA) + str r2, [r1] + + ldr r1, =AT91C_BASE_PIOA + ldr r2, [r1, #PIOA_PDSR] + tst r2, #PIO_BOOTLDR + bne _reloc_dfu +#endif + + bx r10 + +_reloc_dfu: + /* Relocate DFU .data section (Copy from ROM to RAM) */ + LDR R1, =_data_flash + LDR R2, =_data + LDR R3, =_edata +LoopRel: CMP R2, R3 + LDRLO R0, [R1], #4 + STRLO R0, [R2], #4 + BLO LoopRel + + /* Clear DFU .bss section (Zero init) */ + MOV R0, #0 + LDR R1, =__bss_start__ + LDR R2, =__bss_end__ +LoopZI: CMP R1, R2 + STRLO R0, [R1], #4 + BLO LoopZI + + /* relocate DFU .text into RAM */ + ldr r1, =0x00100000 + ldr r2, =0x00200000 + ldr r3, =_etext + add r3, r3, r2 +loop_rel_t: cmp r2, r3 + ldrlo r4, [r1], #4 + strlo r4, [r2], #4 + blo loop_rel_t + ldr r4, =_remap_call_dfu + bx r4 + + .size _startup, . - _startup + .endfunc + +/* "exit" dummy to avoid sbrk write read etc. needed by the newlib default "exit" */ + .global exit + .func exit +exit: + b . + .size exit, . - exit + .endfunc + +/*--------------------------------------------------------------- +//* ?EXEPTION_VECTOR +//* This module is only linked if needed for closing files. +//*---------------------------------------------------------------*/ + .global AT91F_Default_FIQ_handler + .func AT91F_Default_FIQ_handler +AT91F_Default_FIQ_handler: + b AT91F_Default_FIQ_handler + .size AT91F_Default_FIQ_handler, . - AT91F_Default_FIQ_handler + .endfunc + + .global AT91F_Default_IRQ_handler + .func AT91F_Default_IRQ_handler +AT91F_Default_IRQ_handler: + b AT91F_Default_IRQ_handler + .size AT91F_Default_IRQ_handler, . - AT91F_Default_IRQ_handler + .endfunc + + .global AT91F_Spurious_handler + .func AT91F_Spurious_handler +AT91F_Spurious_handler: + b AT91F_Spurious_handler + .size AT91F_Spurious_handler, . - AT91F_Spurious_handler + .endfunc + + + + .end + |