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
213 // The layout of these pointers should match the vector table above since
214 // they are copied in pairs.
217 UNMAPPED_PTR(reset_vector) // 0x20
218 PTR(undefined_instruction) // 0x24
219 PTR(software_interrupt) // 0x28
220 PTR(abort_prefetch) // 0x2C
221 PTR(abort_data) // 0x30
225 #ifdef CYGSEM_HAL_ARM_PID_ANGEL_BOOT
226 PTR(start) // This is copied to 0x28 for bootup // 0x40
228 // location 0x40 is used for storing DRAM size if known
229 // for some platforms.
232 // "Vectors" - fixed location data items
233 // This section contains any data which might be shared between
234 // an eCos application and any other environment, e.g. the debug
237 .section ".fixed_vectors"
238 // Interrupt/exception VSR pointers
248 // what, if anything, hal_dram_type means is up to the platform
254 #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
255 // Vectors used to communicate between eCos and ROM environments
256 .globl hal_virtual_vector_table
257 hal_virtual_vector_table:
258 .rept CYGNUM_CALL_IF_TABLE_SIZE
263 #ifdef CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
264 .balign 16 // Should be at 0x50
266 .long 0 // Must be 'MICE'
267 .long 0 // Pointer to thread support vector
268 .long 0 // eCos executing flag
269 .long 0 // Must be 'GDB '
270 #endif // CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
273 // Other vectors - this may include "fixed" locations
274 #ifdef PLATFORM_VECTORS
279 // Startup code which will get the machine into supervisor mode
281 .type reset_vector,function
283 PLATFORM_SETUP1 // Early stage platform initialization
284 // which can set DRAM size at 0x40
285 // see <cyg/hal/hal_platform_setup.h>
287 // Come here to reset board
290 #if defined(CYG_HAL_STARTUP_RAM) && \
291 !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
292 mrs r7,cpsr // move back to IRQ mode
293 and r7,r7,#CPSR_MODE_BITS
294 cmp r7,#CPSR_SUPERVISOR_MODE
298 // We cannot access any LED registers until after PLATFORM_SETUP1
301 mov r0,#0 // move vectors
302 ldr r1,=__exception_handlers
303 #ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
304 // Wait with this if stubs are included (see further down).
305 ldr r2,[r1,#0x04] // undefined instruction
310 ldr r2,[r1,#0x08] // software interrupt
313 #ifdef CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
314 ldr r2,=ice_thread_vector
315 sub r2,r2,r1 // compute fixed (low memory) address
316 ldr r3,=0x4D494345 // 'MICE'
318 ldr r3,=hal_arm_ice_thread_handler
322 ldr r3,=0x47444220 // 'GDB '
324 #endif // CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
326 #if defined(CYGSEM_HAL_ARM_PID_ANGEL_BOOT)
327 // Ugly hack to get into supervisor mode
333 swi // switch to supervisor mode
336 // =========================================================================
337 // Real startup code. We jump here from the reset vector to set up the world.
343 #if defined(CYG_HAL_STARTUP_RAM) && \
344 !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
345 // If we get restarted, hang here to avoid corrupting memory
354 // Reset software interrupt pointer
355 mov r0,#0 // move vectors
356 ldr r1,.__exception_handlers
357 #if defined(CYG_HAL_STARTUP_RAM) && \
358 !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
359 cmp r7,#CPSR_SUPERVISOR_MODE
362 ldr r2,[r1,#0x28] // software interrupt
365 ldr r2,[r1,#0x18] // IRQ
369 ldr r2,[r1,#0x1C] // FIQ
373 ldr r2,[r1,#0x0C] // abort (prefetch)
377 ldr r2,[r1,#0x10] // abort (data)
384 #if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
385 // Set up reset vector
387 ldr r1,.__exception_handlers
388 ldr r2,[r1,#0x00] // reset vector intstruction
392 // Relocate [copy] data from ROM to RAM
393 ldr r3,.__rom_data_start
394 ldr r4,.__ram_data_start
395 ldr r5,.__ram_data_end
396 cmp r4,r5 // jump if no data to move
398 sub r3,r3,#4 // loop adjustments
400 1: ldr r0,[r3,#4]! // copy info
407 // initialize interrupt/exception environments
408 ldr sp,.__startup_stack
409 mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_IRQ_MODE)
411 ldr sp,.__exception_stack
412 mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE)
414 ldr sp,.__exception_stack
416 // initialize CPSR (machine state register)
417 mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
420 // Note: some functions in LIBGCC1 will cause a "restore from SPSR"!!
424 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
425 // use interrupt stack for system initialization since it's bigger
426 // than the "startup" stack in this configuration
427 ldr sp,.__interrupt_stack
429 ldr sp,.__startup_stack
443 // Run kernel + application in THUMB mode
448 // Call platform specific hardware initialization
451 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
454 // Now that stub is initialized, change vector. It is possible
455 // to single-step through most of the init code, except the below.
456 // Put a breakpoint at the call to cyg_hal_invoke_constructors to
457 // pass over this bit (s-s depends on internal state in the stub).
460 #if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) || \
461 defined(CYGIMP_HAL_PROCESS_ALL_EXCEPTIONS)
462 mov r0,#0 // move vectors
463 ldr r1,=__exception_handlers
464 ldr r2,[r1,#0x04] // undefined instruction
470 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
471 || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
472 .extern hal_ctrlc_isr_init
473 bl hal_ctrlc_isr_init
478 // Run through static constructors
479 bl cyg_hal_invoke_constructors
483 // This starts up the eCos kernel
484 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
485 ldr r1,=__startup_stack
493 .global reset_platform
494 .type reset_platform,function
496 #ifdef CYGSEM_HAL_ROM_MONITOR
497 // initialize CPSR (machine state register)
498 mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
503 mov pc,r0 // Jump to reset vector
510 // Exception handlers
511 // Assumption: get here from a non-user context [mode]
512 // except in case of standalone app. running in user mode
513 // (CYGOPT_HAL_ARM_WITH_USER_MODE should have been defined)
516 undefined_instruction:
517 ldr sp,.__undef_exception_stack // get good stack
518 stmfd sp!,{r0-r5} // save some supervisor regs
520 tst r1,#CPSR_THUMB_ENABLE
521 subeq r0,lr,#4 // PC at time of interrupt (ARM)
522 subne r0,lr,#2 // PC at time of interrupt (thumb)
523 mov r2,#CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
525 b call_exception_handler
530 ldr r8,.__undef_exception_stack // get good stack
531 stmfd r8!,{r0-r5} // save some supervisor regs
535 tst r1,#CPSR_THUMB_ENABLE
536 subeq r0,lr,#4 // PC at time of SWI (ARM)
537 subne r0,lr,#2 // PC at time of SWI (thumb)
538 mov r2,#CYGNUM_HAL_EXCEPTION_INTERRUPT
539 b call_exception_handler
543 ldr sp,.__undef_exception_stack // get good stack
544 stmfd sp!,{r0-r5} // save some supervisor regs
545 sub r0,lr,#4 // PC at time of interrupt
547 mov r2,#CYGNUM_HAL_EXCEPTION_CODE_ACCESS
549 b call_exception_handler
553 ldr sp,.__undef_exception_stack // get good stack
554 stmfd sp!,{r0-r5} // save some supervisor regs
555 sub r0,lr,#4 // PC at time of interrupt
557 mov r2,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS
559 b call_exception_handler
562 // Dispatch an exception handler.
565 call_exception_handler:
570 // r3 = pointer to temp save area
571 // r2 = vector number
572 // r1 = exception psr
575 // [r3+20]: exception r5
576 // [r3+16]: exception r4
577 // [r3+12]: exception r3
578 // [r3+8] : exception r2
579 // [r3+4] : exception r1
580 // [r3] : exception r0
582 mrs r4,cpsr // switch to Supervisor Mode
583 bic r4,r4,#CPSR_MODE_BITS
584 orr r4,r4,#CPSR_SUPERVISOR_MODE
587 mov r5,sp // save original svc sp
588 mov r4,lr // and original svc lr
589 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
590 // Make sure we use the GDB stack.
592 cmp r5,sp // already on GDB stack?
594 ldr r4,.__GDB_stack_base
600 // r5 holds original svc sp, current sp is stack to use
601 // r4 holds original svc lr, which must also be preserved
604 stmfd sp!,{r0-r2,r4,r5} // push svc_sp, svc_lr, vector, psr, pc
606 #ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
607 // did exception occur in user mode ?
608 and r2, r1, #CPSR_MODE_BITS
609 cmp r2, #CPSR_USER_MODE
611 stmfd sp, {r8-r12, sp, lr}^ // get user mode regs
617 // switch to pre-exception mode to get banked regs
618 mov r0,sp // r0 survives mode switch
619 mrs r2,cpsr // Save current psr for return
620 orr r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
621 bic r1,r1,#CPSR_THUMB_ENABLE
623 stmfd r0!,{r8-r12,sp,lr}
624 msr cpsr,r2 // back to svc mode
625 mov sp,r0 // update stack pointer
627 // now save pre-exception r0-r7 on current stack
631 // SP needs fixing if exception occured in SVC mode.
632 // The original SVC LR is still in place so that
633 // does not need to be fixed here.
634 ldr r1,[sp,#armreg_cpsr]
635 and r1,r1,#CPSR_MODE_BITS
636 cmp r1,#CPSR_SUPERVISOR_MODE
637 ldreq r1,[sp,#armreg_svcsp]
638 streq r1,[sp,#armreg_sp]
640 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
643 ldr r2,[sp,#armreg_vector]
644 ldr r1,[r1,r2,lsl #2]
652 // call exception handler
656 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
658 bl cyg_hal_report_exception_handler_returned
664 // Return from exception
666 return_from_exception:
668 ldr r0,[sp,#armreg_cpsr]
670 // return to supervisor mode is simple
671 and r1,r0,#CPSR_MODE_BITS
672 cmp r1,#CPSR_SUPERVISOR_MODE
674 #ifndef CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR
676 ldmeqfd sp,{r0-r14,pc}^
678 // we must take care of not corrupting the current (svc)
679 // spsr which happens to be also the pre-exception spsr
681 tst r0, #CPSR_THUMB_ENABLE
683 // when returning to thumb/svc mode, there is no easy way to preserve
684 // spsr. It is possible to do so, but would add a lot of instructions.
685 // The purpose of CYGOPT_HAL_ARM_PRESERVE_SVC_SPSR is to allow stepping
686 // through SWI exception handling code, so not preserving spsr in this
687 // case should be okay.
689 ldmnefd sp,{r0-r14,pc}^
691 // we are returning to arm/svc mode thus we must restore the
692 // pre-exception cpsr before returning to interrupted code
694 ldmfd sp, {r0-r14, pc}
696 // we are not returning to svc mode thus we can safely restore
701 #ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
702 // are we returning to user mode ?
703 and r2, r1, #CPSR_MODE_BITS
704 cmp r2, #CPSR_USER_MODE
705 add r2, sp, #armreg_r8
707 ldmfd r2, {r8-r14}^ // restore user mode regs
712 add r2, sp, #armreg_r8
715 // return to other non-user modes is a little trickier
718 // switch to pre-exception mode and restore r8-r14
720 orr r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
721 bic r0,r0,#CPSR_THUMB_ENABLE
724 msr cpsr, r1 // back to svc mode
727 // move sp,lr and pc for final load
728 ldr r0,[sp,#armreg_svcsp]
729 str r0,[sp,#armreg_r8]
730 ldr r0,[sp,#armreg_svclr]
731 str r0,[sp,#armreg_r9]
732 ldr r0,[sp,#armreg_pc]
733 str r0,[sp,#armreg_r10]
735 // restore r0-r7,sp,lr and return from exception
736 ldmfd sp,{r0-r7,sp,lr,pc}^
738 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
740 .word 0 // placeholder for reset
741 .word cyg_hal_report_undefined_instruction
742 .word cyg_hal_report_software_interrupt
743 .word cyg_hal_report_abort_prefetch
744 .word cyg_hal_report_abort_data
749 // Handle device interrupts
750 // This is slightly more complicated than the other exception handlers because
751 // it needs to interface with the kernel (if present).
752 // Assumption: can get here from any mode, including user mode
753 // (spurious interrupt while standalone app. is running in user mode)
757 // We can get here from any non-user mode.
758 mrs r8,spsr // CPSR at time of interrupt
759 and r9,r8,#CPSR_MODE_BITS // isolate pre-interrupt mode
760 cmp r9,#CPSR_IRQ_MODE
762 // If FIQ interrupted IRQ mode, just return with FIQ disabled.
763 // The common interrupt handling takes care of the rest.
764 orr r8,r8,#CPSR_FIQ_DISABLE
768 // If FIQ interrupted other non-user mode, switch to IRQ mode and
769 // fall through to IRQ handler.
770 ldr sp,.__exception_stack // get good stack to save lr and spsr
772 mov r8,#CPSR_IRQ_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE
773 msr cpsr,r8 // switch to IRQ mode
774 ldr sp,.__exception_stack // get regs saved in FIQ mode
778 // now it looks like we got an IRQ instead of an FIQ except that
779 // FIQ is disabled so we don't recurse.
781 // Note: I use this exception stack while saving the context because
782 // the current SP does not seem to be always valid in this CPU mode.
783 ldr sp,.__exception_stack // get good stack
784 stmfd sp!,{r0-r5} // save some supervisor regs
785 sub r0,lr,#4 // PC at time of interrupt
787 mov r2,#CYGNUM_HAL_VECTOR_IRQ
792 mrs r4,cpsr // switch to Supervisor Mode
793 bic r4,r4,#CPSR_MODE_BITS
794 orr r4,r4,#CPSR_SUPERVISOR_MODE
797 mov r5,sp // save original svc sp
798 mov r4,lr // save original svc lr
799 stmfd sp!,{r0-r2,r4,r5} // push svc_sp, svc_lr, vector, psr, pc
801 #ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
802 // did exception occur in user mode ?
803 and r2, r1, #CPSR_MODE_BITS
804 cmp r2, #CPSR_USER_MODE
806 stmfd sp, {r8-r12, sp, lr}^ // get user mode regs
812 // switch to pre-exception mode to get banked regs
813 mov r0,sp // r0 survives mode switch
814 mrs r2,cpsr // Save current psr for return
815 orr r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
816 bic r1,r1,#CPSR_THUMB_ENABLE
818 stmfd r0!,{r8-r12,sp,lr}
819 msr cpsr,r2 // back to svc mode
820 mov sp,r0 // update stack pointer
823 // now save pre-exception r0-r7 on current stack
827 // sp needs fixing if exception occured in SVC mode.
828 ldr r1,[sp,#armreg_cpsr]
829 and r1,r1,#CPSR_MODE_BITS
830 cmp r1,#CPSR_SUPERVISOR_MODE
831 ldreq r1,[sp,#armreg_svcsp]
832 streq r1,[sp,#armreg_sp]
834 mov v6,sp // Save pointer to register frame
839 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
840 // Switch to interrupt stack
841 ldr r2,.irq_level // current number of nested interrupts
844 str r1,[r2] // if was zero, switch stacks
846 moveq r1,sp // save old stack pointer
847 ldreq sp,.__interrupt_stack
852 // The entire CPU state is now stashed on the stack,
853 // increment the scheduler lock and handle the interrupt
855 #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
856 .extern cyg_scheduler_sched_lock
857 ldr r3,.cyg_scheduler_sched_lock
866 bl hal_IRQ_handler // determine interrupt source
867 mov v1,r0 // returned vector #
869 #if defined(CYGPKG_KERNEL_INSTRUMENT) && \
870 defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
871 ldr r0,=RAISE_INTR // arg0 = type = INTR,RAISE
872 mov r1,v1 // arg1 = vector
873 mov r2,#0 // arg2 = 0
874 bl cyg_instrument // call instrument function
879 mov r0,v1 // vector #
881 #if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
882 || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
883 // If we are supporting Ctrl-C interrupts from GDB, we must squirrel
884 // away a pointer to the save interrupt state here so that we can
885 // plant a breakpoint at some later time.
887 .extern hal_saved_interrupt_state
888 ldr r2,=hal_saved_interrupt_state
892 cmp r0,#CYGNUM_HAL_INTERRUPT_NONE // spurious interrupt
895 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
896 // Acknowledge the interrupt
897 THUMB_CALL(r1,12,hal_interrupt_acknowledge)
899 mov r0,v6 // register frame
900 THUMB_CALL(r1,12,hal_spurious_IRQ)
901 #endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
904 10: ldr r1,.hal_interrupt_data
905 ldr r1,[r1,v1,lsl #2] // handler data
906 ldr r2,.hal_interrupt_handlers
907 ldr v3,[r2,v1,lsl #2] // handler (indexed by vector #)
908 mov r2,v6 // register frame (this is necessary
909 // for the ISR too, for ^C detection)
913 bx v3 // invoke handler (thumb mode)
919 bx r2 // switch back to ARM mode
925 mov lr,pc // invoke handler (call indirect
926 mov pc,v3 // thru v3)
931 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
932 // If we are returning from the last nested interrupt, move back
933 // to the thread stack. interrupt_end() must be called on the
934 // thread stack since it potentially causes a context switch.
939 ldreq sp,[sp] // This should be the saved stack pointer
941 // The return value from the handler (in r0) will indicate whether a
942 // DSR is to be posted. Pass this together with a pointer to the
943 // interrupt object we have just used to the interrupt tidy up routine.
945 // don't run this for spurious interrupts!
946 cmp v1,#CYGNUM_HAL_INTERRUPT_NONE
948 ldr r1,.hal_interrupt_objects
949 ldr r1,[r1,v1,lsl #2]
950 mov r2,v6 // register frame
954 bl interrupt_end // post any bottom layer handler
955 // threads and call scheduler
962 // return from IRQ is same as return from exception
963 b return_from_exception
965 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
966 // Execute pending DSRs the interrupt stack
967 // Note: this can only be called from code running on a thread stack
968 FUNC_START_ARM(hal_interrupt_stack_call_pending_DSRs, r1)
970 // Disable interrupts
971 mrs r4,cpsr // disable IRQ's
972 orr r2,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
973 bic r5,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
975 // Switch to interrupt stack
976 mov r3,sp // save old stack pointer
977 ldr sp,.__interrupt_stack
978 stmfd sp!,{r3} // stored at top of interrupt stack
979 ldr r2,.irq_level // current number of nested interrupts
981 add r3,r3,#1 // bump nesting level
983 msr cpsr,r5 // enable interrupts
987 bl cyg_interrupt_call_pending_DSRs
992 // Disable interrupts
993 mrs r1,cpsr // disable IRQ's
994 orr r2,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
997 // Move back to the thread stack.
1000 sub r3,r3,#1 // decrement nesting level
1002 ldr sp,[sp] // This should be the saved stack pointer
1003 msr cpsr,r4 // restore interrupts to original state
1006 ldmfd sp!,{r4,r5,lr} // return
1009 ldmfd sp!,{r4,r5,pc} // return
1011 #endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1013 // Thumb-only support functions
1016 FUNC_START_ARM(hal_disable_interrupts, r1)
1017 mrs r0,cpsr // current state
1018 orr r1,r0,#0xC0 // mask both FIQ and IRQ
1020 bx lr // exit, _old_ in r0
1022 FUNC_START_ARM(hal_enable_interrupts, r1)
1023 mrs r0,cpsr // current state
1024 bic r1,r0,#0xC0 // mask both FIQ and IRQ
1028 FUNC_START_ARM(hal_restore_interrupts, r1)
1029 mrs r1,cpsr // current state
1030 bic r1,r1,#0xC0 // mask out FIQ/IRQ bits
1031 and r0,r0,#0xC0 // keep only FIQ/IRQ
1032 orr r1,r1,r0 // mask both FIQ and IRQ
1036 FUNC_START_ARM(hal_query_interrupts, r1)
1037 mrs r0,cpsr // current state
1038 bx lr // exit, state in r0
1042 // Dummy/support functions
1081 // Pointers to various objects.
1083 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
1084 PTR(__GDB_stack_base)
1087 PTR(__startup_stack)
1088 PTR(__exception_stack)
1089 PTR(__undef_exception_stack)
1093 PTR(__rom_data_start)
1094 PTR(__ram_data_start)
1096 PTR(hal_interrupt_handlers)
1097 PTR(hal_interrupt_data)
1098 PTR(hal_interrupt_objects)
1099 PTR(__exception_handlers)
1101 #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
1102 PTR(cyg_scheduler_sched_lock)
1104 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1106 PTR(__interrupt_stack)
1108 #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
1113 // Identification - useful to find out when a system was configured
1115 .asciz "eCos : " __DATE__
1118 // -------------------------------------------------------------------------
1119 // Interrupt vector tables.
1120 // These tables contain the isr, data and object pointers used to deliver
1121 // interrupts to user code.
1123 // Despite appearances, their sizes are not #defines, but .equ symbols
1124 // generated by magic without proper dependencies in arm.inc
1125 // Recompiling will not DTRT without manual intervention.
1133 .extern hal_default_isr
1135 .globl hal_interrupt_handlers
1136 hal_interrupt_handlers:
1137 .rept CYGNUM_HAL_ISR_COUNT
1138 .long hal_default_isr
1141 .globl hal_interrupt_data
1143 .rept CYGNUM_HAL_ISR_COUNT
1147 .globl hal_interrupt_objects
1148 hal_interrupt_objects:
1149 .rept CYGNUM_HAL_ISR_COUNT
1153 // -------------------------------------------------------------------------
1154 // Temporary interrupt stack
1158 // Small stacks, only used for saving information between CPU modes
1159 __exception_stack_base:
1167 __undef_exception_stack:
1169 // Runtime stack used during all interrupt processing
1170 #ifndef CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
1171 #define CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE 4096
1173 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1175 .global cyg_interrupt_stack_base
1176 cyg_interrupt_stack_base:
1177 __interrupt_stack_base:
1178 .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
1182 .global cyg_interrupt_stack
1183 cyg_interrupt_stack:
1189 #ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
1192 .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE // rather than 1k
1198 __startup_stack_base:
1199 #ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1202 .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
1209 #ifdef PLATFORM_EXTRAS
1210 #include PLATFORM_EXTRAS
1213 // --------------------------------------------------------------------------