1 // #========================================================================
5 // # ARM exception vectors
7 // #========================================================================
8 //####ECOSGPLCOPYRIGHTBEGIN####
9 // -------------------------------------------
10 // This file is part of eCos, the Embedded Configurable Operating System.
11 // Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
13 // eCos is free software; you can redistribute it and/or modify it under
14 // the terms of the GNU General Public License as published by the Free
15 // Software Foundation; either version 2 or (at your option) any later version.
17 // eCos is distributed in the hope that it will be useful, but WITHOUT ANY
18 // WARRANTY; without even the implied warranty of MERCHANTABILITY or
19 // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22 // You should have received a copy of the GNU General Public License along
23 // with eCos; if not, write to the Free Software Foundation, Inc.,
24 // 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
26 // As a special exception, if other files instantiate templates or use macros
27 // or inline functions from this file, or you compile this file and link it
28 // with other works to produce a work based on this file, this file does not
29 // by itself cause the resulting work to be covered by the GNU General Public
30 // License. However the source code for this file must still be made available
31 // in accordance with section (3) of the GNU General Public License.
33 // This exception does not invalidate any other reasons why a work based on
34 // this file might be covered by the GNU General Public License.
36 // Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
37 // at http://sources.redhat.com/ecos/ecos-license/
38 // -------------------------------------------
39 //####ECOSGPLCOPYRIGHTEND####
40 // #========================================================================
41 // ######DESCRIPTIONBEGIN####
43 // # Author(s): nickg, gthomas
44 // # Contributors: nickg, gthomas
46 // # Purpose: ARM exception vectors
47 // # Description: This file defines the code placed into the exception
48 // # vectors. It also contains the first level default VSRs
49 // # that save and restore state for both exceptions and
52 // #####DESCRIPTIONEND####
54 // #========================================================================
56 #include <pkgconf/hal.h>
57 #include <pkgconf/hal_arm.h>
58 #ifdef CYGPKG_KERNEL // no CDL yet
59 #include <pkgconf/kernel.h>
61 # undef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
62 # undef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
64 #include <cyg/hal/hal_platform_setup.h>
66 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
67 // The CDL should enforce this
68 #undef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
74 // Switch to thumb mode
75 #define THUMB_MODE(_r_, _l_) \
76 ldr _r_,=_l_ ## f+1 ;\
83 // Call thumb function from ARM mode, return to ARM
85 #define THUMB_CALL(_r_, _l_, _f_) \
99 #define ARM_MODE(_r_, _l_) \
106 // Function definition, start executing body in ARM mode
107 #define FUNC_START_ARM(_name_, _r_) \
112 ldr _r_,=_name_ ## _ARM ;\
119 // Switch to thumb mode
120 #define THUMB_MODE(_r_, _l_)
123 #define THUMB_CALL(_r_, _l_, _f_) \
126 // Switch to ARM mode
127 #define ARM_MODE(_r_, _l_)
129 // Function definition, start executing body in ARM mode
130 #define FUNC_START_ARM(_name_, _r_) \
141 // CYGHWR_HAL_ROM_VADDR is used when compiling for a different location
142 // from the base of ROM. hal_platform_setup.h might define it. For
143 // example, if flash is from 0x50000000 upwards (as on SA11x0), and we are
144 // to execute at 0x50040000, then we want the reset vector to point to
145 // 0x0004pqrs - the unmapped ROM address of the code - rather than
146 // 0x0000pqrs, which is the offset into our flash block.
148 // But usually it's not defined, so the behaviour is the obvious.
151 #ifdef CYGHWR_HAL_ARM_HAS_MMU
152 # ifndef CYGHWR_HAL_ROM_VADDR
153 # define CYGHWR_HAL_ROM_VADDR __exception_handlers
155 # define UNMAPPED(x) ((x)-CYGHWR_HAL_ROM_VADDR)
157 # define UNMAPPED(x) (x)
161 #define UNMAPPED_PTR(name) \
162 .##name: .word UNMAPPED(name)
167 // CYGHWR_LED_MACRO can be defined in hal_platform_setup.h. It's free to
168 // use r0+r1. Argument is in "\x" - cannot use macro arguments since the
169 // macro may contain #-chars and use of arguments cause these to be
170 // interpreted as CPP stringify operators.
171 // See example in PID hal_platform_setup.h.
172 #ifndef CYGHWR_LED_MACRO
173 #define CYGHWR_LED_MACRO
181 //==========================================================================
182 // Hardware exception vectors.
183 // This entire section will be copied to location 0x0000 at startup time.
186 .section ".vectors","ax"
188 // This macro allows platforms to add their own code at the very start of
189 // the image. This may be required in some circumstances where eCos ROM
190 // based code does not run immediately upon reset and/or when some sort of
191 // special header is required at the start of the image.
192 #ifdef PLATFORM_PREAMBLE
196 .global __exception_handlers
197 __exception_handlers:
198 #ifdef CYGSEM_HAL_ROM_RESET_USES_JUMP
199 // Assumption: ROM code has these vectors at the hardware reset address.
200 // A simple jump removes any address-space dependencies [i.e. safer]
201 b reset_vector // 0x00
203 ldr pc,.reset_vector // 0x00
205 ldr pc,.undefined_instruction // 0x04
206 ldr pc,.software_interrupt // 0x08 start && software int
207 ldr pc,.abort_prefetch // 0x0C
208 ldr pc,.abort_data // 0x10
209 #ifdef CYGNUM_HAL_ARM_VECTOR_0x14
210 .word CYGNUM_HAL_ARM_VECTOR_0x14
217 // The layout of these pointers should match the vector table above since
218 // they are copied in pairs.
221 UNMAPPED_PTR(reset_vector) // 0x20
222 PTR(undefined_instruction) // 0x24
223 PTR(software_interrupt) // 0x28
224 PTR(abort_prefetch) // 0x2C
225 PTR(abort_data) // 0x30
229 #ifdef CYGSEM_HAL_ARM_PID_ANGEL_BOOT
230 PTR(start) // This is copied to 0x28 for bootup // 0x40
232 // location 0x40 is used for storing DRAM size if known
233 // for some platforms.
236 // "Vectors" - fixed location data items
237 // This section contains any data which might be shared between
238 // an eCos application and any other environment, e.g. the debug
241 .section ".fixed_vectors"
242 // Interrupt/exception VSR pointers
252 // what, if anything, hal_dram_type means is up to the platform
258 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
259 // Vectors used to communicate between eCos and ROM environments
260 .globl hal_virtual_vector_table
261 hal_virtual_vector_table:
262 .rept CYGNUM_CALL_IF_TABLE_SIZE
267 #ifdef CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
268 .balign 16 // Should be at 0x50
270 .long 0 // Must be 'MICE'
271 .long 0 // Pointer to thread support vector
272 .long 0 // eCos executing flag
273 .long 0 // Must be 'GDB '
274 #endif // CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
277 // Other vectors - this may include "fixed" locations
278 #ifdef PLATFORM_VECTORS
283 // Startup code which will get the machine into supervisor mode
285 .type reset_vector,function
287 PLATFORM_SETUP1 // Early stage platform initialization
288 // which can set DRAM size at 0x40
289 // see <cyg/hal/hal_platform_setup.h>
291 // Come here to reset board
294 #if defined(CYG_HAL_STARTUP_RAM) && \
295 !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
296 mrs r7,cpsr // move back to IRQ mode
297 and r7,r7,#CPSR_MODE_BITS
298 cmp r7,#CPSR_SUPERVISOR_MODE
302 // We cannot access any LED registers until after PLATFORM_SETUP1
305 mov r0,#0 // move vectors
306 ldr r1,=__exception_handlers
307 #ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
308 // Wait with this if stubs are included (see further down).
309 ldr r2,[r1,#0x04] // undefined instruction
314 ldr r2,[r1,#0x08] // software interrupt
317 #ifdef CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
318 ldr r2,=ice_thread_vector
319 sub r2,r2,r1 // compute fixed (low memory) address
320 ldr r3,=0x4D494345 // 'MICE'
322 ldr r3,=hal_arm_ice_thread_handler
326 ldr r3,=0x47444220 // 'GDB '
328 #endif // CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
330 #if defined(CYGSEM_HAL_ARM_PID_ANGEL_BOOT)
331 // Ugly hack to get into supervisor mode
337 swi // switch to supervisor mode
340 // =========================================================================
341 // Real startup code. We jump here from the reset vector to set up the world.
347 #if defined(CYG_HAL_STARTUP_RAM) && \
348 !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
349 // If we get restarted, hang here to avoid corrupting memory
358 // Reset software interrupt pointer
359 mov r0,#0 // move vectors
360 ldr r1,.__exception_handlers
361 #if defined(CYG_HAL_STARTUP_RAM) && \
362 !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
363 cmp r7,#CPSR_SUPERVISOR_MODE
366 ldr r2,[r1,#0x28] // software interrupt
369 ldr r2,[r1,#0x18] // IRQ
373 ldr r2,[r1,#0x1C] // FIQ
377 ldr r2,[r1,#0x0C] // abort (prefetch)
381 ldr r2,[r1,#0x10] // abort (data)
388 #if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
389 // Set up reset vector
391 ldr r1,.__exception_handlers
392 ldr r2,[r1,#0x00] // reset vector intstruction
396 // Relocate [copy] data from ROM to RAM
397 ldr r3,.__rom_data_start
398 ldr r4,.__ram_data_start
399 ldr r5,.__ram_data_end
400 cmp r4,r5 // jump if no data to move
402 sub r3,r3,#4 // loop adjustments
404 1: ldr r0,[r3,#4]! // copy info
411 // initialize interrupt/exception environments
412 ldr sp,.__startup_stack
413 mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_IRQ_MODE)
415 ldr sp,.__exception_stack
416 mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE)
418 ldr sp,.__exception_stack
420 // initialize CPSR (machine state register)
421 mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
424 // Note: some functions in LIBGCC1 will cause a "restore from SPSR"!!
428 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
429 // use interrupt stack for system initialization since it's bigger
430 // than the "startup" stack in this configuration
431 ldr sp,.__interrupt_stack
433 ldr sp,.__startup_stack
447 // Run kernel + application in THUMB mode
452 // Call platform specific hardware initialization
455 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
458 // Now that stub is initialized, change vector. It is possible
459 // to single-step through most of the init code, except the below.
460 // Put a breakpoint at the call to cyg_hal_invoke_constructors to
461 // pass over this bit (s-s depends on internal state in the stub).
464 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) || \
465 defined(CYGIMP_HAL_PROCESS_ALL_EXCEPTIONS)
466 mov r0,#0 // move vectors
467 ldr r1,=__exception_handlers
468 ldr r2,[r1,#0x04] // undefined instruction
474 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
475 || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
476 .extern hal_ctrlc_isr_init
477 bl hal_ctrlc_isr_init
482 // Run through static constructors
483 bl cyg_hal_invoke_constructors
487 // This starts up the eCos kernel
488 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
489 ldr r1,=__startup_stack
497 .global reset_platform
498 .type reset_platform,function
500 #ifdef CYGSEM_HAL_ROM_MONITOR
501 // initialize CPSR (machine state register)
502 mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
507 mov pc,r0 // Jump to reset vector
514 // Exception handlers
515 // Assumption: get here from a non-user context [mode]
516 // except in case of standalone app. running in user mode
517 // (CYGOPT_HAL_ARM_WITH_USER_MODE should have been defined)
520 undefined_instruction:
521 ldr sp,.__undef_exception_stack // get good stack
522 stmfd sp!,{r0-r5} // save some supervisor regs
524 tst r1,#CPSR_THUMB_ENABLE
525 subeq r0,lr,#4 // PC at time of interrupt (ARM)
526 subne r0,lr,#2 // PC at time of interrupt (thumb)
527 mov r2,#CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
529 b call_exception_handler
534 ldr r8,.__undef_exception_stack // get good stack
535 stmfd r8!,{r0-r5} // save some supervisor regs
539 tst r1,#CPSR_THUMB_ENABLE
540 subeq r0,lr,#4 // PC at time of SWI (ARM)
541 subne r0,lr,#2 // PC at time of SWI (thumb)
542 mov r2,#CYGNUM_HAL_EXCEPTION_INTERRUPT
543 b call_exception_handler
547 ldr sp,.__undef_exception_stack // get good stack
548 stmfd sp!,{r0-r5} // save some supervisor regs
549 sub r0,lr,#4 // PC at time of interrupt
551 mov r2,#CYGNUM_HAL_EXCEPTION_CODE_ACCESS
553 b call_exception_handler
557 ldr sp,.__undef_exception_stack // get good stack
558 stmfd sp!,{r0-r5} // save some supervisor regs
559 sub r0,lr,#4 // PC at time of interrupt
561 mov r2,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS
563 b call_exception_handler
566 // Dispatch an exception handler.
569 call_exception_handler:
574 // r3 = pointer to temp save area
575 // r2 = vector number
576 // r1 = exception psr
579 // [r3+20]: exception r5
580 // [r3+16]: exception r4
581 // [r3+12]: exception r3
582 // [r3+8] : exception r2
583 // [r3+4] : exception r1
584 // [r3] : exception r0
586 mrs r4,cpsr // switch to Supervisor Mode
587 bic r4,r4,#CPSR_MODE_BITS
588 orr r4,r4,#CPSR_SUPERVISOR_MODE
591 mov r5,sp // save original svc sp
592 mov r4,lr // and original svc lr
593 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
594 // Make sure we use the GDB stack.
596 cmp r5,sp // already on GDB stack?
598 ldr r4,.__GDB_stack_base
604 // r5 holds original svc sp, current sp is stack to use
605 // r4 holds original svc lr, which must also be preserved
608 stmfd sp!,{r0-r2,r4,r5} // push svc_sp, svc_lr, vector, psr, pc
610 #ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
611 // did exception occur in user mode ?
612 and r2, r1, #CPSR_MODE_BITS
613 cmp r2, #CPSR_USER_MODE
615 stmfd sp, {r8-r12, sp, lr}^ // get user mode regs
621 // switch to pre-exception mode to get banked regs
622 mov r0,sp // r0 survives mode switch
623 mrs r2,cpsr // Save current psr for return
624 orr r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
625 bic r1,r1,#CPSR_THUMB_ENABLE
627 stmfd r0!,{r8-r12,sp,lr}
628 msr cpsr,r2 // back to svc mode
629 mov sp,r0 // update stack pointer
631 // now save pre-exception r0-r7 on current stack
635 // SP needs fixing if exception occured in SVC mode.
636 // The original SVC LR is still in place so that
637 // does not need to be fixed here.
638 ldr r1,[sp,#armreg_cpsr]
639 and r1,r1,#CPSR_MODE_BITS
640 cmp r1,#CPSR_SUPERVISOR_MODE
641 ldreq r1,[sp,#armreg_svcsp]
642 streq r1,[sp,#armreg_sp]
644 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
647 ldr r2,[sp,#armreg_vector]
648 ldr r1,[r1,r2,lsl #2]
656 // call exception handler
660 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
662 bl cyg_hal_report_exception_handler_returned
668 // Return from exception
670 return_from_exception:
672 ldr r0,[sp,#armreg_cpsr]
674 // return to supervisor mode is simple
675 and r1,r0,#CPSR_MODE_BITS
676 cmp r1,#CPSR_SUPERVISOR_MODE
678 #ifndef CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR
680 ldmeqfd sp,{r0-r14,pc}^
682 // we must take care of not corrupting the current (svc)
683 // spsr which happens to be also the pre-exception spsr
685 tst r0, #CPSR_THUMB_ENABLE
687 // when returning to thumb/svc mode, there is no easy way to preserve
688 // spsr. It is possible to do so, but would add a lot of instructions.
689 // The purpose of CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR is to allow stepping
690 // through SWI exception handling code, so not preserving spsr in this
691 // case should be okay.
693 ldmnefd sp,{r0-r14,pc}^
695 // we are returning to arm/svc mode thus we must restore the
696 // pre-exception cpsr before returning to interrupted code
698 ldmfd sp, {r0-r14, pc}
700 // we are not returning to svc mode thus we can safely restore
705 #ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
706 // are we returning to user mode ?
707 and r2, r1, #CPSR_MODE_BITS
708 cmp r2, #CPSR_USER_MODE
709 add r2, sp, #armreg_r8
711 ldmfd r2, {r8-r14}^ // restore user mode regs
716 add r2, sp, #armreg_r8
719 // return to other non-user modes is a little trickier
722 // switch to pre-exception mode and restore r8-r14
724 orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
725 bic r0,r0,#CPSR_THUMB_ENABLE
728 msr cpsr, r1 // back to svc mode
731 // move sp,lr and pc for final load
732 ldr r0,[sp,#armreg_svcsp]
733 str r0,[sp,#armreg_r8]
734 ldr r0,[sp,#armreg_svclr]
735 str r0,[sp,#armreg_r9]
736 ldr r0,[sp,#armreg_pc]
737 str r0,[sp,#armreg_r10]
739 // restore r0-r7,sp,lr and return from exception
740 ldmfd sp,{r0-r7,sp,lr,pc}^
742 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
744 .word 0 // placeholder for reset
745 .word cyg_hal_report_undefined_instruction
746 .word cyg_hal_report_software_interrupt
747 .word cyg_hal_report_abort_prefetch
748 .word cyg_hal_report_abort_data
753 // Handle device interrupts
754 // This is slightly more complicated than the other exception handlers because
755 // it needs to interface with the kernel (if present).
756 // Assumption: can get here from any mode, including user mode
757 // (spurious interrupt while standalone app. is running in user mode)
761 // We can get here from any non-user mode.
762 mrs r8,spsr // CPSR at time of interrupt
763 and r9,r8,#CPSR_MODE_BITS // isolate pre-interrupt mode
764 cmp r9,#CPSR_IRQ_MODE
766 // If FIQ interrupted IRQ mode, just return with FIQ disabled.
767 // The common interrupt handling takes care of the rest.
768 orr r8,r8,#CPSR_FIQ_DISABLE
772 // If FIQ interrupted other non-user mode, switch to IRQ mode and
773 // fall through to IRQ handler.
774 ldr sp,.__exception_stack // get good stack to save lr and spsr
776 mov r8,#CPSR_IRQ_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE
777 msr cpsr,r8 // switch to IRQ mode
778 ldr sp,.__exception_stack // get regs saved in FIQ mode
782 // now it looks like we got an IRQ instead of an FIQ except that
783 // FIQ is disabled so we don't recurse.
785 // Note: I use this exception stack while saving the context because
786 // the current SP does not seem to be always valid in this CPU mode.
787 ldr sp,.__exception_stack // get good stack
788 stmfd sp!,{r0-r5} // save some supervisor regs
789 sub r0,lr,#4 // PC at time of interrupt
791 mov r2,#CYGNUM_HAL_VECTOR_IRQ
794 mrs r4,cpsr // switch to Supervisor Mode
795 bic r4,r4,#CPSR_MODE_BITS
796 // When handling an IRQ we must disable FIQ unless the current
797 // mode in CPSR is IRQ. If we were to get a FIQ while in another
798 // mode, the FIQ handling code would transform the FIQ into an
799 // IRQ and call the non-reentrant IRQ handler again. As a result,
800 // for example, the stack pointer would be set to the beginning
801 // of the exception_stack clobbering the registers we have just
803 orr r4,r4,#CPSR_SUPERVISOR_MODE|CPSR_FIQ_DISABLE
806 mov r5,sp // save original svc sp
807 mov r4,lr // save original svc lr
808 stmfd sp!,{r0-r2,r4,r5} // push svc_sp, svc_lr, vector, psr, pc
810 #ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
811 // did exception occur in user mode ?
812 and r2, r1, #CPSR_MODE_BITS
813 cmp r2, #CPSR_USER_MODE
815 stmfd sp, {r8-r12, sp, lr}^ // get user mode regs
821 // switch to pre-exception mode to get banked regs
822 mov r0,sp // r0 survives mode switch
823 mrs r2,cpsr // Save current psr for return
824 orr r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
825 bic r1,r1,#CPSR_THUMB_ENABLE
827 stmfd r0!,{r8-r12,sp,lr}
828 msr cpsr,r2 // back to svc mode
829 mov sp,r0 // update stack pointer
832 // now save pre-exception r0-r7 on current stack
836 // sp needs fixing if exception occured in SVC mode.
837 ldr r1,[sp,#armreg_cpsr]
838 and r1,r1,#CPSR_MODE_BITS
839 cmp r1,#CPSR_SUPERVISOR_MODE
840 ldreq r1,[sp,#armreg_svcsp]
841 streq r1,[sp,#armreg_sp]
843 mov v6,sp // Save pointer to register frame
848 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
849 // Switch to interrupt stack
850 ldr r2,.irq_level // current number of nested interrupts
853 str r1,[r2] // if was zero, switch stacks
855 moveq r1,sp // save old stack pointer
856 ldreq sp,.__interrupt_stack
861 // The entire CPU state is now stashed on the stack,
862 // increment the scheduler lock and handle the interrupt
864 #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
865 .extern cyg_scheduler_sched_lock
866 ldr r3,.cyg_scheduler_sched_lock
875 bl hal_IRQ_handler // determine interrupt source
876 mov v1,r0 // returned vector #
878 #if defined(CYGPKG_KERNEL_INSTRUMENT) && \
879 defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
880 ldr r0,=RAISE_INTR // arg0 = type = INTR,RAISE
881 mov r1,v1 // arg1 = vector
882 mov r2,#0 // arg2 = 0
883 bl cyg_instrument // call instrument function
888 mov r0,v1 // vector #
890 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
891 || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
892 // If we are supporting Ctrl-C interrupts from GDB, we must squirrel
893 // away a pointer to the save interrupt state here so that we can
894 // plant a breakpoint at some later time.
896 .extern hal_saved_interrupt_state
897 ldr r2,=hal_saved_interrupt_state
901 cmp r0,#CYGNUM_HAL_INTERRUPT_NONE // spurious interrupt
904 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
905 // Acknowledge the interrupt
906 THUMB_CALL(r1,12,hal_interrupt_acknowledge)
908 mov r0,v6 // register frame
909 THUMB_CALL(r1,12,hal_spurious_IRQ)
910 #endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
913 10: ldr r1,.hal_interrupt_data
914 ldr r1,[r1,v1,lsl #2] // handler data
915 ldr r2,.hal_interrupt_handlers
916 ldr v3,[r2,v1,lsl #2] // handler (indexed by vector #)
917 mov r2,v6 // register frame (this is necessary
918 // for the ISR too, for ^C detection)
922 bx v3 // invoke handler (thumb mode)
928 bx r2 // switch back to ARM mode
934 mov lr,pc // invoke handler (call indirect
935 mov pc,v3 // thru v3)
940 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
941 // If we are returning from the last nested interrupt, move back
942 // to the thread stack. interrupt_end() must be called on the
943 // thread stack since it potentially causes a context switch.
948 ldreq sp,[sp] // This should be the saved stack pointer
950 // The return value from the handler (in r0) will indicate whether a
951 // DSR is to be posted. Pass this together with a pointer to the
952 // interrupt object we have just used to the interrupt tidy up routine.
954 // don't run this for spurious interrupts!
955 cmp v1,#CYGNUM_HAL_INTERRUPT_NONE
957 ldr r1,.hal_interrupt_objects
958 ldr r1,[r1,v1,lsl #2]
959 mov r2,v6 // register frame
963 bl interrupt_end // post any bottom layer handler
964 // threads and call scheduler
971 // return from IRQ is same as return from exception
972 b return_from_exception
974 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
975 // Execute pending DSRs the interrupt stack
976 // Note: this can only be called from code running on a thread stack
977 FUNC_START_ARM(hal_interrupt_stack_call_pending_DSRs, r1)
979 // Disable interrupts
980 mrs r4,cpsr // disable IRQ's
981 orr r2,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
982 bic r5,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
984 // Switch to interrupt stack
985 mov r3,sp // save old stack pointer
986 ldr sp,.__interrupt_stack
987 stmfd sp!,{r3} // stored at top of interrupt stack
988 ldr r2,.irq_level // current number of nested interrupts
990 add r3,r3,#1 // bump nesting level
992 msr cpsr,r5 // enable interrupts
996 bl cyg_interrupt_call_pending_DSRs
1001 // Disable interrupts
1002 mrs r1,cpsr // disable IRQ's
1003 orr r2,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
1006 // Move back to the thread stack.
1009 sub r3,r3,#1 // decrement nesting level
1011 ldr sp,[sp] // This should be the saved stack pointer
1012 msr cpsr,r4 // restore interrupts to original state
1015 ldmfd sp!,{r4,r5,lr} // return
1018 ldmfd sp!,{r4,r5,pc} // return
1020 #endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1022 // Thumb-only support functions
1025 FUNC_START_ARM(hal_disable_interrupts, r1)
1026 mrs r0,cpsr // current state
1027 orr r1,r0,#0xC0 // mask both FIQ and IRQ
1029 bx lr // exit, _old_ in r0
1031 FUNC_START_ARM(hal_enable_interrupts, r1)
1032 mrs r0,cpsr // current state
1033 bic r1,r0,#0xC0 // mask both FIQ and IRQ
1037 FUNC_START_ARM(hal_restore_interrupts, r1)
1038 mrs r1,cpsr // current state
1039 bic r1,r1,#0xC0 // mask out FIQ/IRQ bits
1040 and r0,r0,#0xC0 // keep only FIQ/IRQ
1041 orr r1,r1,r0 // mask both FIQ and IRQ
1045 FUNC_START_ARM(hal_query_interrupts, r1)
1046 mrs r0,cpsr // current state
1047 bx lr // exit, state in r0
1051 // Dummy/support functions
1090 // Pointers to various objects.
1092 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
1093 PTR(__GDB_stack_base)
1096 PTR(__startup_stack)
1097 PTR(__exception_stack)
1098 PTR(__undef_exception_stack)
1102 PTR(__rom_data_start)
1103 PTR(__ram_data_start)
1105 PTR(hal_interrupt_handlers)
1106 PTR(hal_interrupt_data)
1107 PTR(hal_interrupt_objects)
1108 PTR(__exception_handlers)
1110 #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
1111 PTR(cyg_scheduler_sched_lock)
1113 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1115 PTR(__interrupt_stack)
1117 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
1122 // Identification - useful to find out when a system was configured
1124 .asciz "eCos : " __DATE__
1127 // -------------------------------------------------------------------------
1128 // Interrupt vector tables.
1129 // These tables contain the isr, data and object pointers used to deliver
1130 // interrupts to user code.
1132 // Despite appearances, their sizes are not #defines, but .equ symbols
1133 // generated by magic without proper dependencies in arm.inc
1134 // Recompiling will not DTRT without manual intervention.
1142 .extern hal_default_isr
1144 .globl hal_interrupt_handlers
1145 hal_interrupt_handlers:
1146 .rept CYGNUM_HAL_ISR_COUNT
1147 .long hal_default_isr
1150 .globl hal_interrupt_data
1152 .rept CYGNUM_HAL_ISR_COUNT
1156 .globl hal_interrupt_objects
1157 hal_interrupt_objects:
1158 .rept CYGNUM_HAL_ISR_COUNT
1162 // -------------------------------------------------------------------------
1163 // Temporary interrupt stack
1167 // Small stacks, only used for saving information between CPU modes
1168 __exception_stack_base:
1176 __undef_exception_stack:
1178 // Runtime stack used during all interrupt processing
1179 #ifndef CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
1180 #define CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE 4096
1182 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1184 .global cyg_interrupt_stack_base
1185 cyg_interrupt_stack_base:
1186 __interrupt_stack_base:
1187 .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
1191 .global cyg_interrupt_stack
1192 cyg_interrupt_stack:
1198 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
1201 .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE // rather than 1k
1207 __startup_stack_base:
1208 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1211 .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
1218 #ifdef PLATFORM_EXTRAS
1219 #include PLATFORM_EXTRAS
1222 // --------------------------------------------------------------------------