This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: Atmel Ecos AIC


>> Hello,
>> I read your email (ecos mailing list) concerning the Atmel ARM and the AIC.
>> Can you email the code (using the AIC registers for IRQ handling) ?
>> I want to use my own IRQ routine for IRQ 4 and it does not work fast
>> enough if I use the ecos methods.
>>
>> With kind regards,
>>  Sven Rehfuß

Sven,

The code below is for the ATMEL ARM processor only. Please use a diff/compare program
to compare it to the original files to see the changes.

1) Compare the sources with the ecos sources and apply the changes
2) define OPTION_FASTER_IRQ (-DOPTION_FASTER_IRQ as parameter to gcc)
3) everything should work the same (test first?)
4) to use the faster irq, modify your interrupt service routines:

on initialisation, add: (for example)

#if defined (ECOS_FAST_INTERRUPT_MYINTERRUPT)
// handle Interrupt outside ecos!
*(volatile unsigned long*)(0xFFFFF080+CYGNUM_HAL_INTERRUPT_EXT1*4) = (unsigned long
My_ISR_function;
#endif

in the interrupt routine, change:

// Acknowlage interrupt
#if defined (ECOS_FAST_INTERRUPT_MYINTERRUPT)
AicBase->AIC_EOICR = (unsigned long)AicBase;  // write dummy value to address
AicBase->AIC_EOICR
#else
cyg_drv_interrupt_acknowledge(vector);
#endif

As long as you return only CYG_ISR_HANDLED the function should be faster. To set
flags or do other ecos things, return (CYG_ISR_CALL_DSR|CYG_ISR_HANDLED)

Below you will find the two (partial!) files at91_misc.c (for the EB40A!) and
vector.S

Eric.

at91_misc.c
------------
/*==========================================================================
//
//      at91_misc.c
//
//      HAL misc board support code for Atmel AT91
//
//==========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
// Copyright (C) 2003 Nick Garnett <nickg@calivar.com>
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND#### */

...

// -------------------------------------------------------------------------
// Hardware init

void hal_hardware_init(void)
{
    unsigned i;

    // Set up eCos/ROM interfaces
    hal_if_init();

    // Reset all interrupts
    HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_IDCR, 0xFFFFFFFF);

    // Flush internal priority level stack
    for (i = 0; i < 8; ++i)
        HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_EOI, 0xFFFFFFFF);

    // Set protected mode, so the debugger can't mess up the AIC controller by
reading AIC_IVR
    *(unsigned long*)(0xFFF00018) = 0x27A80001;

    // Setup source numbers in AIC_SMRx registers (0 = handle by ECOS)
    for (i=0; i<9; i++)
     HAL_WRITE_UINT32(AT91_AIC + AT91_AIC_SVR0 + 4*i, 0);

    for (i=16; i<19; i++)
     HAL_WRITE_UINT32(AT91_AIC + AT91_AIC_SVR0 + 4*i, 0);

    // Make AIC software interrupt edge triggered
    HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_SMR1, AT91_AIC_SMR_LEVEL_HI |
AT91_AIC_SMR_EDGE_POS);
    HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_SVR0, 0);   // FIQ vector (not used)
    HAL_WRITE_UINT32(AT91_AIC+AT91_AIC_SVR, 0);   // Spurious IRQ vector (= 0, use
ecos handler)
}

// -------------------------------------------------------------------------
// This routine is called to respond to a hardware interrupt (IRQ).  It
// should interrogate the hardware and return the IRQ vector number.

int hal_IRQ_handler(void)
{
    cyg_uint32 irq_num;
    cyg_uint32 ivr;

    // Calculate active interrupt (updates ISR)
    // HAL_READ_UINT32(AT91_AIC+AT91_AIC_IVR, ivr); <-- already don by modifier IRQ

    HAL_READ_UINT32(AT91_AIC+AT91_AIC_ISR, irq_num);

    // No valid interrrupt source, treat as spurious interrupt
    // if (irq_num < CYGNUM_HAL_ISR_MIN || irq_num > CYGNUM_HAL_ISR_MAX)
    //  irq_num = CYGNUM_HAL_INTERRUPT_NONE;

    return irq_num;
}

vector.S
--------
// #========================================================================
// #
// #    vectors.S
// #
// #    ARM exception vectors
// #
// #========================================================================
//####ECOSGPLCOPYRIGHTBEGIN####
// -------------------------------------------
// This file is part of eCos, the Embedded Configurable Operating System.
// Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
//
// eCos is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// eCos is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with eCos; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//
// Alternative licenses for eCos may be arranged by contacting Red Hat, Inc.
// at http://sources.redhat.com/ecos/ecos-license/
// -------------------------------------------
//####ECOSGPLCOPYRIGHTEND#### */



...


// Handle device interrupts
// This is slightly more complicated than the other exception handlers because
// it needs to interface with the kernel (if present).
// Assumption: can get here from any mode, including user mode
// (spurious interrupt while standalone app. is running in user mode)

        .code   32
FIQ:
        // Mask FIQ in AIC (because we do not handle FIQ here)
        // it must be reenabled in user irq handler after the cause of FIQ is
resolved!
        ldr     r8, =AT91_AIC
        mov     r9, #1
        str     r9, [r8,#AT91_AIC_IMR]
        // Trigger AIC software interrupt (as FIQ has higher priority than IRQ, it
will not launch imediatly until after FIQ returns)
        mov     r9, #2
        str     r9, [r8,#AT91_AIC_ISCR]
        // Return from interrupt
        subs    pc, lr, #4

IRQ:    // Simple IRQ is *NOT* reentrant, keep interrupts disabled here
        // Note: I use this exception stack while saving the context because
        // the current SP does not seem to be always valid in this CPU mode.
        ldr     sp,.__exception_stack   // get good stack
        stmfd   sp!,{r0-r5}             // save some supervisor regs

        // accept & memorize interrupt
        ldr     r4, =AT91_AIC
        ldr     r5, [r4,#AT91_AIC_IVR]
        str     r5, [r4,#AT91_AIC_IVR]

#ifdef OPTION_FASTER_IRQ
        cmp     r5, #0
        beq     ECOS_IRQ                // AIC vector = 0? use ECOS isr.

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK_x
        // Switch to supervisor mode, which holds the __interrupt_stack stack
        mrs     r0,cpsr                 // switch to Supervisor Mode
        bic     r0,r0,#CPSR_MODE_BITS
        orr     r0,r0,#CPSR_SUPERVISOR_MODE
        msr     cpsr,r0

        // This is supervisor mode. Do not worry about cpsr, either svc is
interrupted and cpsr is stored in spsr_irq or svc is not used at the moment.
        // Switch to interrupt stack
        ldr     r2,.irq_level           // current number of nested interrupts
        ldr     r0,[r2]
        add     r1,r0,#1
        str     r1,[r2]                 // if was zero, switch stacks
        cmp     r0,#0
        moveq   r1,sp                   // save old stack pointer
        ldreq   sp,.__interrupt_stack
        stmeqfd sp!,{r1}
#endif


        // Get vector #   (tested, when there is a higher level AIC interrupt, ISR
stays at correct number until IVR is read
        ldr     r0, [r4,#AT91_AIC_ISR]

        // When a breakpoint is set, the AIC is reset by the debugger. Handle that
case
        cmp r0, #0
        streq   r4, [r4,#AT91_AIC_EOI]   // acknowlage this interrupt (needed?)
        beq     12f                      // and exit
        mov     r4, r0                   // Backup ISR # in r4

        // store r12 & lr, so I can call C routines
        stmfd   sp!,{r12, lr}

        // Get handler data
        ldr     r1,.hal_interrupt_data
        ldr     r1,[r1,r0,lsl #2]       // handler data

        // Call isr. Make sure r0-3 + r12 + lr are safe!
        // Do *NOT* enable interrupts, it would destroy the irq-lr register etc.
#ifdef __thumb__
        ldr     lr,=10f
        bx      r5                      // invoke handler (thumb mode)
        .pool
        .code   16
        .thumb_func
10:     ldr     r2,=15f
        bx      r2                      // switch back to ARM mode
        .pool
        .code   32
15:
#else
        mov     lr,pc                   // invoke handler (call indirect
        mov     pc,r5                   // thru v3)
#endif

        // return from IRQ
        ldmfd   sp!,{r12, lr}

12:
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK_x
        // If we are returning from the last nested interrupt, move back
        // to the thread stack. interrupt_end() must be called on the
        // thread stack since it potentially causes a context switch.
        ldr     r2,.irq_level
        ldr     r3,[r2]
        subs    r1,r3,#1
        str     r1,[r2]
        ldreq   sp,[sp]         // This should be the saved stack pointer

        // Switch back to irq mode, which holds the sp and lr register
        mrs     r2,cpsr
        bic     r2,r2,#CPSR_MODE_BITS
        orr     r2,r2,#CPSR_IRQ_MODE
        msr     cpsr,r2
#endif

#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
        tst     r0, #2 // = CYG_ISR_CALL_DSR
        bne     ECOS_POST_DSR
#endif
        ldmfd   sp!,{r0-r5}             // restore some supervisor regs
        // Return from interrupt
        subs    pc, lr, #4

#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
ECOS_POST_DSR:
        // now do virtually the same as ECOS_IRQ, but r0 = isr result and r4 = vector
number
        // r0 is always #CYG_ISR_CALL_DSR|CYG_ISR_HANDLED, so no need to save result
        sub     r0,lr,#4                // PC at time of interrupt
        mrs     r1,spsr
        mov     r3,sp

        mrs     r2,cpsr                 // switch to Supervisor Mode
        bic     r2,r2,#CPSR_MODE_BITS
        orr     r2,r2,#CPSR_SUPERVISOR_MODE
        msr     cpsr,r2

        mov     r2, sp                  // save original svc sp
        stmfd   sp!,{r2}                // push svc_sp
        mov     r2,#CYGNUM_HAL_VECTOR_IRQ
        stmfd   sp!,{r0-r2,lr}          // push svc_lr, vector, psr, pc

#ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
        // did exception occur in user mode ?
        and     r2, r1, #CPSR_MODE_BITS
        cmp     r2, #CPSR_USER_MODE
        bne     1f
        stmfd   sp, {r8-r12, sp, lr}^   // get user mode regs
        nop
        sub     sp, sp, #4*7
        bal     2f
1:
#endif
        // switch to pre-exception mode to get banked regs
        mov     r0,sp                   // r0 survives mode switch
        mrs     r2,cpsr                 // Save current psr for return
        orr     r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
        bic     r1,r1,#CPSR_THUMB_ENABLE
        msr     cpsr,r1
        stmfd   r0!,{r8-r12,sp,lr}
        msr     cpsr,r2                 // back to svc mode
        mov     sp,r0                   // update stack pointer

2:
        mov     v6, r4 // v6 = r9
        // now save pre-exception r0-r7 on current stack
        ldmfd   r3,{r0-r5}
        stmfd   sp!,{r0-r7}

        // sp needs fixing if exception occured in SVC mode.
        ldr     r1,[sp,#armreg_cpsr]
        and     r1,r1,#CPSR_MODE_BITS
        cmp     r1,#CPSR_SUPERVISOR_MODE
        ldreq   r1,[sp,#armreg_svcsp]
        streq   r1,[sp,#armreg_sp]

        mov     v1,v6                   // Save vector #
        mov     v6,sp                   // Save pointer to register frame

        // The entire CPU state is now stashed on the stack,
        // increment the scheduler lock and handle the interrupt DSR

        .extern cyg_scheduler_sched_lock
        ldr     r3,.cyg_scheduler_sched_lock
        ldr     r2,[r3]
        add     r2,r2,#1
        str     r2,[r3]

#if defined(CYGPKG_KERNEL_INSTRUMENT) && \
    defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
        THUMB_MODE(r3,10)

        ldr     r0,=RAISE_INTR          // arg0 = type = INTR,RAISE
        mov     r1,v1                   // arg1 = vector
        mov     r2,#0                   // arg2 = 0
        bl      cyg_instrument          // call instrument function

        ARM_MODE(r0,10)
#endif

#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
        // If we are supporting Ctrl-C interrupts from GDB, we must squirrel
        // away a pointer to the save interrupt state here so that we can
        // plant a breakpoint at some later time.

       .extern  hal_saved_interrupt_state
        ldr     r2,=hal_saved_interrupt_state
        str     v6,[r2]
#endif

        // The return value from the handler (in r0) will indicate whether a
        // DSR is to be posted. Pass this together with a pointer to the
        // interrupt object we have just used to the interrupt tidy up routine.
        mov     r0, #3 // (= CYG_ISR_CALL_DSR|CYG_ISR_HANDLED)
        b       run_dsr
#endif
#endif

        // now it looks like we got an IRQ instead of an FIQ except that
        // FIQ is disabled so we don't recurse.
ECOS_IRQ:
        // Note: I use this exception stack while saving the context because
        // the current SP does not seem to be always valid in this CPU mode.
        sub     r0,lr,#4                // PC at time of interrupt
        mrs     r1,spsr
        mov     r2,#CYGNUM_HAL_VECTOR_IRQ
        mov     r3,sp

        mrs     r4,cpsr                 // switch to Supervisor Mode
        bic     r4,r4,#CPSR_MODE_BITS
        orr     r4,r4,#CPSR_SUPERVISOR_MODE
        msr     cpsr,r4

        mov     r5,sp                   // save original svc sp
 mov r4,lr   // save original svc lr
        stmfd   sp!,{r0-r2,r4,r5}       // push svc_sp, svc_lr, vector, psr, pc

#ifdef CYGOPT_HAL_ARM_WITH_USER_MODE
        // did exception occur in user mode ?
        and     r2, r1, #CPSR_MODE_BITS
        cmp     r2, #CPSR_USER_MODE
        bne     1f
        stmfd   sp, {r8-r12, sp, lr}^   // get user mode regs
 nop
        sub     sp, sp, #4*7
        bal     2f
1:
#endif
        // switch to pre-exception mode to get banked regs
        mov     r0,sp                   // r0 survives mode switch
        mrs     r2,cpsr                 // Save current psr for return
        orr     r1,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
        bic     r1,r1,#CPSR_THUMB_ENABLE
        msr     cpsr,r1
        stmfd   r0!,{r8-r12,sp,lr}
        msr     cpsr,r2                 // back to svc mode
        mov     sp,r0                   // update stack pointer

2:
        // now save pre-exception r0-r7 on current stack
        ldmfd   r3,{r0-r5}
        stmfd   sp!,{r0-r7}

        // sp needs fixing if exception occured in SVC mode.
        ldr     r1,[sp,#armreg_cpsr]
        and     r1,r1,#CPSR_MODE_BITS
        cmp     r1,#CPSR_SUPERVISOR_MODE
        ldreq   r1,[sp,#armreg_svcsp]
        streq   r1,[sp,#armreg_sp]

        mov     v6,sp                   // Save pointer to register frame

//      mov     r0,sp
//      bl      _show_frame_in

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
        // Switch to interrupt stack
        ldr     r2,.irq_level           // current number of nested interrupts
        ldr     r0,[r2]
        add     r1,r0,#1
        str     r1,[r2]                 // if was zero, switch stacks
        cmp     r0,#0
        moveq   r1,sp                   // save old stack pointer
        ldreq   sp,.__interrupt_stack
        stmeqfd sp!,{r1}
10:
#endif

        // The entire CPU state is now stashed on the stack,
        // increment the scheduler lock and handle the interrupt

#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
        .extern cyg_scheduler_sched_lock
        ldr     r3,.cyg_scheduler_sched_lock
        ldr     r4,[r3]
        add     r4,r4,#1
        str     r4,[r3]
#endif

        THUMB_MODE(r3,10)

        mov     r0,v6
        bl      hal_IRQ_handler         // determine interrupt source
        mov     v1,r0                   // returned vector #

#if defined(CYGPKG_KERNEL_INSTRUMENT) && \
    defined(CYGDBG_KERNEL_INSTRUMENT_INTR)
        ldr     r0,=RAISE_INTR          // arg0 = type = INTR,RAISE
        mov     r1,v1                   // arg1 = vector
        mov     r2,#0                   // arg2 = 0
        bl      cyg_instrument          // call instrument function
#endif

        ARM_MODE(r0,10)

        mov     r0,v1                   // vector #

#if defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \
    || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)
        // If we are supporting Ctrl-C interrupts from GDB, we must squirrel
        // away a pointer to the save interrupt state here so that we can
        // plant a breakpoint at some later time.

       .extern  hal_saved_interrupt_state
        ldr     r2,=hal_saved_interrupt_state
        str     v6,[r2]
#endif

        cmp     r0,#0 //#CYGNUM_HAL_INTERRUPT_NONE   // spurious interrupt
        bgt     10f
#ifndef CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
        mov     r0,v6                   // register frame
# ifdef __thumb__
        ldr     r1,=hal_spurious_IRQ
        mov     lr,pc
        bx      r1
# else
        bl      hal_spurious_IRQ
# endif
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_IGNORE_SPURIOUS
        b       spurious_IRQ

10:     ldr     r1,.hal_interrupt_data
        ldr     r1,[r1,v1,lsl #2]       // handler data
        ldr     r2,.hal_interrupt_handlers
        ldr     v3,[r2,v1,lsl #2]       // handler (indexed by vector #)
        mov     r2,v6                   // register frame (this is necessary
                                        // for the ISR too, for ^C detection)

#ifdef __thumb__
        ldr     lr,=10f
        bx      v3                      // invoke handler (thumb mode)
        .pool
        .code   16
        .thumb_func
IRQ_10T:
10:     ldr     r2,=15f
        bx      r2                      // switch back to ARM mode
        .pool
        .code   32
15:
IRQ_15A:
#else
        mov     lr,pc                   // invoke handler (call indirect
        mov     pc,v3                   // thru v3)
#endif
        b 10f                           // Do NOT acknowlage handled interrupt, that
is done by handler

spurious_IRQ:
        // Acknowlage spurious interrupt
        ldr     r4, =AT91_AIC
        str     r4, [r4,#AT91_AIC_EOI]
10:

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
        // If we are returning from the last nested interrupt, move back
        // to the thread stack. interrupt_end() must be called on the
        // thread stack since it potentially causes a context switch.
        ldr     r2,.irq_level
        ldr     r3,[r2]
        subs    r1,r3,#1
        str     r1,[r2]
        ldreq   sp,[sp]         // This should be the saved stack pointer
#endif
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
        // The return value from the handler (in r0) will indicate whether a
        // DSR is to be posted. Pass this together with a pointer to the
        // interrupt object we have just used to the interrupt tidy up routine.

                              // don't run this for spurious interrupts!
        cmp     v1,#CYGNUM_HAL_INTERRUPT_NONE
        beq     17f
run_dsr:
        ldr     r1,.hal_interrupt_objects
        ldr     r1,[r1,v1,lsl #2]
        mov     r2,v6           // register frame

        THUMB_MODE(r3,10)

        bl      interrupt_end   // post any bottom layer handler
                                // threads and call scheduler
        ARM_MODE(r1,10)
17:
#endif

//      mov     r0,sp
//      bl      show_frame_out

 // return from IRQ is same as return from exception
 b return_from_exception

#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
// Execute pending DSRs the interrupt stack
// Note: this can only be called from code running on a thread stack
FUNC_START_ARM(hal_interrupt_stack_call_pending_DSRs, r1)
        stmfd   sp!,{r4,r5,lr}
        // Disable interrupts
        mrs     r4,cpsr                 // disable IRQ's
        orr     r2,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
        bic     r5,r4,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
        msr     cpsr,r2
        // Switch to interrupt stack
        mov     r3,sp                   // save old stack pointer
        ldr     sp,.__interrupt_stack
        stmfd   sp!,{r3}                // stored at top of interrupt stack
        ldr     r2,.irq_level           // current number of nested interrupts
        ldr     r3,[r2]
        add     r3,r3,#1                // bump nesting level
        str     r3,[r2]
        msr     cpsr,r5                 // enable interrupts

        THUMB_MODE(r1,20)

        bl      cyg_interrupt_call_pending_DSRs


        ARM_MODE(r1,22)

        // Disable interrupts
        mrs     r1,cpsr                 // disable IRQ's
        orr     r2,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE
        msr     cpsr,r2

        // Move back to the thread stack.
        ldr     r2,.irq_level
        ldr     r3,[r2]
        sub     r3,r3,#1                // decrement nesting level
        str     r3,[r2]
        ldr     sp,[sp]                 // This should be the saved stack pointer
        msr     cpsr,r4                 // restore interrupts to original state

#ifdef __thumb__
        ldmfd   sp!,{r4,r5,lr}          // return
        bx      lr
#else
        ldmfd   sp!,{r4,r5,pc}          // return
#endif // __thumb__
#endif // CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK

// Thumb-only support functions
#ifdef __thumb__

FUNC_START_ARM(hal_disable_interrupts, r1)
        mrs     r0,cpsr                 // current state
        orr     r1,r0,#0xC0             // mask both FIQ and IRQ
        msr     cpsr,r1
        bx      lr                      // exit, _old_ in r0

FUNC_START_ARM(hal_enable_interrupts, r1)
        mrs     r0,cpsr                 // current state
        bic     r1,r0,#0xC0             // mask both FIQ and IRQ
        msr     cpsr,r1
        bx      lr                      // exit

FUNC_START_ARM(hal_restore_interrupts, r1)
        mrs     r1,cpsr                 // current state
        bic     r1,r1,#0xC0             // mask out FIQ/IRQ bits
        and     r0,r0,#0xC0             // keep only FIQ/IRQ
        orr     r1,r1,r0                // mask both FIQ and IRQ
        msr     cpsr,r1
        bx      lr                      // exit

FUNC_START_ARM(hal_query_interrupts, r1)
        mrs     r0,cpsr                 // current state
        bx      lr                      // exit, state in r0

#endif // __thumb__

// Dummy/support functions

        .global __gccmain
        .global _psr
        .global _sp

#ifdef __thumb__
        .code   16
        .thumb_func
__gccmain:
        bx      lr

        .code   16
        .thumb_func
_psr:
        ARM_MODE(r1,10)
        mrs     r0,cpsr
        bx      lr

        .code   16
        .thumb_func
_sp:
        mov     r0,sp
        bx      lr
#else
__gccmain:
        mov     pc,lr

_psr:
        mrs     r0,cpsr
        mov     pc,lr

_sp:
        mov     r0,sp
        mov     pc,lr
#endif


//
// Pointers to various objects.
//
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
PTR(__GDB_stack_base)
PTR(__GDB_stack)
#endif
PTR(__startup_stack)
PTR(__exception_stack)
PTR(__undef_exception_stack)
PTR(__bss_start)
PTR(__bss_end)
PTR(_end)
PTR(__rom_data_start)
PTR(__ram_data_start)
PTR(__ram_data_end)
PTR(hal_interrupt_handlers)
PTR(hal_interrupt_data)
PTR(hal_interrupt_objects)
PTR(__vector_lma)
PTR(init_flag)
#ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT
PTR(cyg_scheduler_sched_lock)
#endif
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
PTR(irq_level)
PTR(__interrupt_stack)
#endif
#ifdef  CYGHWR_HAL_ARM_DUMP_EXCEPTIONS
PTR(__dump_procs)
#endif

//
// Identification - useful to find out when a system was configured
_eCos_id:
        .asciz  "eCos : " __DATE__


// -------------------------------------------------------------------------
// Interrupt vector tables.
// These tables contain the isr, data and object pointers used to deliver
// interrupts to user code.

// Despite appearances, their sizes are not #defines, but .equ symbols
// generated by magic without proper dependencies in arm.inc
// Recompiling will not DTRT without manual intervention.

        .data

init_flag:
        .balign 4
        .long   0

        .extern hal_default_isr

        .globl  hal_interrupt_handlers
hal_interrupt_handlers:
        .rept   CYGNUM_HAL_ISR_COUNT
        .long   hal_default_isr
        .endr

        .globl  hal_interrupt_data
hal_interrupt_data:
        .rept   CYGNUM_HAL_ISR_COUNT
        .long   0
        .endr

        .globl  hal_interrupt_objects
hal_interrupt_objects:
        .rept   CYGNUM_HAL_ISR_COUNT
        .long   0
        .endr

// -------------------------------------------------------------------------
// Temporary interrupt stack

        .section ".bss"

// Small stacks, only used for saving information between CPU modes
__exception_stack_base:
#if defined(OPTION_FASTER_IRQ) &&
!defined(CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK_x)
        .rept   256
#else
        .rept   32
#endif
        .long   0
        .endr
__exception_stack:

        .rept   32
        .long   0
        .endr
__undef_exception_stack:

// Runtime stack used during all interrupt processing
#ifndef CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
#define CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE 4096
#endif
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
        .balign 16
        .global cyg_interrupt_stack_base
cyg_interrupt_stack_base:
__interrupt_stack_base:
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
        .byte 0
        .endr
        .balign 16
        .global cyg_interrupt_stack
cyg_interrupt_stack:
__interrupt_stack:
irq_level:
        .long   0
#endif

#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
        .balign 16
__GDB_stack_base:
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE // rather than 1k
        .byte 0
        .endr
__GDB_stack:
#endif
        .balign 16
__startup_stack_base:
#ifdef CYGIMP_HAL_COMMON_INTERRUPTS_USE_INTERRUPT_STACK
        .rept 512
#else
        .rept CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE
#endif
        .byte 0
        .endr
        .balign 16
__startup_stack:

#ifdef PLATFORM_EXTRAS
#include PLATFORM_EXTRAS
#endif

// --------------------------------------------------------------------------
//  end of vectors.S



-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]