OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [rtos/] [ecos-2.0/] [packages/] [hal/] [arm/] [arch/] [v2_0/] [src/] [vectors.S] - Blame information for rev 587

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 27 unneback
// #========================================================================
2
// #
3
// #    vectors.S
4
// #
5
// #    ARM exception vectors
6
// #
7
// #========================================================================
8
//####ECOSGPLCOPYRIGHTBEGIN####
9
// -------------------------------------------
10
// This file is part of eCos, the Embedded Configurable Operating System.
11
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
12
//
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.
16
//
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
20
// for more details.
21
//
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.
25
//
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.
32
//
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.
35
//
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####
42
// #
43
// # Author(s):     nickg, gthomas
44
// # Contributors:  nickg, gthomas
45
// # Date:          1999-02-20
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
50
// #                interrupts.
51
// #
52
// #####DESCRIPTIONEND####
53
// #
54
// #========================================================================
55
 
56
#include 
57
#include 
58
#ifdef CYGPKG_KERNEL  // no CDL yet
59
#include 
60
#else
61
# undef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
62
# undef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
63
#endif
64
#include 
65
 
66
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
67
// The CDL should enforce this
68
#undef  CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
69
#endif
70
 
71
#include "arm.inc"
72
 
73
#ifdef __thumb__
74
// Switch to thumb mode
75
#define THUMB_MODE(_r_, _l_)                     \
76
        ldr     _r_,=_l_ ## f+1                 ;\
77
        bx      _r_                             ;\
78
        .pool                                   ;\
79
        .code   16                              ;\
80
        .thumb_func                             ;\
81
 _l_:
82
 
83
// Switch to ARM mode
84
#define ARM_MODE(_r_, _l_)                       \
85
        ldr     _r_,=_l_ ## f                   ;\
86
        bx      _r_                             ;\
87
        .pool                                   ;\
88
        .code   32                              ;\
89
 _l_:
90
 
91
// Function definition, start executing body in ARM mode
92
#define FUNC_START_ARM(_name_, _r_)              \
93
        .code   16                              ;\
94
        .thumb_func                             ;\
95
        .globl _name_                           ;\
96
_name_:                                         ;\
97
        ldr     _r_,=_name_ ## _ARM             ;\
98
        bx      _r_                             ;\
99
        .code   32                              ;\
100
_name_ ## _ARM:
101
 
102
#else
103
 
104
// Switch to thumb mode
105
#define THUMB_MODE(_r_, _l_)
106
 
107
// Switch to ARM mode
108
#define ARM_MODE(_r_, _l_)
109
 
110
// Function definition, start executing body in ARM mode
111
#define FUNC_START_ARM(_name_, _r_) \
112
        .globl _name_; \
113
_name_:
114
 
115
#endif
116
 
117
 
118
 
119
#define PTR(name)               \
120
.##name: .word  name
121
 
122
// CYGHWR_HAL_ROM_VADDR is used when compiling for a different location
123
// from the base of ROM.  hal_platform_setup.h might define it.  For
124
// example, if flash is from 0x50000000 upwards (as on SA11x0), and we are
125
// to execute at 0x50040000, then we want the reset vector to point to
126
// 0x0004pqrs - the unmapped ROM address of the code - rather than
127
// 0x0000pqrs, which is the offset into our flash block.
128
//
129
// But usually it's not defined, so the behaviour is the obvious.
130
 
131
#ifndef UNMAPPED
132
#ifdef CYGHWR_HAL_ARM_HAS_MMU
133
# ifndef CYGHWR_HAL_ROM_VADDR
134
#  define CYGHWR_HAL_ROM_VADDR __exception_handlers
135
# endif
136
# define UNMAPPED(x) ((x)-CYGHWR_HAL_ROM_VADDR)
137
#else
138
# define UNMAPPED(x) (x)
139
#endif
140
#endif
141
 
142
#define UNMAPPED_PTR(name)              \
143
.##name: .word  UNMAPPED(name)
144
 
145
//        .file   "vectors.S"
146
 
147
 
148
// CYGHWR_LED_MACRO can be defined in hal_platform_setup.h. It's free to
149
// use r0+r1. Argument is in "\x" - cannot use macro arguments since the
150
// macro may contain #-chars and use of arguments cause these to be
151
// interpreted as CPP stringify operators.
152
// See example in PID hal_platform_setup.h.
153
#ifndef CYGHWR_LED_MACRO
154
#define CYGHWR_LED_MACRO
155
#endif
156
 
157
.macro LED x
158
    CYGHWR_LED_MACRO
159
.endm
160
 
161
 
162
//==========================================================================
163
// Hardware exception vectors.
164
//   This entire section will be copied to location 0x0000 at startup time.
165
//
166
        .code   32
167
        .section ".vectors","ax"
168
 
169
// This macro allows platforms to add their own code at the very start of
170
// the image.  This may be required in some circumstances where eCos ROM
171
// based code does not run immediately upon reset and/or when some sort of
172
// special header is required at the start of the image.
173
#ifdef PLATFORM_PREAMBLE
174
        PLATFORM_PREAMBLE
175
#endif
176
 
177
        .global __exception_handlers
178
__exception_handlers:
179
#ifdef CYGSEM_HAL_ROM_RESET_USES_JUMP
180
// Assumption:  ROM code has these vectors at the hardware reset address.
181
// A simple jump removes any address-space dependencies [i.e. safer]
182
        b       reset_vector                    // 0x00
183
#else
184
        ldr     pc,.reset_vector                // 0x00
185
#endif
186
        ldr     pc,.undefined_instruction       // 0x04
187
        ldr     pc,.software_interrupt          // 0x08 start && software int
188
        ldr     pc,.abort_prefetch              // 0x0C
189
        ldr     pc,.abort_data                  // 0x10
190
        .word   0                               // unused
191
        ldr     pc,.IRQ                         // 0x18
192
        ldr     pc,.FIQ                         // 0x1C
193
 
194
// The layout of these pointers should match the vector table above since
195
// they are copied in pairs.
196
        .global vectors
197
vectors:
198
UNMAPPED_PTR(reset_vector)                      // 0x20
199
PTR(undefined_instruction)                      // 0x24
200
PTR(software_interrupt)                         // 0x28
201
PTR(abort_prefetch)                             // 0x2C
202
PTR(abort_data)                                 // 0x30
203
        .word   0                               // 0x34
204
PTR(IRQ)                                        // 0x38
205
PTR(FIQ)                                        // 0x3c
206
#ifdef CYGSEM_HAL_ARM_PID_ANGEL_BOOT
207
PTR(start) // This is copied to 0x28 for bootup // 0x40
208
#endif
209
           // location 0x40 is used for storing DRAM size if known
210
           // for some platforms.
211
 
212
//
213
// "Vectors" - fixed location data items
214
//    This section contains any data which might be shared between
215
// an eCos application and any other environment, e.g. the debug
216
// ROM.
217
//
218
        .section ".fixed_vectors"
219
        // Interrupt/exception VSR pointers
220
        .globl  hal_vsr_table
221
hal_vsr_table:
222
        .rept   8
223
        .long   0
224
        .endr
225
 
226
        .globl  hal_dram_size
227
hal_dram_size:
228
        .long   0
229
        // what, if anything, hal_dram_type means is up to the platform
230
        .globl  hal_dram_type
231
hal_dram_type:
232
        .long   0
233
 
234
        .balign 16
235
#ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT
236
        // Vectors used to communicate between eCos and ROM environments
237
        .globl  hal_virtual_vector_table
238
hal_virtual_vector_table:
239
        .rept   CYGNUM_CALL_IF_TABLE_SIZE
240
        .long   0
241
        .endr
242
#endif
243
 
244
#ifdef CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
245
        .balign 16      // Should be at 0x50
246
ice_thread_vector:
247
        .long   0       // Must be 'MICE'
248
        .long   0       // Pointer to thread support vector
249
        .long   0       // eCos executing flag
250
        .long   0       // Must be 'GDB '
251
#endif // CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
252
        .balign 32
253
 
254
// Other vectors - this may include "fixed" locations
255
#ifdef PLATFORM_VECTORS
256
        PLATFORM_VECTORS
257
#endif
258
 
259
        .text
260
// Startup code which will get the machine into supervisor mode
261
        .global reset_vector
262
        .type   reset_vector,function
263
reset_vector:
264
        PLATFORM_SETUP1         // Early stage platform initialization
265
                                // which can set DRAM size at 0x40
266
                                // see 
267
 
268
        // Come here to reset board
269
warm_reset:
270
 
271
#if defined(CYG_HAL_STARTUP_RAM) && \
272
    !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
273
        mrs     r7,cpsr                 // move back to IRQ mode
274
        and     r7,r7,#CPSR_MODE_BITS
275
        cmp     r7,#CPSR_SUPERVISOR_MODE
276
        beq     start
277
#endif
278
 
279
        // We cannot access any LED registers until after PLATFORM_SETUP1
280
        LED 7
281
 
282
        mov     r0,#0           // move vectors
283
        ldr     r1,=__exception_handlers
284
#ifndef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
285
        // Wait with this if stubs are included (see further down).
286
        ldr     r2,[r1,#0x04]   // undefined instruction
287
        str     r2,[r0,#0x04]
288
        ldr     r2,[r1,#0x24]
289
        str     r2,[r0,#0x24]
290
#endif
291
        ldr     r2,[r1,#0x08]   // software interrupt
292
        str     r2,[r0,#0x08]
293
 
294
#ifdef CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
295
        ldr     r2,=ice_thread_vector
296
        sub     r2,r2,r1        // compute fixed (low memory) address
297
        ldr     r3,=0x4D494345  // 'MICE'
298
        str     r3,[r2],#4
299
        ldr     r3,=hal_arm_ice_thread_handler
300
        str     r3,[r2],#4
301
        mov     r3,#1
302
        str     r3,[r2],#4
303
        ldr     r3,=0x47444220  // 'GDB '
304
        str     r3,[r2],#4
305
#endif // CYGHWR_HAL_ARM_ICE_THREAD_SUPPORT
306
 
307
#if defined(CYGSEM_HAL_ARM_PID_ANGEL_BOOT)
308
// Ugly hack to get into supervisor mode
309
        ldr     r2,[r1,#0x40]
310
        str     r2,[r0,#0x28]
311
 
312
        LED 6
313
 
314
        swi                     // switch to supervisor mode
315
#endif
316
 
317
// =========================================================================
318
// Real startup code. We jump here from the reset vector to set up the world.
319
        .globl  start
320
start:
321
 
322
        LED 5
323
 
324
#if defined(CYG_HAL_STARTUP_RAM) && \
325
    !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
326
// If we get restarted, hang here to avoid corrupting memory
327
        ldr     r0,.init_flag
328
        ldr     r1,[r0]
329
1:      cmp     r1,#0
330
        bne     1b
331
        ldr     r1,init_done
332
        str     r1,[r0]
333
#endif
334
 
335
        // Reset software interrupt pointer
336
        mov     r0,#0           // move vectors
337
        ldr     r1,.__exception_handlers
338
#if defined(CYG_HAL_STARTUP_RAM) && \
339
    !defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
340
        cmp     r7,#CPSR_SUPERVISOR_MODE
341
        beq     10f
342
#endif
343
        ldr     r2,[r1,#0x28]   // software interrupt
344
        str     r2,[r0,#0x28]
345
10:
346
        ldr     r2,[r1,#0x18]   // IRQ
347
        str     r2,[r0,#0x18]
348
        ldr     r2,[r1,#0x38]
349
        str     r2,[r0,#0x38]
350
        ldr     r2,[r1,#0x1C]   // FIQ
351
        str     r2,[r0,#0x1C]
352
        ldr     r2,[r1,#0x3C]
353
        str     r2,[r0,#0x3C]
354
        ldr     r2,[r1,#0x0C]   // abort (prefetch)
355
        str     r2,[r0,#0x0C]
356
        ldr     r2,[r1,#0x2C]
357
        str     r2,[r0,#0x2C]
358
        ldr     r2,[r1,#0x10]   // abort (data)
359
        str     r2,[r0,#0x10]
360
        ldr     r2,[r1,#0x30]
361
        str     r2,[r0,#0x30]
362
 
363
        LED 4
364
 
365
#if defined(CYG_HAL_STARTUP_ROM) || defined(CYG_HAL_STARTUP_ROMRAM)
366
        // Set up reset vector
367
        mov     r0,#0
368
        ldr     r1,.__exception_handlers
369
        ldr     r2,[r1,#0x00]    // reset vector intstruction
370
        str     r2,[r0,#0x00]
371
        ldr     r2,=warm_reset
372
        str     r2,[r0,#0x20]
373
        // Relocate [copy] data from ROM to RAM
374
        ldr     r3,.__rom_data_start
375
        ldr     r4,.__ram_data_start
376
        ldr     r5,.__ram_data_end
377
        cmp     r4,r5           // jump if no data to move
378
        beq     2f
379
        sub     r3,r3,#4        // loop adjustments
380
        sub     r4,r4,#4
381
1:      ldr     r0,[r3,#4]!     // copy info
382
        str     r0,[r4,#4]!
383
        cmp     r4,r5
384
        bne     1b
385
2:
386
#endif
387
 
388
        // initialize interrupt/exception environments
389
        ldr     sp,.__startup_stack
390
        mov     r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_IRQ_MODE)
391
        msr     cpsr,r0
392
        ldr     sp,.__exception_stack
393
        mov     r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE)
394
        msr     cpsr,r0
395
        ldr     sp,.__exception_stack
396
 
397
        // initialize CPSR (machine state register)
398
        mov     r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
399
        msr     cpsr,r0
400
 
401
        // Note: some functions in LIBGCC1 will cause a "restore from SPSR"!!
402
        msr     spsr,r0
403
 
404
        // initialize stack
405
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
406
        // use interrupt stack for system initialization since it's bigger
407
        // than the "startup" stack in this configuration
408
        ldr     sp,.__interrupt_stack
409
#else
410
        ldr     sp,.__startup_stack
411
#endif
412
 
413
        // clear BSS
414
        ldr     r1,.__bss_start
415
        ldr     r2,.__bss_end
416
        mov     r0,#0
417
        cmp     r1,r2
418
        beq     2f
419
1:      str     r0,[r1],#4
420
        cmp     r1,r2
421
        bls     1b
422
2:
423
 
424
        // Run kernel + application in THUMB mode
425
        THUMB_MODE(r1,10)
426
 
427
        LED 3
428
 
429
        // Call platform specific hardware initialization
430
        bl      hal_hardware_init
431
 
432
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
433
        bl      initialize_stub
434
 
435
        // Now that stub is initialized, change vector. It is possible
436
        // to single-step through most of the init code, except the below.
437
        // Put a breakpoint at the call to cyg_hal_invoke_constructors to
438
        // pass over this bit (s-s depends on internal state in the stub).
439
#endif
440
 
441
#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS) || \
442
    defined(CYGIMP_HAL_PROCESS_ALL_EXCEPTIONS)
443
        mov     r0,#0           // move vectors
444
        ldr     r1,=__exception_handlers
445
        ldr     r2,[r1,#0x04]   // undefined instruction
446
        str     r2,[r0,#0x04]
447
        ldr     r2,[r1,#0x24]
448
        str     r2,[r0,#0x24]
449
#endif
450
 
451
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
452
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
453
        .extern hal_ctrlc_isr_init
454
        bl      hal_ctrlc_isr_init
455
#endif
456
 
457
        LED 2
458
 
459
        // Run through static constructors
460
        bl      cyg_hal_invoke_constructors
461
 
462
        LED 1
463
 
464
        // This starts up the eCos kernel
465
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
466
        ldr     r1,=__startup_stack
467
        mov     sp,r1
468
#endif
469
        bl      cyg_start
470
_start_hang:
471
        b       _start_hang
472
        .code   32
473
 
474
        .global reset_platform
475
        .type   reset_platform,function
476
reset_platform:
477
#ifdef CYGSEM_HAL_ROM_MONITOR
478
        // initialize CPSR (machine state register)
479
        mov     r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE)
480
        msr     cpsr,r0
481
        b       warm_reset
482
#else
483
        mov     r0,#0
484
        mov     pc,r0           // Jump to reset vector
485
#endif
486
 
487
init_done:
488
        .long   0xDEADB00B
489
 
490
//
491
// Exception handlers
492
// Assumption: get here from a non-user context [mode]
493
//
494
        .code   32
495
undefined_instruction:
496
        ldr     sp,.__undef_exception_stack     // get good stack
497
        stmfd   sp!,{r0-r5}                     // save some supervisor regs
498
        mrs     r1,spsr
499
        tst     r1,#CPSR_THUMB_ENABLE
500
        subeq   r0,lr,#4                // PC at time of interrupt (ARM)
501
        subne   r0,lr,#2                // PC at time of interrupt (thumb)
502
        mov     r2,#CYGNUM_HAL_EXCEPTION_ILLEGAL_INSTRUCTION
503
        mov     r3,sp
504
        b       call_exception_handler
505
 
506
        .code   32
507
software_interrupt:
508
        stmfd   sp!,{r8}
509
        ldr     r8,.__undef_exception_stack     // get good stack
510
        stmfd   r8!,{r0-r5}                     // save some supervisor regs
511
        mov     r3,r8
512
        ldmfd   sp!,{r8}
513
        mrs     r1,spsr
514
        tst     r1,#CPSR_THUMB_ENABLE
515
        subeq   r0,lr,#4                // PC at time of SWI (ARM)
516
        subne   r0,lr,#2                // PC at time of SWI (thumb)
517
        mov     r2,#CYGNUM_HAL_EXCEPTION_INTERRUPT
518
        b       call_exception_handler
519
 
520
        .code   32
521
abort_prefetch:
522
        ldr     sp,.__undef_exception_stack     // get good stack
523
        stmfd   sp!,{r0-r5}                     // save some supervisor regs
524
        sub     r0,lr,#4                        // PC at time of interrupt
525
        mrs     r1,spsr
526
        mov     r2,#CYGNUM_HAL_EXCEPTION_CODE_ACCESS
527
        mov     r3,sp
528
        b       call_exception_handler
529
 
530
        .code   32
531
abort_data:
532
        ldr     sp,.__undef_exception_stack     // get good stack
533
        stmfd   sp!,{r0-r5}                     // save some supervisor regs
534
        sub     r0,lr,#4                        // PC at time of interrupt
535
        mrs     r1,spsr
536
        mov     r2,#CYGNUM_HAL_EXCEPTION_DATA_ACCESS
537
        mov     r3,sp
538
        b       call_exception_handler
539
 
540
//
541
// Dispatch an exception handler.
542
 
543
        .code   32
544
call_exception_handler:
545
        //
546
        // On Entry:
547
        //
548
        // r4,r5 = scratch
549
        // r3 = pointer to temp save area
550
        // r2 = vector number
551
        // r1 = exception psr
552
        // r0 = exception pc
553
        //
554
        // [r3+20]: exception r5
555
        // [r3+16]: exception r4
556
        // [r3+12]: exception r3
557
        // [r3+8] : exception r2
558
        // [r3+4] : exception r1
559
        // [r3]   : exception r0
560
 
561
        mrs     r4,cpsr                 // switch to Supervisor Mode
562
        bic     r4,r4,#CPSR_MODE_BITS
563
        orr     r4,r4,#CPSR_SUPERVISOR_MODE
564
        msr     cpsr,r4
565
 
566
        mov     r5,sp                   // save original svc sp
567
        mov     r4,lr                   // and original svc lr
568
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
569
        // Make sure we use the GDB stack.
570
        ldr     sp,.__GDB_stack
571
        cmp     r5,sp                   // already on GDB stack?
572
        bhi     10f
573
        ldr     r4,.__GDB_stack_base
574
        cmp     r5,r4
575
        movhi   sp,r5
576
10:
577
#endif
578
        //
579
        // r5 holds original svc sp, current sp is stack to use
580
        // r4 holds original svc lr, which must also be preserved
581
        //
582
 
583
        stmfd   sp!,{r0-r2,r4,r5}       // push svc_sp, svc_lr, vector, psr, pc
584
 
585
        // switch to pre-exception mode to get banked regs
586
        mov     r0,sp                   // r0 survives mode switch
587
        mrs     r2,cpsr                 // Save current psr for return
588
        orr     r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
589
        bic     r1,r1,#CPSR_THUMB_ENABLE
590
        msr     cpsr,r1
591
        stmfd   r0!,{r8-r12,sp,lr}
592
        msr     cpsr,r2                 // back to svc mode
593
        mov     sp,r0                   // update stack pointer
594
 
595
        // now save pre-exception r0-r7 on current stack
596
        ldmfd   r3,{r0-r5}
597
        stmfd   sp!,{r0-r7}
598
 
599
        // SP needs fixing if exception occured in SVC mode.
600
        // The original SVC LR is still in place so that
601
        // does not need to be fixed here.
602
        ldr     r1,[sp,#armreg_cpsr]
603
        and     r1,r1,#CPSR_MODE_BITS
604
        cmp     r1,#CPSR_SUPERVISOR_MODE
605
        ldreq   r1,[sp,#armreg_svcsp]
606
        streq   r1,[sp,#armreg_sp]
607
 
608
#ifdef  CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
609
        mov     r0,sp
610
        ldr     r1,.__dump_procs
611
        ldr     r2,[sp,#armreg_vector]
612
        mov     lr,pc
613
        ldr     pc,[r1,r2,lsl #2]
614
#endif
615
 
616
        // call exception handler
617
        mov     r0,sp
618
        THUMB_MODE(r9,10)
619
        bl      exception_handler
620
 
621
#ifdef  CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
622
        mov     r0,sp
623
        bl      cyg_hal_report_exception_handler_returned
624
#endif
625
 
626
        ARM_MODE(r1,10)
627
 
628
        //
629
        // Return from exception
630
        //
631
return_from_exception:
632
 
633
        ldr     r0,[sp,#armreg_cpsr]
634
        msr     spsr,r0
635
 
636
        // return to supervisor mode is simple
637
        and     r1,r0,#CPSR_MODE_BITS
638
        cmp     r1,#CPSR_SUPERVISOR_MODE
639
        ldmeqfd sp,{r0-r14,pc}^
640
 
641
        //
642
        // return to other non-user modes is a little trickier
643
        //
644
 
645
        // switch to pre-exception mode and restore r8-r14
646
        add     r2,sp,#armreg_r8
647
        mrs     r1,cpsr
648
        orr     r0,r0,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
649
        bic     r0,r0,#CPSR_THUMB_ENABLE
650
        msr     cpsr,r0
651
        ldmfd   r2,{r8-r14}
652
        msr     cpsr, r1        // back to svc mode
653
 
654
        // move sp,lr and pc for final load
655
        ldr     r0,[sp,#armreg_svcsp]
656
        str     r0,[sp,#armreg_r8]
657
        ldr     r0,[sp,#armreg_svclr]
658
        str     r0,[sp,#armreg_r9]
659
        ldr     r0,[sp,#armreg_pc]
660
        str     r0,[sp,#armreg_r10]
661
 
662
        // restore r0-r7,sp,lr and return from exception
663
        ldmfd   sp,{r0-r7,sp,lr,pc}^
664
 
665
#ifdef  CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
666
__dump_procs:
667
        .word  0    // placeholder for reset
668
        .word  cyg_hal_report_undefined_instruction
669
        .word  cyg_hal_report_software_interrupt
670
        .word  cyg_hal_report_abort_prefetch
671
        .word  cyg_hal_report_abort_data
672
        .word  0    // reserved
673
#endif
674
 
675
 
676
// Handle device interrupts
677
// This is slightly more complicated than the other exception handlers because
678
// it needs to interface with the kernel (if present).
679
 
680
        .code   32
681
FIQ:
682
        // We can get here from any non-user mode.
683
        mrs     r8,spsr                 // CPSR at time of interrupt
684
        and     r9,r8,#CPSR_MODE_BITS   // isolate pre-interrupt mode
685
        cmp     r9,#CPSR_IRQ_MODE
686
        bne     1f
687
        // If FIQ interrupted IRQ mode, just return with FIQ disabled.
688
        // The common interrupt handling takes care of the rest.
689
        orr     r8,r8,#CPSR_FIQ_DISABLE
690
        msr     spsr,r8
691
        subs    pc,lr,#4
692
    1:
693
        // If FIQ interrupted other non-user mode, switch to IRQ mode and
694
        // fall through to IRQ handler.
695
        ldr     sp,.__exception_stack   // get good stack to save lr and spsr
696
        stmdb   sp,{r8,lr}
697
        mov     r8,#CPSR_IRQ_MODE|CPSR_FIQ_DISABLE|CPSR_IRQ_DISABLE
698
        msr     cpsr,r8                 // switch to IRQ mode
699
        ldr     sp,.__exception_stack   // get regs saved in FIQ mode
700
        ldmdb   sp,{sp,lr}
701
        msr     spsr,sp
702
 
703
        // now it looks like we got an IRQ instead of an FIQ except that
704
        // FIQ is disabled so we don't recurse.
705
IRQ:
706
        // Note: I use this exception stack while saving the context because
707
        // the current SP does not seem to be always valid in this CPU mode.
708
        ldr     sp,.__exception_stack   // get good stack
709
        stmfd   sp!,{r0-r5}             // save some supervisor regs
710
        sub     r0,lr,#4                // PC at time of interrupt
711
        mrs     r1,spsr
712
        mov     r2,#CYGNUM_HAL_VECTOR_IRQ
713
        mov     r3,sp
714
 
715
handle_IRQ_or_FIQ:
716
 
717
        mrs     r4,cpsr                 // switch to Supervisor Mode
718
        bic     r4,r4,#CPSR_MODE_BITS
719
        orr     r4,r4,#CPSR_SUPERVISOR_MODE
720
        msr     cpsr,r4
721
 
722
        mov     r5,sp                   // save original svc sp
723
        mov     r4,lr                   // save original svc lr
724
        stmfd   sp!,{r0-r2,r4,r5}       // push svc_sp, svc_lr, vector, psr, pc
725
 
726
        // switch to pre-exception mode to get banked regs
727
        mov     r0,sp                   // r0 survives mode switch
728
        mrs     r2,cpsr                 // Save current psr for return
729
        orr     r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
730
        bic     r1,r1,#CPSR_THUMB_ENABLE
731
        msr     cpsr,r1
732
        stmfd   r0!,{r8-r12,sp,lr}
733
        msr     cpsr,r2                 // back to svc mode
734
        mov     sp,r0                   // update stack pointer
735
 
736
        // now save pre-exception r0-r7 on current stack
737
        ldmfd   r3,{r0-r5}
738
        stmfd   sp!,{r0-r7}
739
 
740
        // sp needs fixing if exception occured in SVC mode.
741
        ldr     r1,[sp,#armreg_cpsr]
742
        and     r1,r1,#CPSR_MODE_BITS
743
        cmp     r1,#CPSR_SUPERVISOR_MODE
744
        ldreq   r1,[sp,#armreg_svcsp]
745
        streq   r1,[sp,#armreg_sp]
746
 
747
        mov     v6,sp                   // Save pointer to register frame
748
 
749
//      mov     r0,sp
750
//      bl      _show_frame_in
751
 
752
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
753
        // Switch to interrupt stack
754
        ldr     r2,.irq_level           // current number of nested interrupts
755
        ldr     r0,[r2]
756
        add     r1,r0,#1
757
        str     r1,[r2]                 // if was zero, switch stacks
758
        cmp     r0,#0
759
        moveq   r1,sp                   // save old stack pointer
760
        ldreq   sp,.__interrupt_stack
761
        stmeqfd sp!,{r1}
762
10:
763
#endif
764
 
765
        // The entire CPU state is now stashed on the stack,
766
        // increment the scheduler lock and handle the interrupt
767
 
768
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
769
        .extern cyg_scheduler_sched_lock
770
        ldr     r3,.cyg_scheduler_sched_lock
771
        ldr     r4,[r3]
772
        add     r4,r4,#1
773
        str     r4,[r3]
774
#endif
775
 
776
        THUMB_MODE(r3,10)
777
 
778
        mov     r0,v6
779
        bl      hal_IRQ_handler         // determine interrupt source
780
        mov     v1,r0                   // returned vector #
781
 
782
#if defined(CYGPKG_KERNEL_INSTRUMENT) && \
783
    defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
784
        ldr     r0,=RAISE_INTR          // arg0 = type = INTR,RAISE
785
        mov     r1,v1                   // arg1 = vector
786
        mov     r2,#0                   // arg2 = 0
787
        bl      cyg_instrument          // call instrument function
788
#endif
789
 
790
        ARM_MODE(r0,10)
791
 
792
        mov     r0,v1                   // vector #
793
 
794
#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
795
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
796
        // If we are supporting Ctrl-C interrupts from GDB, we must squirrel
797
        // away a pointer to the save interrupt state here so that we can
798
        // plant a breakpoint at some later time.
799
 
800
       .extern  hal_saved_interrupt_state
801
        ldr     r2,=hal_saved_interrupt_state
802
        str     v6,[r2]
803
#endif
804
 
805
        cmp     r0,#CYGNUM_HAL_INTERRUPT_NONE   // spurious interrupt
806
        bne     10f
807
#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
808
        mov     r0,v6                   // register frame
809
        bl      hal_spurious_IRQ
810
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
811
        b       spurious_IRQ
812
 
813
10:     ldr     r1,.hal_interrupt_data
814
        ldr     r1,[r1,v1,lsl #2]       // handler data
815
        ldr     r2,.hal_interrupt_handlers
816
        ldr     v3,[r2,v1,lsl #2]       // handler (indexed by vector #)
817
        mov     r2,v6                   // register frame (this is necessary
818
                                        // for the ISR too, for ^C detection)
819
 
820
#ifdef __thumb__
821
        ldr     lr,=10f
822
        bx      v3                      // invoke handler (thumb mode)
823
        .pool
824
        .code   16
825
        .thumb_func
826
IRQ_10T:
827
10:     ldr     r2,=15f
828
        bx      r2                      // switch back to ARM mode
829
        .pool
830
        .code   32
831
15:
832
IRQ_15A:
833
#else
834
        mov     lr,pc                   // invoke handler (call indirect
835
        mov     pc,v3                   // thru v3)
836
#endif
837
 
838
spurious_IRQ:
839
 
840
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
841
        // If we are returning from the last nested interrupt, move back
842
        // to the thread stack. interrupt_end() must be called on the
843
        // thread stack since it potentially causes a context switch.
844
        ldr     r2,.irq_level
845
        ldr     r3,[r2]
846
        subs    r1,r3,#1
847
        str     r1,[r2]
848
        ldreq   sp,[sp]         // This should be the saved stack pointer
849
#endif
850
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
851
        // The return value from the handler (in r0) will indicate whether a
852
        // DSR is to be posted. Pass this together with a pointer to the
853
        // interrupt object we have just used to the interrupt tidy up routine.
854
 
855
                              // don't run this for spurious interrupts!
856
        cmp     v1,#CYGNUM_HAL_INTERRUPT_NONE
857
        beq     17f
858
        ldr     r1,.hal_interrupt_objects
859
        ldr     r1,[r1,v1,lsl #2]
860
        mov     r2,v6           // register frame
861
 
862
        THUMB_MODE(r3,10)
863
 
864
        bl      interrupt_end   // post any bottom layer handler
865
                                // threads and call scheduler
866
        ARM_MODE(r1,10)
867
17:
868
#endif
869
 
870
//      mov     r0,sp
871
//      bl      show_frame_out
872
 
873
        // return from IRQ is same as return from exception
874
        b       return_from_exception
875
 
876
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
877
// Execute pending DSRs the interrupt stack
878
// Note: this can only be called from code running on a thread stack
879
FUNC_START_ARM(hal_interrupt_stack_call_pending_DSRs, r1)
880
        stmfd   sp!,{r4,r5,lr}
881
        // Disable interrupts
882
        mrs     r4,cpsr                 // disable IRQ's
883
        orr     r2,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
884
        bic     r5,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
885
        msr     cpsr,r2
886
        // Switch to interrupt stack
887
        mov     r3,sp                   // save old stack pointer
888
        ldr     sp,.__interrupt_stack
889
        stmfd   sp!,{r3}                // stored at top of interrupt stack
890
        ldr     r2,.irq_level           // current number of nested interrupts
891
        ldr     r3,[r2]
892
        add     r3,r3,#1                // bump nesting level
893
        str     r3,[r2]
894
        msr     cpsr,r5                 // enable interrupts
895
 
896
        THUMB_MODE(r1,20)
897
 
898
        bl      cyg_interrupt_call_pending_DSRs
899
 
900
 
901
        ARM_MODE(r1,22)
902
 
903
        // Disable interrupts
904
        mrs     r1,cpsr                 // disable IRQ's
905
        orr     r2,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
906
        msr     cpsr,r2
907
 
908
        // Move back to the thread stack.
909
        ldr     r2,.irq_level
910
        ldr     r3,[r2]
911
        sub     r3,r3,#1                // decrement nesting level
912
        str     r3,[r2]
913
        ldr     sp,[sp]                 // This should be the saved stack pointer
914
        msr     cpsr,r4                 // restore interrupts to original state
915
 
916
#ifdef __thumb__
917
        ldmfd   sp!,{r4,r5,lr}          // return
918
        bx      lr
919
#else
920
        ldmfd   sp!,{r4,r5,pc}          // return
921
#endif // __thumb__
922
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
923
 
924
// Thumb-only support functions
925
#ifdef __thumb__
926
 
927
FUNC_START_ARM(hal_disable_interrupts, r1)
928
        mrs     r0,cpsr                 // current state
929
        orr     r1,r0,#0xC0             // mask both FIQ and IRQ
930
        msr     cpsr,r1
931
        bx      lr                      // exit, _old_ in r0
932
 
933
FUNC_START_ARM(hal_enable_interrupts, r1)
934
        mrs     r0,cpsr                 // current state
935
        bic     r1,r0,#0xC0             // mask both FIQ and IRQ
936
        msr     cpsr,r1
937
        bx      lr                      // exit
938
 
939
FUNC_START_ARM(hal_restore_interrupts, r1)
940
        mrs     r1,cpsr                 // current state
941
        bic     r1,r1,#0xC0             // mask out FIQ/IRQ bits
942
        and     r0,r0,#0xC0             // keep only FIQ/IRQ
943
        orr     r1,r1,r0                // mask both FIQ and IRQ
944
        msr     cpsr,r1
945
        bx      lr                      // exit
946
 
947
FUNC_START_ARM(hal_query_interrupts, r1)
948
        mrs     r0,cpsr                 // current state
949
        bx      lr                      // exit, state in r0
950
 
951
#endif // __thumb__
952
 
953
// Dummy/support functions
954
 
955
        .global __gccmain
956
        .global _psr
957
        .global _sp
958
 
959
#ifdef __thumb__
960
        .code   16
961
        .thumb_func
962
__gccmain:
963
        bx      lr
964
 
965
        .code   16
966
        .thumb_func
967
_psr:
968
        ARM_MODE(r1,10)
969
        mrs     r0,cpsr
970
        bx      lr
971
 
972
        .code   16
973
        .thumb_func
974
_sp:
975
        mov     r0,sp
976
        bx      lr
977
#else
978
__gccmain:
979
        mov     pc,lr
980
 
981
_psr:
982
        mrs     r0,cpsr
983
        mov     pc,lr
984
 
985
_sp:
986
        mov     r0,sp
987
        mov     pc,lr
988
#endif
989
 
990
 
991
//
992
// Pointers to various objects.
993
//
994
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
995
PTR(__GDB_stack_base)
996
PTR(__GDB_stack)
997
#endif
998
PTR(__startup_stack)
999
PTR(__exception_stack)
1000
PTR(__undef_exception_stack)
1001
PTR(__bss_start)
1002
PTR(__bss_end)
1003
PTR(_end)
1004
PTR(__rom_data_start)
1005
PTR(__ram_data_start)
1006
PTR(__ram_data_end)
1007
PTR(hal_interrupt_handlers)
1008
PTR(hal_interrupt_data)
1009
PTR(hal_interrupt_objects)
1010
PTR(__exception_handlers)
1011
PTR(init_flag)
1012
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
1013
PTR(cyg_scheduler_sched_lock)
1014
#endif
1015
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1016
PTR(irq_level)
1017
PTR(__interrupt_stack)
1018
#endif
1019
#ifdef  CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
1020
PTR(__dump_procs)
1021
#endif
1022
 
1023
//
1024
// Identification - useful to find out when a system was configured
1025
_eCos_id:
1026
        .asciz  "eCos : " __DATE__
1027
 
1028
 
1029
// -------------------------------------------------------------------------
1030
// Interrupt vector tables.
1031
// These tables contain the isr, data and object pointers used to deliver
1032
// interrupts to user code.
1033
 
1034
// Despite appearances, their sizes are not #defines, but .equ symbols
1035
// generated by magic without proper dependencies in arm.inc
1036
// Recompiling will not DTRT without manual intervention.
1037
 
1038
        .data
1039
 
1040
init_flag:
1041
        .balign 4
1042
        .long   0
1043
 
1044
        .extern hal_default_isr
1045
 
1046
        .globl  hal_interrupt_handlers
1047
hal_interrupt_handlers:
1048
        .rept   CYGNUM_HAL_ISR_COUNT
1049
        .long   hal_default_isr
1050
        .endr
1051
 
1052
        .globl  hal_interrupt_data
1053
hal_interrupt_data:
1054
        .rept   CYGNUM_HAL_ISR_COUNT
1055
        .long   0
1056
        .endr
1057
 
1058
        .globl  hal_interrupt_objects
1059
hal_interrupt_objects:
1060
        .rept   CYGNUM_HAL_ISR_COUNT
1061
        .long   0
1062
        .endr
1063
 
1064
// -------------------------------------------------------------------------
1065
// Temporary interrupt stack
1066
 
1067
        .section ".bss"
1068
 
1069
// Small stacks, only used for saving information between CPU modes
1070
__exception_stack_base:
1071
        .rept   32
1072
        .long   0
1073
        .endr
1074
__exception_stack:
1075
        .rept   32
1076
        .long   0
1077
        .endr
1078
__undef_exception_stack:
1079
 
1080
// Runtime stack used during all interrupt processing
1081
#ifndef CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
1082
#define CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE 4096
1083
#endif
1084
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1085
        .balign 16
1086
        .global cyg_interrupt_stack_base
1087
cyg_interrupt_stack_base:
1088
__interrupt_stack_base:
1089
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
1090
        .byte 0
1091
        .endr
1092
        .balign 16
1093
        .global cyg_interrupt_stack
1094
cyg_interrupt_stack:
1095
__interrupt_stack:
1096
irq_level:
1097
        .long   0
1098
#endif
1099
 
1100
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
1101
        .balign 16
1102
__GDB_stack_base:
1103
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE // rather than 1k
1104
        .byte 0
1105
        .endr
1106
__GDB_stack:
1107
#endif
1108
        .balign 16
1109
__startup_stack_base:
1110
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
1111
        .rept 512
1112
#else
1113
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
1114
#endif
1115
        .byte 0
1116
        .endr
1117
        .balign 16
1118
__startup_stack:
1119
 
1120
#ifdef PLATFORM_EXTRAS
1121
#include PLATFORM_EXTRAS
1122
#endif
1123
 
1124
// --------------------------------------------------------------------------
1125
//  end of vectors.S

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.