This is the mail archive of the
ecos-discuss@sources.redhat.com
mailing list for the eCos project.
Re: Atmel Ecos AIC
- From: "Eric de Jong" <list_ericdejong_10 at gmx dot net>
- To: <ecos-discuss at sources dot redhat dot com>
- Date: Tue, 2 Mar 2004 11:25:53 +0100
- Subject: [ECOS] Re: Atmel Ecos AIC
- References: <1078153023.2355.7.camel@linux.local>
- Reply-to: "Eric de Jong" <list_ericdejong_10 at gmx dot net>
>> 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