1
0
mirror of https://github.com/stargieg/bacnet-stack synced 2025-10-26 23:35:52 +08:00
bacnet-stack/ports/at91sam7s/crt.s
2013-03-21 22:53:31 +01:00

320 lines
16 KiB
ArmAsm

/* ****************************************************************************************************** */
/* crt.s */
/* */
/* Assembly Language Startup Code for Atmel AT91SAM7S256 */
/* */
/* */
/* */
/* */
/* Author: James P Lynch May 12, 2007 */
/* ****************************************************************************************************** */
/* Stack Sizes */
.set UND_STACK_SIZE, 0x00000010 /* stack for "undefined instruction" interrupts is 16 bytes */
.set ABT_STACK_SIZE, 0x00000010 /* stack for "abort" interrupts is 16 bytes */
.set FIQ_STACK_SIZE, 0x00000080 /* stack for "FIQ" interrupts is 128 bytes */
.set IRQ_STACK_SIZE, 0X00000080 /* stack for "IRQ" normal interrupts is 128 bytes */
.set SVC_STACK_SIZE, 0x00000080 /* stack for "SVC" supervisor mode is 128 bytes */
/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */
.set ARM_MODE_USR, 0x10 /* Normal User Mode */
.set ARM_MODE_FIQ, 0x11 /* FIQ Processing Fast Interrupts Mode */
.set ARM_MODE_IRQ, 0x12 /* IRQ Processing Standard Interrupts Mode */
.set ARM_MODE_SVC, 0x13 /* Supervisor Processing Software Interrupts Mode */
.set ARM_MODE_ABT, 0x17 /* Abort Processing memory Faults Mode */
.set ARM_MODE_UND, 0x1B /* Undefined Processing Undefined Instructions Mode */
.set ARM_MODE_SYS, 0x1F /* System Running Priviledged Operating System Tasks Mode */
.set I_BIT, 0x80 /* when I bit is set, IRQ is disabled (program status registers) */
.set F_BIT, 0x40 /* when F bit is set, FIQ is disabled (program status registers) */
/* Addresses and offsets of AIC and PIO */
.set AT91C_BASE_AIC, 0xFFFFF000 /* (AIC) Base Address */
.set AT91C_PIOA_CODR, 0xFFFFF434 /* (PIO) Clear Output Data Register */
.set AT91C_AIC_IVR, 0xFFFFF100 /* (AIC) IRQ Interrupt Vector Register */
.set AT91C_AIC_FVR, 0xFFFFF104 /* (AIC) FIQ Interrupt Vector Register */
.set AIC_IVR, 256 /* IRQ Vector Register offset from base above */
.set AIC_FVR, 260 /* FIQ Vector Register offset from base above */
.set AIC_EOICR, 304 /* End of Interrupt Command Register */
/* identify all GLOBAL symbols */
.global _vec_reset
.global _vec_undef
.global _vec_swi
.global _vec_pabt
.global _vec_dabt
.global _vec_rsv
.global _vec_irq
.global _vec_fiq
.global AT91F_Irq_Handler
.global AT91F_Fiq_Handler
.global AT91F_Default_FIQ_handler
.global AT91F_Default_IRQ_handler
.global AT91F_Spurious_handler
.global AT91F_Dabt_Handler
.global AT91F_Pabt_Handler
.global AT91F_Undef_Handler
/* GNU assembler controls */
.text /* all assembler code that follows will go into .text section */
.arm /* compile for 32-bit ARM instruction set */
.align /* align section on 32-bit boundary */
/* ============================================================ */
/* VECTOR TABLE */
/* */
/* Must be located in FLASH at address 0x00000000 */
/* */
/* Easy to do if this file crt.s is first in the list */
/* for the linker step in the makefile, e.g. */
/* */
/* $(LD) $(LFLAGS) -o main.out crt.o main.o */
/* */
/* ============================================================ */
_vec_reset: b _init_reset /* RESET vector - must be at 0x00000000 */
_vec_undef: b AT91F_Undef_Handler /* Undefined Instruction vector */
_vec_swi: b _vec_swi /* Software Interrupt vector */
_vec_pabt: b AT91F_Pabt_Handler /* Prefetch abort vector */
_vec_dabt: b AT91F_Dabt_Handler /* Data abort vector */
_vec_rsv: nop /* Reserved vector */
_vec_irq: b AT91F_Irq_Handler /* Interrupt Request (IRQ) vector */
_vec_fiq: /* Fast interrupt request (FIQ) vector */
/* ======================================================================== */
/* Function: AT91F_Fiq_Handler */
/* */
/* The FIQ interrupt asserts when switch SW1 is pressed. */
/* */
/* This simple FIQ handler turns on LED3 (Port PA2). The LED3 will be */
/* turned off by the background loop in main() thus giving a visual */
/* indication that the interrupt has occurred. */
/* */
/* This FIQ_Handler supports non-nested FIQ interrupts (a FIQ interrupt */
/* cannot itself be interrupted). */
/* */
/* The Fast Interrupt Vector Register (AIC_FVR) is read to clear the */
/* interrupt. */
/* */
/* A global variable FiqCount is also incremented. */
/* */
/* Remember that switch SW1 is not debounced, so the FIQ interrupt may */
/* occur more than once for a single button push. */
/* */
/* Programmer: James P Lynch */
/* ======================================================================== */
AT91F_Fiq_Handler:
/* Adjust LR_irq */
sub lr, lr, #4
/* Read the AIC Fast Interrupt Vector register to clear the interrupt */
ldr r12, =AT91C_AIC_FVR
ldr r11, [r12]
/* Return from Fiq interrupt */
movs pc, lr
/* ======================================================================== */
/* _init_reset Handler */
/* */
/* RESET vector 0x00000000 branches to here. */
/* */
/* ARM microprocessor begins execution after RESET at address 0x00000000 */
/* in Supervisor mode with interrupts disabled! */
/* */
/* _init_reset handler: creates a stack for each ARM mode. */
/* sets up a stack pointer for each ARM mode. */
/* turns off interrupts in each mode. */
/* leaves CPU in SYS (System) mode. */
/* */
/* block copies the initializers to .data section */
/* clears the .bss section to zero */
/* */
/* branches to main( ) */
/* ======================================================================== */
.text /* all assembler code that follows will go into .text section */
.align /* align section on 32-bit boundary */
_init_reset:
/* Setup a stack for each mode with interrupts initially disabled. */
ldr r0, =_stack_end /* r0 = top-of-stack */
msr CPSR_c, #ARM_MODE_UND|I_BIT|F_BIT /* switch to Undefined Instruction Mode */
mov sp, r0 /* set stack pointer for UND mode */
sub r0, r0, #UND_STACK_SIZE /* adjust r0 past UND stack */
msr CPSR_c, #ARM_MODE_ABT|I_BIT|F_BIT /* switch to Abort Mode */
mov sp, r0 /* set stack pointer for ABT mode */
sub r0, r0, #ABT_STACK_SIZE /* adjust r0 past ABT stack */
msr CPSR_c, #ARM_MODE_FIQ|I_BIT|F_BIT /* switch to FIQ Mode */
mov sp, r0 /* set stack pointer for FIQ mode */
sub r0, r0, #FIQ_STACK_SIZE /* adjust r0 past FIQ stack */
msr CPSR_c, #ARM_MODE_IRQ|I_BIT|F_BIT /* switch to IRQ Mode */
mov sp, r0 /* set stack pointer for IRQ mode */
sub r0, r0, #IRQ_STACK_SIZE /* adjust r0 past IRQ stack */
msr CPSR_c, #ARM_MODE_SVC|I_BIT|F_BIT /* switch to Supervisor Mode */
mov sp, r0 /* set stack pointer for SVC mode */
sub r0, r0, #SVC_STACK_SIZE /* adjust r0 past SVC stack */
msr CPSR_c, #ARM_MODE_SYS|I_BIT|F_BIT /* switch to System Mode */
mov sp, r0 /* set stack pointer for SYS mode */
/* we now start execution in SYSTEM mode */
/* This is exactly like USER mode (same stack) */
/* but SYSTEM mode has more privileges */
/* copy initialized variables .data section (Copy from ROM to RAM) */
ldr R1, =_etext
ldr R2, =_data
ldr R3, =_edata
1: cmp R2, R3
ldrlo R0, [R1], #4
strlo R0, [R2], #4
blo 1b
/* Clear uninitialized variables .bss section (Zero init) */
mov R0, #0
ldr R1, =_bss_start
ldr R2, =_bss_end
2: cmp R1, R2
strlo R0, [R1], #4
blo 2b
/* Enter the C code */
b main
/* ======================================================================== */
/* Function: AT91F_Irq_Handler */
/* */
/* This IRQ_Handler supports nested interrupts (an IRQ interrupt can itself */
/* be interrupted). */
/* */
/* This handler re-enables interrupts and switches to "Supervisor" mode to */
/* prevent any corruption to the link and IP registers. */
/* */
/* The Interrupt Vector Register (AIC_IVR) is read to determine the address */
/* of the required interrupt service routine. The ISR routine can be a */
/* standard C function since this handler minds all the save/restore */
/* protocols. */
/* */
/* */
/* Programmers: */
/*--------------------------------------------------------------------------*/
/* ATMEL Microcontroller Software Support - ROUSSET - */
/*--------------------------------------------------------------------------*/
/* DISCLAIMER: THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS */
/* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED */
/* WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND */
/* NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR */
/* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR */
/* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT */
/* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR */
/* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, */
/* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE */
/* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, */
/* EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */
/* File source : Cstartup.s79 */
/* Object : Generic CStartup to AT91SAM7S256 */
/* 1.0 09/May/06 JPP : Creation */
/* */
/* */
/* Note: taken from Atmel web site (www.at91.com) */
/* Keil example project: AT91SAM7S-Interrupt_SAM7S */
/* ======================================================================== */
AT91F_Irq_Handler:
/* Manage Exception Entry */
/* Adjust and save LR_irq in IRQ stack */
sub lr, lr, #4
stmfd sp!, {lr}
/* Save r0 and SPSR (need to be saved for nested interrupt) */
mrs r14, SPSR
stmfd sp!, {r0,r14}
/* 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
/* Manage Exception Exit */
/* 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,r14}
msr SPSR_cxsf, r14
/* Restore adjusted LR_irq from IRQ stack directly in the PC */
ldmia sp!, {pc}^
/* ======================================================================== */
/* Function: AT91F_Dabt_Handler */
/* */
/* Entered on Data Abort exception. */
/* Enters blink routine (3 blinks followed by a pause) */
/* processor hangs in the blink loop forever */
/* */
/* ======================================================================== */
AT91F_Dabt_Handler: mov R0, #3
b blinker
/* ======================================================================== */
/* Function: AT91F_Pabt_Handler */
/* */
/* Entered on Prefetch Abort exception. */
/* Enters blink routine (2 blinks followed by a pause) */
/* processor hangs in the blink loop forever */
/* */
/* ======================================================================== */
AT91F_Pabt_Handler: mov R0, #2
b blinker
/* ======================================================================== */
/* Function: AT91F_Undef_Handler */
/* */
/* Entered on Undefined Instruction exception. */
/* Enters blink routine (1 blinks followed by a pause) */
/* processor hangs in the blink loop forever */
/* */
/* ======================================================================== */
AT91F_Undef_Handler: mov R0, #1
b blinker
AT91F_Default_FIQ_handler: b AT91F_Default_FIQ_handler
AT91F_Default_IRQ_handler: b AT91F_Default_IRQ_handler
AT91F_Spurious_handler: b AT91F_Spurious_handler
.end