diff options
Diffstat (limited to 'firmware/src/start')
-rw-r--r-- | firmware/src/start/Cstartup.S | 386 | ||||
-rw-r--r-- | firmware/src/start/Cstartup_SAM7.c | 89 |
2 files changed, 475 insertions, 0 deletions
diff --git a/firmware/src/start/Cstartup.S b/firmware/src/start/Cstartup.S new file mode 100644 index 0000000..e91fd86 --- /dev/null +++ b/firmware/src/start/Cstartup.S @@ -0,0 +1,386 @@ +/*------------------------------------------------------------------------------ +//*- 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 +//*-----------------------------------------------------------------------------*/ + +#define CONFIG_DFU_SWITCH + +//#define DEBUG_LL + +#ifdef DEBUG_LL +/* Debugging macros for switching on/off LED1 (green) */ +#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 */ + .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 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) + .equ PIO_BOOTLDR, (1 << 27) + #.equ PIO_BOOTLDR, (1 << 6) + + +/* #include "AT91SAM7S64_inc.h" */ + +/* Exception Vectors in RAM */ + + .text + .arm + .section .vectram, "ax" +resetvecR: B resetvecR +undefvecR: B undefvecR +swivecR: B swivecR +pabtvecR: B pabtvecR +dabtvecR: B dabtvecR +rsvdvecR: B rsvdvecR +irqvecR: B IRQ_Handler_EntryR +fiqvecR: + +FIQ_Handler_EntryR: + +/*- 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 + + .global IRQ_Handler_EntryR + .func IRQ_Handler_EntryR + +IRQ_Handler_EntryR: + +/*- 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_EntryR, . - IRQ_Handler_EntryR + .endfunc + + .global remap + .func remap +_remap: +# led1on +# Remap RAM to 0x00000000 for DFU + ldr r1, =AT91C_BASE_AIC + mov r2, #0x01 + str r2, [r1, #AIC_MCR_RCR] + + /* prepare c function call to main */ + mov r0, #0 /* argc = 0 */ + ldr lr,=exit + ldr r10,=main + +#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 + ldrne r10,=dfu_main +#endif + + bx r10 + .size remap, . - remap + .endfunc + +/* "exit" dummy added by mthomas 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 + + + +#;------------------------------------------------------------------------------ +#;- 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 + .global _startup + .func _startup +_startup: +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 irqvec /* 0x18 IRQ */ +fiqvec: + B fiqvec /* 0x1c FIQ */ + .align 0 +.RAM_TOP: + .word Top_Stack + +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 +/*------------------------------------------------------------------------------ +//*- Stack Sizes Definition +//*------------------------ +//*- Interrupt Stack requires 2 words x 8 priority level x 4 bytes when using +//*- the vectoring. This assume that the IRQ management. +//*- The Interrupt Stack must be adjusted depending on the interrupt handlers. +//*- Fast Interrupt not requires stack If in your application it required you must +//*- be definehere. +//*- The System stack size is not defined and is limited by the free internal +//*- SRAM. +//*------------------------------------------------------------------------------*/ + +/*------------------------------------------------------------------------------ +//*- 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 IRQ_STACK_SIZE, (3*8*4) + .EQU ARM_MODE_FIQ, 0x11 + .EQU ARM_MODE_IRQ, 0x12 + .EQU ARM_MODE_SVC, 0x13 + + .EQU I_BIT, 0x80 + .EQU F_BIT, 0x40 + +/*------------------------------------------------------------------------------ +//*- 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 +/*- 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 + mov r13, r0 /* Init stack Sup */ + +/*- Relocate DFU .data section (Copy from ROM to RAM)*/ + ldr r1, =_etext_dfu + ldr r2, =_data_dfu + ldr r3, =_edata_dfu +LoopRelDFU: cmp r2, r3 + ldrlo r0, [r1], #4 + strlo r0, [r2], #4 + blo LoopRelDFU + +# Relocate .data section (Copy from ROM to RAM) + LDR R1, =_etext + LDR R2, =_data + LDR R3, =_edata +LoopRel: CMP R2, R3 + LDRLO R0, [R1], #4 + STRLO R0, [R2], #4 + BLO LoopRel + +# Clear .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 + + led1on + + ldr r0, =_remap + bx r0 + + .size _startup, . - _startup + .endfunc + + .end + diff --git a/firmware/src/start/Cstartup_SAM7.c b/firmware/src/start/Cstartup_SAM7.c new file mode 100644 index 0000000..66dbe20 --- /dev/null +++ b/firmware/src/start/Cstartup_SAM7.c @@ -0,0 +1,89 @@ +//*---------------------------------------------------------------------------- +//* 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 Name : Cstartup_SAM7.c +//* Object : Low level initializations written in C for GCC Tools +//* Creation : 12/Jun/04 +//* 1.2 28/Feb/05 JPP : LIB change AT91C_WDTC_WDDIS & PLL +//* 1.3 21/Mar/05 JPP : Change PLL Wait time +//*---------------------------------------------------------------------------- + +// Include the board file description +#include <board.h> + +// The following functions must be write in ARM mode this function called directly +// by exception vector +extern void AT91F_Spurious_handler (void); +extern void AT91F_Default_IRQ_handler (void); +extern void AT91F_Default_FIQ_handler (void); + +//*---------------------------------------------------------------------------- +//* \fn AT91F_LowLevelInit +//* \brief This function performs very low level HW initialization +//* this function can be use a Stack, depending the compilation +//* optimization mode +//*---------------------------------------------------------------------------- +void +AT91F_LowLevelInit (void) +{ + int i; + AT91PS_PMC pPMC = AT91C_BASE_PMC; + //* Set Flash Waite sate + // Single Cycle Access at Up to 30 MHz, or 40 + // if MCK = 47923200 I have 50 Cycle for 1 usecond ( flied MC_FMR->FMCN + AT91C_BASE_MC->MC_FMR = ((AT91C_MC_FMCN) & (48 << 16)) | AT91C_MC_FWS_1FWS; + + //* Watchdog Disable + AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; + + //* Set MCK at 47 923 200 + // 1 Enabling the Main Oscillator: + // SCK = 1/32768 = 30.51 uSecond + // Start up time = 8 * 6 / SCK = 56 * 30.51 = 1,46484375 ms + pPMC->PMC_MOR = ((AT91C_CKGR_OSCOUNT) & (0x06 << 8)) | AT91C_CKGR_MOSCEN; + // Wait the startup time + while (!(pPMC->PMC_SR & AT91C_PMC_MOSCS)); + // 2 Checking the Main Oscillator Frequency (Optional) + // 3 Setting PLL and divider: + // - div by 24 Fin = 0,7680 =(18,432 / 24) + // - Mul 125: Fout = 96,0000 =(0,7680 *125) + // for 96 MHz the erroe is 0.16% + // Field out NOT USED = 0 + // PLLCOUNT pll startup time estimate at : 0.844 ms + // PLLCOUNT 28 = 0.000844 /(1/32768) +#if 0 + pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 0x05) | + (AT91C_CKGR_PLLCOUNT & (28 << 8)) | + (AT91C_CKGR_MUL & (25 << 16))); +#else + pPMC->PMC_PLLR = ((AT91C_CKGR_DIV & 24) | + (AT91C_CKGR_PLLCOUNT & (28 << 8)) | + (AT91C_CKGR_MUL & (125 << 16))); +#endif + + // Wait the startup time + while (!(pPMC->PMC_SR & AT91C_PMC_LOCK)); + while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY)); + // 4. Selection of Master Clock and Processor Clock + // select the PLL clock divided by 2 + pPMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; + while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY)); + + pPMC->PMC_MCKR |= AT91C_PMC_CSS_PLL_CLK; + while (!(pPMC->PMC_SR & AT91C_PMC_MCKRDY)); + + // Set up the default interrupts handler vectors + AT91C_BASE_AIC->AIC_SVR[0] = (int) AT91F_Default_FIQ_handler; + for (i = 1; i < 31; i++) + { + AT91C_BASE_AIC->AIC_SVR[i] = (int) AT91F_Default_IRQ_handler; + } + AT91C_BASE_AIC->AIC_SPU = (int) AT91F_Spurious_handler; + +} |