This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
Re: Questions about vectors.s
- To: Gary Thomas <gthomas at redhat dot com>
- Subject: [ECOS] Re: Questions about vectors.s
- From: Bill Diehls <billabloke at yahoo dot com>
- Date: Sat, 27 Oct 2001 22:11:40 -0700 (PDT)
- Cc: rich at intervideo dot com, eCos Discussion <ecos-discuss at sources dot redhat dot com>
I've attached two files -- vectors.s.orig is the
original file before we started modifying it, and
vectors.s is the modified file.
thanks!
--bill
--- Gary Thomas <gthomas@redhat.com> wrote:
> While I intend to comment on your questions later
> (when I have more
> time), it would be much easier for me to analyze
> your changes if
> you either send the file (vectors.S) as an
> attachment or as context
> diffs. The version provided is horribly wrapped by
> [at least my]
> email reader as to be totally useless. The best
> form for diffs
> is "diff -u5 -p -N" - again make sure that they
> don't get wrapped.
>
> I'll comment on the rest later, probably after you
> provide a more
> useful file to look at.
>
>
>
__________________________________________________
Do You Yahoo!?
Make a great connection at Yahoo! Personals.
http://personals.yahoo.com
// #========================================================================
// #
// # vectors.S
// #
// # ARM exception vectors
// #
// #========================================================================
// ####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
// ####COPYRIGHTEND####
// #========================================================================
// ######DESCRIPTIONBEGIN####
// #
// # Author(s): nickg, gthomas
// # Contributors: nickg, gthomas
// # Date: 1999-02-20
// # Purpose: ARM exception vectors
// # Description: This file defines the code placed into the exception
// # vectors. It also contains the first level default VSRs
// # that save and restore state for both exceptions and
// # interrupts.
// #
// #####DESCRIPTIONEND####
// #
// #========================================================================
#define RICH
#include <pkgconf/hal.h>
#include <pkgconf/hal_arm.h>
#ifdef CYGPKG_KERNEL // no CDL yet
#include <pkgconf/kernel.h>
#else
# undef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
# undef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
#endif
#include <cyg/hal/hal_platform_setup.h>
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
// The CDL should enforce this
#undef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
#endif
#include "arm.inc"
#ifdef __thumb__
// Switch to thumb mode
#define THUMB_MODE(_r_, _l_) \
ldr _r_,=_l_ ## f+1 ;\
bx _r_ ;\
.pool ;\
.code 16 ;\
.thumb_func ;\
_l_:
// Switch to ARM mode
#define ARM_MODE(_r_, _l_) \
ldr _r_,=_l_ ## f ;\
bx _r_ ;\
.pool ;\
.code 32 ;\
_l_:
// Function definition, start executing body in ARM mode
#define FUNC_START_ARM(_name_, _r_) \
.code 16 ;\
.thumb_func ;\
.globl _name_ ;\
_name_: ;\
ldr _r_,=_name_ ## _ARM ;\
bx _r_ ;\
.code 32 ;\
_name_ ## _ARM:
#else
// Switch to thumb mode
#define THUMB_MODE(_r_, _l_)
// Switch to ARM mode
#define ARM_MODE(_r_, _l_)
// Function definition, start executing body in ARM mode
#define FUNC_START_ARM(_name_, _r_) \
.globl _name_; \
_name_:
#endif
#define PTR(name) \
.##name: .word name
// CYGHWR_HAL_ROM_VADDR is used when compiling for a different location
// from the base of ROM. hal_platform_setup.h might define it. For
// example, if flash is from 0x50000000 upwards (as on SA11x0), and we are
// to execute at 0x50040000, then we want the reset vector to point to
// 0x0004pqrs - the unmapped ROM address of the code - rather than
// 0x0000pqrs, which is the offset into our flash block.
//
// But usually it's not defined, so the behaviour is the obvious.
#ifndef UNMAPPED
#ifdef CYGHWR_HAL_ARM_HAS_MMU
# ifndef CYGHWR_HAL_ROM_VADDR
# define CYGHWR_HAL_ROM_VADDR __exception_handlers
# endif
# define UNMAPPED(x) ((x)-CYGHWR_HAL_ROM_VADDR)
#else
# define UNMAPPED(x) (x)
#endif
#endif
#define UNMAPPED_PTR(name) \
.##name: .word UNMAPPED(name)
.file "vectors.S"
// CYGHWR_LED_MACRO can be defined in hal_platform_setup.h. It's free to
// use r0+r1. Argument is in "\x" - cannot use macro arguments since the
// macro may contain #-chars and use of arguments cause these to be
// interpreted as CPP stringify operators.
// See example in PID hal_platform_setup.h.
#ifndef CYGHWR_LED_MACRO
#define CYGHWR_LED_MACRO
#endif
.macro LED x
CYGHWR_LED_MACRO
.endm
#ifdef RICH
.GLOBAL reset_vector
reset_vector:
.ALIGN
.CODE 32
@ Start Vector
rom_header: b rom_header_end
@ Nintendo Logo Character Data (8000004h)
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00
@ Software Titles (80000A0h)
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00
.byte 0x00,0x00,0x00,0x00
@ Initial Code (80000ACh)
.byte 0x00,0x00,0x00,0x00
@ Maker Code (80000B0h)
.byte 0x30,0x31
@ Fixed Value (80000B2h)
.byte 0x96
@ Main Unit Code (80000B3h)
.byte 0x00
@ Device Type (80000B4h)
.byte 0x00
@ Unused Data (7Byte) (80000B5h)
.byte 0x00,0x00,0x00,0x00,0x00,0x00,0x00
@ Software Version No (80000BCh)
.byte 0x00
@ Complement Check (80000BDh)
.byte 0xf0
@ Check Sum (80000BEh)
.byte 0x00,0x00
rom_header_end:
b start_vector
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ The following reserved bytes are used if the code is compiled for
@ multiboot mode. The GBA BIOS will auto-patch the first two bytes
@ with 0x03 and 0x01, respectively, before running any code.
@
.byte 0 @ boot method (0=ROM boot, 3=Multiplay boot)
.byte 0 @ slave # (1=slave#1, 2=slave#2, 3=slave#3)
.byte 0 @ reserved
.byte 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
.word 0 @ reserved
@
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
#endif
//==========================================================================
// Hardware exception vectors.
// This entire section will be copied to location 0x0000 at startup time.
//
#ifndef RICH
.code 32
.section ".vectors","ax"
#endif
// This macro allows platforms to add their own code at the very start of
// the image. This may be required in some circumstances where eCos ROM
// based code does not run immediately upon reset and/or when some sort of
// special header is required at the start of the image.
#ifdef PLATFORM_PREAMBLE
PLATFORM_PREAMBLE
#endif
.global __exception_handlers
__exception_handlers:
#ifdef CYGSEM_HAL_ROM_RESET_USES_JUMP
// Assumption: ROM code has these vectors at the hardware reset address.
// A simple jump removes any address-space dependencies [i.e. safer]
b reset_vector // 0x00
#else
ldr pc,.reset_vector // 0x00
#endif
ldr pc,.undefined_instruction // 0x04
ldr pc,.software_interrupt // 0x08 start && software int
ldr pc,.abort_prefetch // 0x0C
ldr pc,.abort_data // 0x10
.word 0 // unused
ldr pc,.IRQ // 0x18
ldr pc,.FIQ // 0x1C
// The layout of these pointers should match the vector table above since
// they are copied in pairs.
.global vectors
vectors:
UNMAPPED_PTR(reset_vector) // 0x20
PTR(undefined_instruction) // 0x24
PTR(software_interrupt) // 0x28
PTR(abort_prefetch) // 0x2C
PTR(abort_data) // 0x30
.word 0 // 0x34
PTR(IRQ) // 0x38
PTR(FIQ) // 0x3c
#ifdef CYGSEM_HAL_ARM_PID_ANGEL_BOOT
PTR(start) // This is copied to 0x28 for bootup // 0x40
#endif
// location 0x40 is used for storing DRAM size if known
// for some platforms.
//
// "Patch vectors" - used to patch illegal instruction into debug stub code
// This code gets mapped to 0x9ffc000 (mirrored at 0x83fc000 for 4mb flash)
//
.section ".patch_vectors", "ax"
.code 32
.globl hal_patch_vector_code
hal_patch_vector_code:
// restore registers and return to user code (not bios, which returns incorrectly)
ldr r13, .pv_cl1
ldmfd r13!, {r12,r14}
msr spsr, r12
ldmfd r13!, {r12,r14}
b undefined_instruction
.pv_cl0:
.word 0x6004000
.pv_cl1:
.word 0x3007fe0
//
// "Vectors" - fixed location data items
// This section contains any data which might be shared between
// an eCos application and any other environment, e.g. the debug
// ROM.
//
.section ".fixed_vectors"
// Interrupt/exception VSR pointers
.globl hal_vsr_table
hal_vsr_table:
.rept 8
.long 0
.endr
.globl hal_dram_size
hal_dram_size:
.long 0
// what, if anything, hal_dram_type means is up to the platform
.globl hal_dram_type
hal_dram_type:
.long 0
.balign 16
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
// Vectors used to communicate between eCos and ROM environments
.globl hal_virtual_vector_table
hal_virtual_vector_table:
.rept CYGNUM_CALL_IF_TABLE_SIZE
.long 0
.endr
#endif
.balign 32
// Other vectors - this may include "fixed" locations
#ifdef PLATFORM_VECTORS
PLATFORM_VECTORS
#endif
.text
#ifdef RICH
start_vector:
#else
// Startup code which will get the machine into supervisor mode
.global reset_vector
.type reset_vector,function
reset_vector:
PLATFORM_SETUP1 // Early stage platform initialization
// which can set DRAM size at 0x40
// see <cyg/hal/hal_platform_setup.h>
// Come here to reset board
warm_reset:
#if defined(CYG_HAL_STARTUP_RAM) && \
!defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
mrs r7,cpsr // move back to IRQ mode
and r7,r7,#CPSR_MODE_BITS
cmp r7,#CPSR_SUPERVISOR_MODE
beq start
#endif
// We cannot access any LED registers until after PLATFORM_SETUP1
LED 7
mov r0,#0 // move vectors
ldr r1,=__exception_handlers
#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
// Wait with this if stubs are included (see further down).
ldr r2,[r1,#0x04] // undefined instruction
str r2,[r0,#0x04]
ldr r2,[r1,#0x24]
str r2,[r0,#0x24]
#endif
ldr r2,[r1,#0x08] // software interrupt
str r2,[r0,#0x08]
#if defined(CYGSEM_HAL_ARM_PID_ANGEL_BOOT)
// Ugly hack to get into supervisor mode
ldr r2,[r1,#0x40]
str r2,[r0,#0x28]
LED 6
swi // switch to supervisor mode
#endif
// =========================================================================
// Real startup code. We jump here from the reset vector to set up the world.
.globl start
start:
LED 5
#if defined(CYG_HAL_STARTUP_RAM) && \
!defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
// If we get restarted, hang here to avoid corrupting memory
ldr r0,.init_flag
ldr r1,[r0]
1: cmp r1,#0
bne 1b
ldr r1,init_done
str r1,[r0]
#endif
// Reset software interrupt pointer
mov r0,#0 // move vectors
ldr r1,.__exception_handlers
#if defined(CYG_HAL_STARTUP_RAM) && \
!defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
cmp r7,#CPSR_SUPERVISOR_MODE
beq 10f
#endif
ldr r2,[r1,#0x28] // software interrupt
str r2,[r0,#0x28]
10:
ldr r2,[r1,#0x18] // IRQ
str r2,[r0,#0x18]
ldr r2,[r1,#0x38]
str r2,[r0,#0x38]
ldr r2,[r1,#0x1C] // FIQ
str r2,[r0,#0x1C]
ldr r2,[r1,#0x3C]
str r2,[r0,#0x3C]
ldr r2,[r1,#0x0C] // abort (prefetch)
str r2,[r0,#0x0C]
ldr r2,[r1,#0x2C]
str r2,[r0,#0x2C]
ldr r2,[r1,#0x10] // abort (data)
str r2,[r0,#0x10]
ldr r2,[r1,#0x30]
str r2,[r0,#0x30]
LED 4
#endif
#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
#ifndef RICH
// Set up reset vector
mov r0,#0
ldr r1,.__exception_handlers
ldr r2,[r1,#0x00] // reset vector intstruction
str r2,[r0,#0x00]
ldr r2,=warm_reset
str r2,[r0,#0x20]
#endif
// Relocate [copy] data from ROM to RAM
ldr r3,.__rom_data_start
ldr r4,.__ram_data_start
ldr r5,.__ram_data_end
cmp r4,r5 // jump if no data to move
beq 2f
sub r3,r3,#4 // loop adjustments
sub r4,r4,#4
1: ldr r0,[r3,#4]! // copy info
str r0,[r4,#4]!
cmp r4,r5
bne 1b
2:
#endif
// initialize interrupt/exception environments
ldr sp,.__startup_stack
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_IRQ_MODE)
msr cpsr,r0
ldr sp,.__exception_stack
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE)
msr cpsr,r0
ldr sp,.__exception_stack
// initialize CPSR (machine state register)
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
msr cpsr,r0
// Note: some functions in LIBGCC1 will cause a "restore from SPSR"!!
msr spsr,r0
// initialize stack
ldr sp,.__startup_stack
// clear BSS
ldr r1,.__bss_start
ldr r2,.__bss_end
mov r0,#0
cmp r1,r2
beq 2f
1: str r0,[r1],#4
cmp r1,r2
bne 1b
2:
// Run kernel + application in THUMB mode
THUMB_MODE(r1,10)
// setup agb interrupt address
ldr r1, int_addr
adr r0, IRQ
str r0, [r1]
LED 3
bl TDInit
// Call platform specific hardware initialization
bl hal_hardware_init
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
bl initialize_stub
// Now that stub is initialized, change vector. It is possible
// to single-step through most of the init code, except the below.
// Put a breakpoint at the call to cyg_hal_invoke_constructors to
// pass over this bit (s-s depends on internal state in the stub).
#endif
#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) || \
defined(CYGIMP_HAL_PROCESS_ALL_EXCEPTIONS)
mov r0,#0 // move vectors
ldr r1,=__exception_handlers
ldr r2,[r1,#0x04] // undefined instruction
str r2,[r0,#0x04]
ldr r2,[r1,#0x24]
str r2,[r0,#0x24]
#endif
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
.extern hal_ctrlc_isr_init
bl hal_ctrlc_isr_init
#endif
LED 2
// Run through static constructors
bl cyg_hal_invoke_constructors
LED 1
// This starts up the eCos kernel
bl cyg_start
_start_hang:
b _start_hang
.code 32
.global reset_platform
.type reset_platform,function
reset_platform:
#ifdef CYGSEM_HAL_ROM_MONITOR
// initialize CPSR (machine state register)
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
msr cpsr,r0
b start_vector
#else
mov r0,#0
mov pc,r0 // Jump to reset vector
#endif
init_done:
.long 0xDEADB00B
int_addr:
.long 0x3007ffc
//
// Exception handlers
// Assumption: get here from a Supervisor context [mode]
//
.code 32
undefined_instruction:
ldr sp,.__undef_exception_stack // get good stack
stmfd sp!,{r0,fp,ip,lr}
mrs r0,spsr
stmfd sp!,{r0}
mov ip,sp // save SP which will vanish with
// mode switch
mrs r0,cpsr // switch to Supervisor Mode
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_SUPERVISOR_MODE
msr cpsr,r0 // sp,lr are now old values
mov fp,sp
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
ldr sp,.__GDB_stack
cmp fp,sp // already on GDB stack?
bhi 10f
ldr r0,.__GDB_stack_base
cmp fp,r0
bls 10f // no - switch to GDB stack
// (already in sp)
mov sp,fp // yes - no switch
10:
#endif
sub sp,sp,#ARMREG_SIZE // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
ldmfd ip,{r0-r4} // saved registers
// Adjust PC according to CPU mode
tst r0,#CPSR_THUMB_ENABLE
subeq r4,r4,#4 // PC at time of interrupt (ARM)
subne r4,r4,#2 // PC at time of interrupt (thumb)
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str r1,[sp,#armreg_r0] // saved R0
str r2,[sp,#armreg_fp] // saved FP
str r3,[sp,#armreg_ip] // saved IP
str r4,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
add r0,ip,#ARMREG_SIZE
str fp,[sp,#armreg_sp] // SP at time of interrupt
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_undefined_instruction
#endif
mov v1,#CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
b call_exception_handler
.code 32
software_interrupt:
sub sp,sp,#ARMREG_SIZE+16 // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
mrs r0,spsr
// Adjust PC according to CPU mode
tst r0,#CPSR_THUMB_ENABLE
subeq r3,lr,#4 // PC at time of interrupt (ARM)
subne r3,lr,#2 // PC at time of interrupt (thumb)
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str ip,[sp,#armreg_ip] // saved IP
str r3,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
add r0,sp,#ARMREG_SIZE+16
str r0,[sp,#armreg_sp] // SP at time of interrupt
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_software_interrupt
#endif
mov v1,#CYGNUM_HAL_EXCEPTION_INTERRUPT
b call_exception_handler
.code 32
abort_prefetch:
ldr sp,.__undef_exception_stack // get good stack
sub lr,lr,#4 // PC at time of interrupt
stmfd sp!,{r0,fp,ip,lr}
mrs r0,spsr
stmfd sp!,{r0}
mov ip,sp // save SP which will vanish with
// mode switch
mrs r0,cpsr // switch to Supervisor Mode
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_SUPERVISOR_MODE
msr cpsr,r0 // sp,lr are now old values
mov fp,sp
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
ldr sp,.__GDB_stack
cmp fp,sp // already on GDB stack?
bhi 10f
ldr r0,.__GDB_stack_base
cmp fp,r0
bls 10f // no - switch to GDB stack
// (already in sp)
mov sp,fp // yes - no switch
10:
#endif
sub sp,sp,#ARMREG_SIZE // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
ldmfd ip,{r0-r4} // saved registers
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str r1,[sp,#armreg_r0] // saved R0
str r2,[sp,#armreg_fp] // saved FP
str r3,[sp,#armreg_ip] // saved IP
str r4,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
add r0,ip,#ARMREG_SIZE
str fp,[sp,#armreg_sp] // SP at time of interrupt
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_abort_prefetch
#endif
mov v1,#CYGNUM_HAL_EXCEPTION_CODE_ACCESS
b call_exception_handler
.code 32
abort_data:
ldr sp,.__undef_exception_stack // get good stack
sub lr,lr,#4 // PC at time of interrupt
stmfd sp!,{r0,fp,ip,lr}
mrs r0,spsr
stmfd sp!,{r0}
mov ip,sp // save SP which will vanish with
// mode switch
mrs r0,cpsr // switch to Supervisor Mode
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_SUPERVISOR_MODE
msr cpsr,r0 // sp,lr are now old values
mov fp,sp
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
ldr sp,.__GDB_stack
cmp fp,sp // already on GDB stack?
bhi 10f
ldr r0,.__GDB_stack_base
cmp fp,r0
bls 10f // no - switch to GDB stack
// (already in sp)
mov sp,fp // yes - no switch
10:
#endif
sub sp,sp,#ARMREG_SIZE // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
ldmfd ip,{r0-r4} // saved registers
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str r1,[sp,#armreg_r0] // saved R0
str r2,[sp,#armreg_fp] // saved FP
str r3,[sp,#armreg_ip] // saved IP
str r4,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
add r0,ip,#ARMREG_SIZE
str fp,[sp,#armreg_sp] // SP at time of interrupt
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_abort_data
#endif
mov v1,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS
b call_exception_handler
//
// Dispatch an exception handler.
.code 32
call_exception_handler:
str v1,[sp,#armreg_vector]
mov r0,sp
THUMB_MODE(r9,10)
bl exception_handler
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_exception_handler_returned
#endif
ARM_MODE(r1,10)
// Restore [interrupted] context
mov ip,sp // get stack pointer
mrs r0,cpsr // move back to IRQ mode
orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
msr cpsr,r0
nop
nop
ldr lr,[ip,#armreg_lr]
ldr sp,[sp,#armreg_sp]
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_IRQ_MODE
msr cpsr,r0
mov sp,ip
ldr lr,[sp,#armreg_pc]
ldr r0,[sp,#armreg_cpsr]
ldr ip,[sp,#armreg_ip]
msr spsr,r0
ldmfd sp,{r0-r10,fp}
movs pc,lr // restore PC from LR, CPSR from SPSR
// Handle device interrupts
// This is slightly more complicated than the other exception handlers because
// it needs to interface with the kernel (if present).
.code 32
FIQ:
// We can get here from supervisor mode or from IRQ mode.
mrs r8,spsr // CPSR at time of interrupt
and r9,r8,#CPSR_MODE_BITS // isolate pre-interrupt mode
cmp r9,#CPSR_IRQ_MODE
bne 1f
// If FIQ interrupted IRQ mode, just return with FIQ disabled.
// The common interrupt handling takes care of the rest.
orr r8,r8,#CPSR_FIQ_DISABLE
msr spsr,r8
subs pc,lr,#4
1:
// If FIQ interrupted supervisor mode, switch to IRQ mode and
// fall through to IRQ handler.
ldr sp,.__exception_stack // get good stack to save lr and spsr
stmdb sp,{r8,lr}
mov r8,#CPSR_IRQ_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE
msr cpsr,r8 // switch to IRQ mode
ldr sp,.__exception_stack // get regs saved in FIQ mode
ldmdb sp,{sp,lr}
msr spsr,sp
// now it looks like we got an IRQ instead of an FIQ except that
// FIQ is disabled so we don't recurse.
//#define MODE_SWITCH
IRQ:
// This restores registers and stack from GBA bios
ldmfd r13!,{r0-r3,r12,r14}
// Note: I use this exception stack while saving the context because
// the current SP does not seem to be always valid in this CPU mode.
ldr sp,.__exception_stack // get good stack
sub lr,lr,#4 // PC at time of interrupt
stmfd sp!,{r0,fp,ip,lr}
mrs r0,spsr
stmfd sp!,{r0}
handle_IRQ_or_FIQ:
mov ip,sp // save SP which will vanish with
// mode switch
#ifdef MODE_SWITCH
mrs r0,cpsr // switch to Supervisor Mode
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_SUPERVISOR_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE
msr cpsr,r0 // sp,lr are now old values
#endif
mov fp,sp // save old SP
sub sp,sp,#ARMREG_SIZE // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
ldmfd ip,{r0-r4} // saved registers
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str r1,[sp,#armreg_r0] // saved R0
str r2,[sp,#armreg_fp] // saved FP
str r3,[sp,#armreg_ip] // saved IP
str r4,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
str fp,[sp,#armreg_sp] // SP at time of interrupt
mov r0,#CYGNUM_HAL_VECTOR_IRQ // FIXME: we don't distinguish
str r0,[sp,#armreg_vector] // FIQ and IRQ here
mov v6,sp // Save pointer to register frame
// mov r0,sp
// bl _show_frame_in
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// Switch to interrupt stack
ldr r2,.irq_level // current number of nested interrupts
ldr r0,[r2]
add r1,r0,#1
str r1,[r2] // if was zero, switch stacks
cmp r0,#0
moveq r1,sp // save old stack pointer
ldreq sp,.__interrupt_stack
stmeqfd sp!,{r1}
10:
#endif
// The entire CPU state is now stashed on the stack,
// increment the scheduler lock and handle the interrupt
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
.extern cyg_scheduler_sched_lock
ldr r3,.cyg_scheduler_sched_lock
ldr r4,[r3]
add r4,r4,#1
str r4,[r3]
#endif
THUMB_MODE(r3,10)
mov r0,v6
bl hal_IRQ_handler // determine interrupt source
mov v1,r0 // returned vector #
#if defined(CYGPKG_KERNEL_INSTRUMENT) && \
defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
ldr r0,=RAISE_INTR // arg0 = type = INTR,RAISE
mov r1,v1 // arg1 = vector
mov r2,#0 // arg2 = 0
bl cyg_instrument // call instrument function
#endif
ARM_MODE(r0,10)
mov r0,v1 // vector #
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
// If we are supporting Ctrl-C interrupts from GDB, we must squirrel
// away a pointer to the save interrupt state here so that we can
// plant a breakpoint at some later time.
.extern hal_saved_interrupt_state
ldr r2,=hal_saved_interrupt_state
str v6,[r2]
#endif
cmp r0,#CYGNUM_HAL_INTERRUPT_NONE // spurious interrupt
bne 10f
#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
mov r0,v6 // register frame
bl hal_spurious_IRQ
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
b spurious_IRQ
10: ldr r1,.hal_interrupt_data
ldr r1,[r1,v1,lsl #2] // handler data
ldr r2,.hal_interrupt_handlers
ldr v3,[r2,v1,lsl #2] // handler (indexed by vector #)
mov r2,v6 // register frame (this is necessary
// for the ISR too, for ^C detection)
#ifdef __thumb__
ldr lr,=10f
bx v3 // invoke handler (thumb mode)
.pool
.code 16
.thumb_func
IRQ_10T:
10: ldr r2,=15f
bx r2 // switch back to ARM mode
.pool
.code 32
15:
IRQ_15A:
#else
mov lr,pc // invoke handler (call indirect
mov pc,v3 // thru v3)
#endif
spurious_IRQ:
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// If we are returning from the last nested interrupt, move back
// to the thread stack. interrupt_end() must be called on the
// thread stack since it potentially causes a context switch.
ldr r2,.irq_level
ldr r3,[r2]
subs r1,r3,#1
str r1,[r2]
ldreq sp,[sp] // This should be the saved stack pointer
#endif
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
// The return value from the handler (in r0) will indicate whether a
// DSR is to be posted. Pass this together with a pointer to the
// interrupt object we have just used to the interrupt tidy up routine.
// don't run this for spurious interrupts!
cmp v1,#CYGNUM_HAL_INTERRUPT_NONE
beq 17f
ldr r1,.hal_interrupt_objects
ldr r1,[r1,v1,lsl #2]
mov r2,v6 // register frame
THUMB_MODE(r3,10)
bl interrupt_end // post any bottom layer handler
// threads and call scheduler
ARM_MODE(r1,10)
17:
#endif
// mov r0,sp
// bl show_frame_out
mov ip,sp // get stack pointer
#ifdef MODE_SWITCH
mrs r0,cpsr // move back to IRQ mode
orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
msr cpsr,r0
nop
nop
#endif
ldr lr,[ip,#armreg_lr]
ldr sp,[sp,#armreg_sp]
#ifdef MODE_SWITCH
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_IRQ_MODE
msr cpsr,r0
#endif
mov sp,ip
ldr lr,[sp,#armreg_pc]
ldr r0,[sp,#armreg_cpsr]
ldr ip,[sp,#armreg_ip]
msr spsr,r0
ldmfd sp,{r0-r10,fp}
movs pc,lr // restore PC from LR, CPSR from SPSR
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// Execute pending DSRs the interrupt stack
// Note: this can only be called from code running on a thread stack
FUNC_START_ARM(hal_interrupt_stack_call_pending_DSRs, r1)
stmfd sp!,{r4,r5,lr}
// Disable interrupts
mrs r4,cpsr // disable IRQ's
orr r2,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
bic r5,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
msr cpsr,r2
// Switch to interrupt stack
mov r3,sp // save old stack pointer
ldr sp,.__interrupt_stack
stmfd sp!,{r3} // stored at top of interrupt stack
ldr r2,.irq_level // current number of nested interrupts
ldr r3,[r2]
add r3,r3,#1 // bump nesting level
str r3,[r2]
msr cpsr,r5 // enable interrupts
THUMB_MODE(r1,20)
bl cyg_interrupt_call_pending_DSRs
ARM_MODE(r1,22)
// Disable interrupts
mrs r1,cpsr // disable IRQ's
orr r2,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
msr cpsr,r2
// Move back to the thread stack.
ldr r2,.irq_level
ldr r3,[r2]
sub r3,r3,#1 // decrement nesting level
str r3,[r2]
ldr sp,[sp] // This should be the saved stack pointer
msr cpsr,r4 // restore interrupts to original state
#ifdef __thumb__
ldmfd sp!,{r4,r5,lr} // return
bx lr
#else
ldmfd sp!,{r4,r5,pc} // return
#endif // __thumb__
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// Thumb-only support functions
#ifdef __thumb__
FUNC_START_ARM(hal_disable_interrupts, r1)
mrs r0,cpsr // current state
orr r1,r0,#0xC0 // mask both FIQ and IRQ
msr cpsr,r1
bx lr // exit, _old_ in r0
FUNC_START_ARM(hal_enable_interrupts, r1)
mrs r0,cpsr // current state
bic r1,r0,#0xC0 // mask both FIQ and IRQ
msr cpsr,r1
bx lr // exit
FUNC_START_ARM(hal_restore_interrupts, r1)
mrs r1,cpsr // current state
bic r1,r1,#0xC0 // mask out FIQ/IRQ bits
and r0,r0,#0xC0 // keep only FIQ/IRQ
orr r1,r1,r0 // mask both FIQ and IRQ
msr cpsr,r1
bx lr // exit
FUNC_START_ARM(hal_query_interrupts, r1)
mrs r0,cpsr // current state
bx lr // exit, state in r0
#endif // __thumb__
// Dummy/support functions
.global __gccmain
.global _psr
.global _sp
#ifdef __thumb__
.code 16
.thumb_func
__gccmain:
bx lr
.code 16
.thumb_func
_psr:
ARM_MODE(r1,10)
mrs r0,cpsr
bx lr
.code 16
.thumb_func
_sp:
mov r0,sp
bx lr
#else
__gccmain:
mov pc,lr
_psr:
mrs r0,cpsr
mov pc,lr
_sp:
mov r0,sp
mov pc,lr
#endif
//
// Pointers to various objects.
//
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
PTR(__GDB_stack_base)
PTR(__GDB_stack)
#endif
PTR(__startup_stack)
PTR(__exception_stack)
PTR(__undef_exception_stack)
PTR(__bss_start)
PTR(__bss_end)
PTR(_end)
PTR(__rom_data_start)
PTR(__ram_data_start)
PTR(__ram_data_end)
PTR(hal_interrupt_handlers)
PTR(hal_interrupt_data)
PTR(hal_interrupt_objects)
PTR(__exception_handlers)
PTR(init_flag)
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
PTR(cyg_scheduler_sched_lock)
#endif
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
PTR(irq_level)
PTR(__interrupt_stack)
#endif
PTR(hal_patch_vector_code)
//
// Identification - useful to find out when a system was configured
_eCos_id:
.asciz "eCos : " __DATE__
// -------------------------------------------------------------------------
// Interrupt vector tables.
// These tables contain the isr, data and object pointers used to deliver
// interrupts to user code.
// Despite appearances, their sizes are not #defines, but .equ symbols
// generated by magic without proper dependencies in arm.inc
// Recompiling will not DTRT without manual intervention.
.data
init_flag:
.balign 4
.long 0
.extern hal_default_isr
.globl hal_interrupt_handlers
hal_interrupt_handlers:
.rept CYGNUM_HAL_ISR_COUNT
.long hal_default_isr
.endr
.globl hal_interrupt_data
hal_interrupt_data:
.rept CYGNUM_HAL_ISR_COUNT
.long 0
.endr
.globl hal_interrupt_objects
hal_interrupt_objects:
.rept CYGNUM_HAL_ISR_COUNT
.long 0
.endr
// -------------------------------------------------------------------------
// Temporary interrupt stack
.section ".bss"
// Small stacks, only used for saving information between CPU modes
__exception_stack_base:
.rept 32
.long 0
.endr
__exception_stack:
.rept 32
.long 0
.endr
__undef_exception_stack:
// Runtime stack used during all interrupt processing
#ifndef CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
#define CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE 4096
#endif
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
.balign 16
.global cyg_interrupt_stack_base
cyg_interrupt_stack_base:
__interrupt_stack_base:
.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
.byte 0
.endr
.balign 16
.global cyg_interrupt_stack
cyg_interrupt_stack:
__interrupt_stack:
irq_level:
.long 0
#endif
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
.balign 16
__GDB_stack_base:
.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE // rather than 1k
.byte 0
.endr
__GDB_stack:
#endif
.balign 16
__startup_stack_base:
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
.rept 4096
#else
.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
#endif
.byte 0
.endr
.balign 16
__startup_stack:
#ifdef PLATFORM_EXTRAS
#include PLATFORM_EXTRAS
#endif
// --------------------------------------------------------------------------
// end of vectors.S
// #========================================================================
// #
// # vectors.S
// #
// # ARM exception vectors
// #
// #========================================================================
// ####COPYRIGHTBEGIN####
//
// -------------------------------------------
// The contents of this file are subject to the Red Hat eCos Public License
// Version 1.1 (the "License"); you may not use this file except in
// compliance with the License. You may obtain a copy of the License at
// http://www.redhat.com/
//
// Software distributed under the License is distributed on an "AS IS"
// basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
// License for the specific language governing rights and limitations under
// the License.
//
// The Original Code is eCos - Embedded Configurable Operating System,
// released September 30, 1998.
//
// The Initial Developer of the Original Code is Red Hat.
// Portions created by Red Hat are
// Copyright (C) 1998, 1999, 2000, 2001 Red Hat, Inc.
// All Rights Reserved.
// -------------------------------------------
//
// ####COPYRIGHTEND####
// #========================================================================
// ######DESCRIPTIONBEGIN####
// #
// # Author(s): nickg, gthomas
// # Contributors: nickg, gthomas
// # Date: 1999-02-20
// # Purpose: ARM exception vectors
// # Description: This file defines the code placed into the exception
// # vectors. It also contains the first level default VSRs
// # that save and restore state for both exceptions and
// # interrupts.
// #
// #####DESCRIPTIONEND####
// #
// #========================================================================
#include <pkgconf/hal.h>
#include <pkgconf/hal_arm.h>
#ifdef CYGPKG_KERNEL // no CDL yet
#include <pkgconf/kernel.h>
#else
# undef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
# undef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
#endif
#include <cyg/hal/hal_platform_setup.h>
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
// The CDL should enforce this
#undef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
#endif
#include "arm.inc"
#ifdef __thumb__
// Switch to thumb mode
#define THUMB_MODE(_r_, _l_) \
ldr _r_,=_l_ ## f+1 ;\
bx _r_ ;\
.pool ;\
.code 16 ;\
.thumb_func ;\
_l_:
// Switch to ARM mode
#define ARM_MODE(_r_, _l_) \
ldr _r_,=_l_ ## f ;\
bx _r_ ;\
.pool ;\
.code 32 ;\
_l_:
// Function definition, start executing body in ARM mode
#define FUNC_START_ARM(_name_, _r_) \
.code 16 ;\
.thumb_func ;\
.globl _name_ ;\
_name_: ;\
ldr _r_,=_name_ ## _ARM ;\
bx _r_ ;\
.code 32 ;\
_name_ ## _ARM:
#else
// Switch to thumb mode
#define THUMB_MODE(_r_, _l_)
// Switch to ARM mode
#define ARM_MODE(_r_, _l_)
// Function definition, start executing body in ARM mode
#define FUNC_START_ARM(_name_, _r_) \
.globl _name_; \
_name_:
#endif
#define PTR(name) \
.##name: .word name
// CYGHWR_HAL_ROM_VADDR is used when compiling for a different location
// from the base of ROM. hal_platform_setup.h might define it. For
// example, if flash is from 0x50000000 upwards (as on SA11x0), and we are
// to execute at 0x50040000, then we want the reset vector to point to
// 0x0004pqrs - the unmapped ROM address of the code - rather than
// 0x0000pqrs, which is the offset into our flash block.
//
// But usually it's not defined, so the behaviour is the obvious.
#ifndef UNMAPPED
#ifdef CYGHWR_HAL_ARM_HAS_MMU
# ifndef CYGHWR_HAL_ROM_VADDR
# define CYGHWR_HAL_ROM_VADDR __exception_handlers
# endif
# define UNMAPPED(x) ((x)-CYGHWR_HAL_ROM_VADDR)
#else
# define UNMAPPED(x) (x)
#endif
#endif
#define UNMAPPED_PTR(name) \
.##name: .word UNMAPPED(name)
.file "vectors.S"
// CYGHWR_LED_MACRO can be defined in hal_platform_setup.h. It's free to
// use r0+r1. Argument is in "\x" - cannot use macro arguments since the
// macro may contain #-chars and use of arguments cause these to be
// interpreted as CPP stringify operators.
// See example in PID hal_platform_setup.h.
#ifndef CYGHWR_LED_MACRO
#define CYGHWR_LED_MACRO
#endif
.macro LED x
CYGHWR_LED_MACRO
.endm
//==========================================================================
// Hardware exception vectors.
// This entire section will be copied to location 0x0000 at startup time.
//
.code 32
.section ".vectors","ax"
// This macro allows platforms to add their own code at the very start of
// the image. This may be required in some circumstances where eCos ROM
// based code does not run immediately upon reset and/or when some sort of
// special header is required at the start of the image.
#ifdef PLATFORM_PREAMBLE
PLATFORM_PREAMBLE
#endif
.global __exception_handlers
__exception_handlers:
#ifdef CYGSEM_HAL_ROM_RESET_USES_JUMP
// Assumption: ROM code has these vectors at the hardware reset address.
// A simple jump removes any address-space dependencies [i.e. safer]
b reset_vector // 0x00
#else
ldr pc,.reset_vector // 0x00
#endif
ldr pc,.undefined_instruction // 0x04
ldr pc,.software_interrupt // 0x08 start && software int
ldr pc,.abort_prefetch // 0x0C
ldr pc,.abort_data // 0x10
.word 0 // unused
ldr pc,.IRQ // 0x18
ldr pc,.FIQ // 0x1C
// The layout of these pointers should match the vector table above since
// they are copied in pairs.
.global vectors
vectors:
UNMAPPED_PTR(reset_vector) // 0x20
PTR(undefined_instruction) // 0x24
PTR(software_interrupt) // 0x28
PTR(abort_prefetch) // 0x2C
PTR(abort_data) // 0x30
.word 0 // 0x34
PTR(IRQ) // 0x38
PTR(FIQ) // 0x3c
#ifdef CYGSEM_HAL_ARM_PID_ANGEL_BOOT
PTR(start) // This is copied to 0x28 for bootup // 0x40
#endif
// location 0x40 is used for storing DRAM size if known
// for some platforms.
//
// "Vectors" - fixed location data items
// This section contains any data which might be shared between
// an eCos application and any other environment, e.g. the debug
// ROM.
//
.section ".fixed_vectors"
// Interrupt/exception VSR pointers
.globl hal_vsr_table
hal_vsr_table:
.rept 8
.long 0
.endr
.globl hal_dram_size
hal_dram_size:
.long 0
// what, if anything, hal_dram_type means is up to the platform
.globl hal_dram_type
hal_dram_type:
.long 0
.balign 16
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
// Vectors used to communicate between eCos and ROM environments
.globl hal_virtual_vector_table
hal_virtual_vector_table:
.rept CYGNUM_CALL_IF_TABLE_SIZE
.long 0
.endr
#endif
.balign 32
// Other vectors - this may include "fixed" locations
#ifdef PLATFORM_VECTORS
PLATFORM_VECTORS
#endif
.text
// Startup code which will get the machine into supervisor mode
.global reset_vector
.type reset_vector,function
reset_vector:
PLATFORM_SETUP1 // Early stage platform initialization
// which can set DRAM size at 0x40
// see <cyg/hal/hal_platform_setup.h>
// Come here to reset board
warm_reset:
#if defined(CYG_HAL_STARTUP_RAM) && \
!defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
mrs r7,cpsr // move back to IRQ mode
and r7,r7,#CPSR_MODE_BITS
cmp r7,#CPSR_SUPERVISOR_MODE
beq start
#endif
// We cannot access any LED registers until after PLATFORM_SETUP1
LED 7
mov r0,#0 // move vectors
ldr r1,=__exception_handlers
#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
// Wait with this if stubs are included (see further down).
ldr r2,[r1,#0x04] // undefined instruction
str r2,[r0,#0x04]
ldr r2,[r1,#0x24]
str r2,[r0,#0x24]
#endif
ldr r2,[r1,#0x08] // software interrupt
str r2,[r0,#0x08]
#if defined(CYGSEM_HAL_ARM_PID_ANGEL_BOOT)
// Ugly hack to get into supervisor mode
ldr r2,[r1,#0x40]
str r2,[r0,#0x28]
LED 6
swi // switch to supervisor mode
#endif
// =========================================================================
// Real startup code. We jump here from the reset vector to set up the world.
.globl start
start:
LED 5
#if defined(CYG_HAL_STARTUP_RAM) && \
!defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
// If we get restarted, hang here to avoid corrupting memory
ldr r0,.init_flag
ldr r1,[r0]
1: cmp r1,#0
bne 1b
ldr r1,init_done
str r1,[r0]
#endif
// Reset software interrupt pointer
mov r0,#0 // move vectors
ldr r1,.__exception_handlers
#if defined(CYG_HAL_STARTUP_RAM) && \
!defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
cmp r7,#CPSR_SUPERVISOR_MODE
beq 10f
#endif
ldr r2,[r1,#0x28] // software interrupt
str r2,[r0,#0x28]
10:
ldr r2,[r1,#0x18] // IRQ
str r2,[r0,#0x18]
ldr r2,[r1,#0x38]
str r2,[r0,#0x38]
ldr r2,[r1,#0x1C] // FIQ
str r2,[r0,#0x1C]
ldr r2,[r1,#0x3C]
str r2,[r0,#0x3C]
ldr r2,[r1,#0x0C] // abort (prefetch)
str r2,[r0,#0x0C]
ldr r2,[r1,#0x2C]
str r2,[r0,#0x2C]
ldr r2,[r1,#0x10] // abort (data)
str r2,[r0,#0x10]
ldr r2,[r1,#0x30]
str r2,[r0,#0x30]
LED 4
#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
// Set up reset vector
mov r0,#0
ldr r1,.__exception_handlers
ldr r2,[r1,#0x00] // reset vector intstruction
str r2,[r0,#0x00]
ldr r2,=warm_reset
str r2,[r0,#0x20]
// Relocate [copy] data from ROM to RAM
ldr r3,.__rom_data_start
ldr r4,.__ram_data_start
ldr r5,.__ram_data_end
cmp r4,r5 // jump if no data to move
beq 2f
sub r3,r3,#4 // loop adjustments
sub r4,r4,#4
1: ldr r0,[r3,#4]! // copy info
str r0,[r4,#4]!
cmp r4,r5
bne 1b
2:
#endif
// initialize interrupt/exception environments
ldr sp,.__startup_stack
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_IRQ_MODE)
msr cpsr,r0
ldr sp,.__exception_stack
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE)
msr cpsr,r0
ldr sp,.__exception_stack
// initialize CPSR (machine state register)
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
msr cpsr,r0
// Note: some functions in LIBGCC1 will cause a "restore from SPSR"!!
msr spsr,r0
// initialize stack
ldr sp,.__startup_stack
// clear BSS
ldr r1,.__bss_start
ldr r2,.__bss_end
mov r0,#0
cmp r1,r2
beq 2f
1: str r0,[r1],#4
cmp r1,r2
bne 1b
2:
// Run kernel + application in THUMB mode
THUMB_MODE(r1,10)
LED 3
// Call platform specific hardware initialization
bl hal_hardware_init
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
bl initialize_stub
// Now that stub is initialized, change vector. It is possible
// to single-step through most of the init code, except the below.
// Put a breakpoint at the call to cyg_hal_invoke_constructors to
// pass over this bit (s-s depends on internal state in the stub).
#endif
#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) || \
defined(CYGIMP_HAL_PROCESS_ALL_EXCEPTIONS)
mov r0,#0 // move vectors
ldr r1,=__exception_handlers
ldr r2,[r1,#0x04] // undefined instruction
str r2,[r0,#0x04]
ldr r2,[r1,#0x24]
str r2,[r0,#0x24]
#endif
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
.extern hal_ctrlc_isr_init
bl hal_ctrlc_isr_init
#endif
LED 2
// Run through static constructors
bl cyg_hal_invoke_constructors
LED 1
// This starts up the eCos kernel
bl cyg_start
_start_hang:
b _start_hang
.code 32
.global reset_platform
.type reset_platform,function
reset_platform:
#ifdef CYGSEM_HAL_ROM_MONITOR
// initialize CPSR (machine state register)
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
msr cpsr,r0
b warm_reset
#else
mov r0,#0
mov pc,r0 // Jump to reset vector
#endif
init_done:
.long 0xDEADB00B
//
// Exception handlers
// Assumption: get here from a Supervisor context [mode]
//
.code 32
undefined_instruction:
ldr sp,.__undef_exception_stack // get good stack
stmfd sp!,{r0,fp,ip,lr}
mrs r0,spsr
stmfd sp!,{r0}
mov ip,sp // save SP which will vanish with
// mode switch
mrs r0,cpsr // switch to Supervisor Mode
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_SUPERVISOR_MODE
msr cpsr,r0 // sp,lr are now old values
mov fp,sp
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
ldr sp,.__GDB_stack
cmp fp,sp // already on GDB stack?
bhi 10f
ldr r0,.__GDB_stack_base
cmp fp,r0
bls 10f // no - switch to GDB stack
// (already in sp)
mov sp,fp // yes - no switch
10:
#endif
sub sp,sp,#ARMREG_SIZE // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
ldmfd ip,{r0-r4} // saved registers
// Adjust PC according to CPU mode
tst r0,#CPSR_THUMB_ENABLE
subeq r4,r4,#4 // PC at time of interrupt (ARM)
subne r4,r4,#2 // PC at time of interrupt (thumb)
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str r1,[sp,#armreg_r0] // saved R0
str r2,[sp,#armreg_fp] // saved FP
str r3,[sp,#armreg_ip] // saved IP
str r4,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
add r0,ip,#ARMREG_SIZE
str fp,[sp,#armreg_sp] // SP at time of interrupt
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_undefined_instruction
#endif
mov v1,#CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
b call_exception_handler
.code 32
software_interrupt:
sub sp,sp,#ARMREG_SIZE+16 // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
mrs r0,spsr
// Adjust PC according to CPU mode
tst r0,#CPSR_THUMB_ENABLE
subeq r3,lr,#4 // PC at time of interrupt (ARM)
subne r3,lr,#2 // PC at time of interrupt (thumb)
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str ip,[sp,#armreg_ip] // saved IP
str r3,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
add r0,sp,#ARMREG_SIZE+16
str r0,[sp,#armreg_sp] // SP at time of interrupt
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_software_interrupt
#endif
mov v1,#CYGNUM_HAL_EXCEPTION_INTERRUPT
b call_exception_handler
.code 32
abort_prefetch:
ldr sp,.__undef_exception_stack // get good stack
sub lr,lr,#4 // PC at time of interrupt
stmfd sp!,{r0,fp,ip,lr}
mrs r0,spsr
stmfd sp!,{r0}
mov ip,sp // save SP which will vanish with
// mode switch
mrs r0,cpsr // switch to Supervisor Mode
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_SUPERVISOR_MODE
msr cpsr,r0 // sp,lr are now old values
mov fp,sp
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
ldr sp,.__GDB_stack
cmp fp,sp // already on GDB stack?
bhi 10f
ldr r0,.__GDB_stack_base
cmp fp,r0
bls 10f // no - switch to GDB stack
// (already in sp)
mov sp,fp // yes - no switch
10:
#endif
sub sp,sp,#ARMREG_SIZE // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
ldmfd ip,{r0-r4} // saved registers
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str r1,[sp,#armreg_r0] // saved R0
str r2,[sp,#armreg_fp] // saved FP
str r3,[sp,#armreg_ip] // saved IP
str r4,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
add r0,ip,#ARMREG_SIZE
str fp,[sp,#armreg_sp] // SP at time of interrupt
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_abort_prefetch
#endif
mov v1,#CYGNUM_HAL_EXCEPTION_CODE_ACCESS
b call_exception_handler
.code 32
abort_data:
ldr sp,.__undef_exception_stack // get good stack
sub lr,lr,#4 // PC at time of interrupt
stmfd sp!,{r0,fp,ip,lr}
mrs r0,spsr
stmfd sp!,{r0}
mov ip,sp // save SP which will vanish with
// mode switch
mrs r0,cpsr // switch to Supervisor Mode
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_SUPERVISOR_MODE
msr cpsr,r0 // sp,lr are now old values
mov fp,sp
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
ldr sp,.__GDB_stack
cmp fp,sp // already on GDB stack?
bhi 10f
ldr r0,.__GDB_stack_base
cmp fp,r0
bls 10f // no - switch to GDB stack
// (already in sp)
mov sp,fp // yes - no switch
10:
#endif
sub sp,sp,#ARMREG_SIZE // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
ldmfd ip,{r0-r4} // saved registers
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str r1,[sp,#armreg_r0] // saved R0
str r2,[sp,#armreg_fp] // saved FP
str r3,[sp,#armreg_ip] // saved IP
str r4,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
add r0,ip,#ARMREG_SIZE
str fp,[sp,#armreg_sp] // SP at time of interrupt
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_abort_data
#endif
mov v1,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS
b call_exception_handler
//
// Dispatch an exception handler.
.code 32
call_exception_handler:
str v1,[sp,#armreg_vector]
mov r0,sp
THUMB_MODE(r9,10)
bl exception_handler
#ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
mov r0,sp
bl cyg_hal_report_exception_handler_returned
#endif
ARM_MODE(r1,10)
// Restore [interrupted] context
mov ip,sp // get stack pointer
mrs r0,cpsr // move back to IRQ mode
orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
msr cpsr,r0
nop
nop
ldr lr,[ip,#armreg_lr]
ldr sp,[sp,#armreg_sp]
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_IRQ_MODE
msr cpsr,r0
mov sp,ip
ldr lr,[sp,#armreg_pc]
ldr r0,[sp,#armreg_cpsr]
ldr ip,[sp,#armreg_ip]
msr spsr,r0
ldmfd sp,{r0-r10,fp}
movs pc,lr // restore PC from LR, CPSR from SPSR
// Handle device interrupts
// This is slightly more complicated than the other exception handlers because
// it needs to interface with the kernel (if present).
.code 32
FIQ:
// We can get here from supervisor mode or from IRQ mode.
mrs r8,spsr // CPSR at time of interrupt
and r9,r8,#CPSR_MODE_BITS // isolate pre-interrupt mode
cmp r9,#CPSR_IRQ_MODE
bne 1f
// If FIQ interrupted IRQ mode, just return with FIQ disabled.
// The common interrupt handling takes care of the rest.
orr r8,r8,#CPSR_FIQ_DISABLE
msr spsr,r8
subs pc,lr,#4
1:
// If FIQ interrupted supervisor mode, switch to IRQ mode and
// fall through to IRQ handler.
ldr sp,.__exception_stack // get good stack to save lr and spsr
stmdb sp,{r8,lr}
mov r8,#CPSR_IRQ_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE
msr cpsr,r8 // switch to IRQ mode
ldr sp,.__exception_stack // get regs saved in FIQ mode
ldmdb sp,{sp,lr}
msr spsr,sp
// now it looks like we got an IRQ instead of an FIQ except that
// FIQ is disabled so we don't recurse.
IRQ:
// Note: I use this exception stack while saving the context because
// the current SP does not seem to be always valid in this CPU mode.
ldr sp,.__exception_stack // get good stack
sub lr,lr,#4 // PC at time of interrupt
stmfd sp!,{r0,fp,ip,lr}
mrs r0,spsr
stmfd sp!,{r0}
handle_IRQ_or_FIQ:
mov ip,sp // save SP which will vanish with
// mode switch
mrs r0,cpsr // switch to Supervisor Mode
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_SUPERVISOR_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE
msr cpsr,r0 // sp,lr are now old values
mov fp,sp // save old SP
sub sp,sp,#ARMREG_SIZE // make space for frame
stmea sp,{r0-r10,fp} // save immediately visible registers
ldmfd ip,{r0-r4} // saved registers
str r0,[sp,#armreg_cpsr] // CPSR at time of interrupt
str r1,[sp,#armreg_r0] // saved R0
str r2,[sp,#armreg_fp] // saved FP
str r3,[sp,#armreg_ip] // saved IP
str r4,[sp,#armreg_pc] // PC at time of interrupt
str lr,[sp,#armreg_lr] // LR at time of interrupt
str fp,[sp,#armreg_sp] // SP at time of interrupt
mov r0,#CYGNUM_HAL_VECTOR_IRQ // FIXME: we don't distinguish
str r0,[sp,#armreg_vector] // FIQ and IRQ here
mov v6,sp // Save pointer to register frame
// mov r0,sp
// bl _show_frame_in
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// Switch to interrupt stack
ldr r2,.irq_level // current number of nested interrupts
ldr r0,[r2]
add r1,r0,#1
str r1,[r2] // if was zero, switch stacks
cmp r0,#0
moveq r1,sp // save old stack pointer
ldreq sp,.__interrupt_stack
stmeqfd sp!,{r1}
10:
#endif
// The entire CPU state is now stashed on the stack,
// increment the scheduler lock and handle the interrupt
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
.extern cyg_scheduler_sched_lock
ldr r3,.cyg_scheduler_sched_lock
ldr r4,[r3]
add r4,r4,#1
str r4,[r3]
#endif
THUMB_MODE(r3,10)
mov r0,v6
bl hal_IRQ_handler // determine interrupt source
mov v1,r0 // returned vector #
#if defined(CYGPKG_KERNEL_INSTRUMENT) && \
defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
ldr r0,=RAISE_INTR // arg0 = type = INTR,RAISE
mov r1,v1 // arg1 = vector
mov r2,#0 // arg2 = 0
bl cyg_instrument // call instrument function
#endif
ARM_MODE(r0,10)
mov r0,v1 // vector #
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
|| defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
// If we are supporting Ctrl-C interrupts from GDB, we must squirrel
// away a pointer to the save interrupt state here so that we can
// plant a breakpoint at some later time.
.extern hal_saved_interrupt_state
ldr r2,=hal_saved_interrupt_state
str v6,[r2]
#endif
cmp r0,#CYGNUM_HAL_INTERRUPT_NONE // spurious interrupt
bne 10f
#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
mov r0,v6 // register frame
bl hal_spurious_IRQ
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
b spurious_IRQ
10: ldr r1,.hal_interrupt_data
ldr r1,[r1,v1,lsl #2] // handler data
ldr r2,.hal_interrupt_handlers
ldr v3,[r2,v1,lsl #2] // handler (indexed by vector #)
mov r2,v6 // register frame (this is necessary
// for the ISR too, for ^C detection)
#ifdef __thumb__
ldr lr,=10f
bx v3 // invoke handler (thumb mode)
.pool
.code 16
.thumb_func
IRQ_10T:
10: ldr r2,=15f
bx r2 // switch back to ARM mode
.pool
.code 32
15:
IRQ_15A:
#else
mov lr,pc // invoke handler (call indirect
mov pc,v3 // thru v3)
#endif
spurious_IRQ:
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// If we are returning from the last nested interrupt, move back
// to the thread stack. interrupt_end() must be called on the
// thread stack since it potentially causes a context switch.
ldr r2,.irq_level
ldr r3,[r2]
subs r1,r3,#1
str r1,[r2]
ldreq sp,[sp] // This should be the saved stack pointer
#endif
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
// The return value from the handler (in r0) will indicate whether a
// DSR is to be posted. Pass this together with a pointer to the
// interrupt object we have just used to the interrupt tidy up routine.
// don't run this for spurious interrupts!
cmp v1,#CYGNUM_HAL_INTERRUPT_NONE
beq 17f
ldr r1,.hal_interrupt_objects
ldr r1,[r1,v1,lsl #2]
mov r2,v6 // register frame
THUMB_MODE(r3,10)
bl interrupt_end // post any bottom layer handler
// threads and call scheduler
ARM_MODE(r1,10)
17:
#endif
// mov r0,sp
// bl show_frame_out
mov ip,sp // get stack pointer
mrs r0,cpsr // move back to IRQ mode
orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
msr cpsr,r0
nop
nop
ldr lr,[ip,#armreg_lr]
ldr sp,[sp,#armreg_sp]
bic r0,r0,#CPSR_MODE_BITS
orr r0,r0,#CPSR_IRQ_MODE
msr cpsr,r0
mov sp,ip
ldr lr,[sp,#armreg_pc]
ldr r0,[sp,#armreg_cpsr]
ldr ip,[sp,#armreg_ip]
msr spsr,r0
ldmfd sp,{r0-r10,fp}
movs pc,lr // restore PC from LR, CPSR from SPSR
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// Execute pending DSRs the interrupt stack
// Note: this can only be called from code running on a thread stack
FUNC_START_ARM(hal_interrupt_stack_call_pending_DSRs, r1)
stmfd sp!,{r4,r5,lr}
// Disable interrupts
mrs r4,cpsr // disable IRQ's
orr r2,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
bic r5,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
msr cpsr,r2
// Switch to interrupt stack
mov r3,sp // save old stack pointer
ldr sp,.__interrupt_stack
stmfd sp!,{r3} // stored at top of interrupt stack
ldr r2,.irq_level // current number of nested interrupts
ldr r3,[r2]
add r3,r3,#1 // bump nesting level
str r3,[r2]
msr cpsr,r5 // enable interrupts
THUMB_MODE(r1,20)
bl cyg_interrupt_call_pending_DSRs
ARM_MODE(r1,22)
// Disable interrupts
mrs r1,cpsr // disable IRQ's
orr r2,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
msr cpsr,r2
// Move back to the thread stack.
ldr r2,.irq_level
ldr r3,[r2]
sub r3,r3,#1 // decrement nesting level
str r3,[r2]
ldr sp,[sp] // This should be the saved stack pointer
msr cpsr,r4 // restore interrupts to original state
#ifdef __thumb__
ldmfd sp!,{r4,r5,lr} // return
bx lr
#else
ldmfd sp!,{r4,r5,pc} // return
#endif // __thumb__
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// Thumb-only support functions
#ifdef __thumb__
FUNC_START_ARM(hal_disable_interrupts, r1)
mrs r0,cpsr // current state
orr r1,r0,#0xC0 // mask both FIQ and IRQ
msr cpsr,r1
bx lr // exit, _old_ in r0
FUNC_START_ARM(hal_enable_interrupts, r1)
mrs r0,cpsr // current state
bic r1,r0,#0xC0 // mask both FIQ and IRQ
msr cpsr,r1
bx lr // exit
FUNC_START_ARM(hal_restore_interrupts, r1)
mrs r1,cpsr // current state
bic r1,r1,#0xC0 // mask out FIQ/IRQ bits
and r0,r0,#0xC0 // keep only FIQ/IRQ
orr r1,r1,r0 // mask both FIQ and IRQ
msr cpsr,r1
bx lr // exit
FUNC_START_ARM(hal_query_interrupts, r1)
mrs r0,cpsr // current state
bx lr // exit, state in r0
#endif // __thumb__
// Dummy/support functions
.global __gccmain
.global _psr
.global _sp
#ifdef __thumb__
.code 16
.thumb_func
__gccmain:
bx lr
.code 16
.thumb_func
_psr:
ARM_MODE(r1,10)
mrs r0,cpsr
bx lr
.code 16
.thumb_func
_sp:
mov r0,sp
bx lr
#else
__gccmain:
mov pc,lr
_psr:
mrs r0,cpsr
mov pc,lr
_sp:
mov r0,sp
mov pc,lr
#endif
//
// Pointers to various objects.
//
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
PTR(__GDB_stack_base)
PTR(__GDB_stack)
#endif
PTR(__startup_stack)
PTR(__exception_stack)
PTR(__undef_exception_stack)
PTR(__bss_start)
PTR(__bss_end)
PTR(_end)
PTR(__rom_data_start)
PTR(__ram_data_start)
PTR(__ram_data_end)
PTR(hal_interrupt_handlers)
PTR(hal_interrupt_data)
PTR(hal_interrupt_objects)
PTR(__exception_handlers)
PTR(init_flag)
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
PTR(cyg_scheduler_sched_lock)
#endif
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
PTR(irq_level)
PTR(__interrupt_stack)
#endif
//
// Identification - useful to find out when a system was configured
_eCos_id:
.asciz "eCos : " __DATE__
// -------------------------------------------------------------------------
// Interrupt vector tables.
// These tables contain the isr, data and object pointers used to deliver
// interrupts to user code.
// Despite appearances, their sizes are not #defines, but .equ symbols
// generated by magic without proper dependencies in arm.inc
// Recompiling will not DTRT without manual intervention.
.data
init_flag:
.balign 4
.long 0
.extern hal_default_isr
.globl hal_interrupt_handlers
hal_interrupt_handlers:
.rept CYGNUM_HAL_ISR_COUNT
.long hal_default_isr
.endr
.globl hal_interrupt_data
hal_interrupt_data:
.rept CYGNUM_HAL_ISR_COUNT
.long 0
.endr
.globl hal_interrupt_objects
hal_interrupt_objects:
.rept CYGNUM_HAL_ISR_COUNT
.long 0
.endr
// -------------------------------------------------------------------------
// Temporary interrupt stack
.section ".bss"
// Small stacks, only used for saving information between CPU modes
__exception_stack_base:
.rept 32
.long 0
.endr
__exception_stack:
.rept 32
.long 0
.endr
__undef_exception_stack:
// Runtime stack used during all interrupt processing
#ifndef CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
#define CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE 4096
#endif
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
.balign 16
.global cyg_interrupt_stack_base
cyg_interrupt_stack_base:
__interrupt_stack_base:
.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
.byte 0
.endr
.balign 16
.global cyg_interrupt_stack
cyg_interrupt_stack:
__interrupt_stack:
irq_level:
.long 0
#endif
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
.balign 16
__GDB_stack_base:
.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE // rather than 1k
.byte 0
.endr
__GDB_stack:
#endif
.balign 16
__startup_stack_base:
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
.rept 512
#else
.rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
#endif
.byte 0
.endr
.balign 16
__startup_stack:
#ifdef PLATFORM_EXTRAS
#include PLATFORM_EXTRAS
#endif
// --------------------------------------------------------------------------
// end of vectors.S