mirror of
https://github.com/stargieg/bacnet-stack
synced 2025-10-26 23:35:52 +08:00
320 lines
16 KiB
ArmAsm
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
|