summaryrefslogtreecommitdiff
path: root/openpicc/os/boot/Cstartup.S
diff options
context:
space:
mode:
Diffstat (limited to 'openpicc/os/boot/Cstartup.S')
-rw-r--r--openpicc/os/boot/Cstartup.S450
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
+
personal git repositories of Harald Welte. Your mileage may vary