Mercurial > ecos
diff packages/hal/arm/arch/current/src/vectors.S @ 3173:afb59e9b7339
* cdl/hal_arm.cdl: Add CDL to control whether both IRQs and FIQs
are disabled in critical sections, or only IRQs. The default is to
disable both and translate any FIQs into IRQs for delivery. The
alternative is for FIQs to essentially exist outside eCos.
* include/hal_arch.h (CPSR_THREAD_INITIAL):
* include/hal_intr.h (CPSR_INTR_MASK, HAL_*_INTERRUPTS)
(HAL_*_FIQ): Add definitions for separating FIQ from IRQ.
* src/hal_mk_defs.c (main):
* src/vectors.S (start, FIQ, IRQ, spurious_IRQ):
(hal_*_interrupts, hal_*_FIQ, __fiq_stack_base): Add support for
separating FIQ from IRQ in critical section processing.
| author | nickg |
|---|---|
| date | Fri, 11 May 2012 10:24:33 +0000 |
| parents | a501465abec6 |
| children |
line wrap: on
line diff
--- a/packages/hal/arm/arch/current/src/vectors.S +++ b/packages/hal/arm/arch/current/src/vectors.S @@ -428,7 +428,12 @@ 2: mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE) msr cpsr,r0 ldr sp,.__exception_stack - +#ifndef CYGOPT_HAL_ARM_FIQ_DISABLE + mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_FIQ_MODE) + msr cpsr,r0 + ldr sp,.__fiq_stack +#endif + // initialize CPSR (machine state register) mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SUPERVISOR_MODE) msr cpsr,r0 @@ -770,6 +775,18 @@ 2: .code 32 FIQ: +#ifndef CYGOPT_HAL_ARM_FIQ_DISABLE + // If we are not disabling FIQs as part of eCos, these will be under + // user control. In theory the user should have installed their own + // FIQ VSR before enabling them and we should never come here. If + // we do there is nothing eCos itself can do because we are outside + // the scope of the system. The default action here, then, is to simply + // mask FIQs and return. + mrs r8,spsr // CPSR at time of interrupt + orr r8,r8,#CPSR_FIQ_DISABLE + msr spsr,r8 + subs pc,lr,#4 +#else // We can get here from any non-user mode. mrs r8,spsr // CPSR at time of interrupt and r9,r8,#CPSR_MODE_BITS // isolate pre-interrupt mode @@ -793,6 +810,7 @@ FIQ: // now it looks like we got an IRQ instead of an FIQ except that // FIQ is disabled so we don't recurse. +#endif 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. @@ -804,6 +822,17 @@ IRQ: mov r3,sp mrs r4,cpsr // switch to Supervisor Mode + +#ifdef CYGOPT_HAL_ARM_FIQ_DISABLE + // Due to a small chance of contention with FIQ, + // we should disable FIQ while still in IRQ mode and then + // change to SVC mode. This only applies when eCos is masking + // FIQ alongside IRQ, otherwise FIQs are outside eCos' control + // and the FIQ to IRQ translation doesn't happen. + orr r4,r4,#CPSR_FIQ_DISABLE + msr cpsr,r4 +#endif + bic r4,r4,#CPSR_MODE_BITS // When handling an IRQ we must disable FIQ unless the current // mode in CPSR is IRQ. If we were to get a FIQ while in another @@ -812,7 +841,10 @@ IRQ: // for example, the stack pointer would be set to the beginning // of the exception_stack clobbering the registers we have just // saved. - orr r4,r4,#CPSR_SUPERVISOR_MODE|CPSR_FIQ_DISABLE + // However, if we are allowing the user to handle their own + // FIQs, we don't need to do that, since FIQ will not be + // translated to IRQ. + orr r4,r4,#CPSR_SUPERVISOR_MODE|CPSR_INTR_MASK msr cpsr,r4 mov r5,sp // save original svc sp @@ -990,8 +1022,8 @@ FUNC_START_ARM(hal_interrupt_stack_call_ 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 + orr r2,r4,#CPSR_INTR_MASK + bic r5,r4,#CPSR_INTR_MASK msr cpsr,r2 // Switch to interrupt stack mov r3,sp // save old stack pointer @@ -1012,7 +1044,7 @@ FUNC_START_ARM(hal_interrupt_stack_call_ // Disable interrupts mrs r1,cpsr // disable IRQ's - orr r2,r1,#CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE + orr r2,r1,#CPSR_INTR_MASK msr cpsr,r2 // Move back to the thread stack. @@ -1036,21 +1068,21 @@ FUNC_START_ARM(hal_interrupt_stack_call_ FUNC_START_ARM(hal_disable_interrupts, r1) mrs r0,cpsr // current state - orr r1,r0,#0xC0 // mask both FIQ and IRQ + orr r1,r0,#CPSR_INTR_MASK // mask interrupts 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 + bic r1,r0,#CPSR_INTR_MASK // mask interrupts 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 + bic r1,r1,#CPSR_INTR_MASK // mask out interrupts + and r0,r0,#CPSR_INTR_MASK // keep only interrupts + orr r1,r1,r0 // mask interrupts msr cpsr,r1 bx lr // exit @@ -1060,6 +1092,38 @@ FUNC_START_ARM(hal_query_interrupts, r1) #endif // __thumb__ +#ifndef CYGOPT_HAL_ARM_FIQ_DISABLE + +// Functions for controlling FIQ independently of IRQ. +// These are only present if we are not manipulating FIQs +// alongside IRQs in the standard interrupt control macros. + +FUNC_START_ARM(hal_disable_FIQ, r1) + mrs r0,cpsr // current state + orr r1,r0,#CPSR_FIQ_DISABLE // mask FIQs + msr cpsr,r1 + bx lr // exit, _old_ in r0 + +FUNC_START_ARM(hal_enable_FIQ, r1) + mrs r0,cpsr // current state + bic r1,r0,#CPSR_FIQ_DISABLE // mask FIQs + msr cpsr,r1 + bx lr // exit + +FUNC_START_ARM(hal_restore_FIQ, r1) + mrs r1,cpsr // current state + bic r1,r1,#CPSR_FIQ_DISABLE // mask out FIQs + and r0,r0,#CPSR_FIQ_DISABLE // keep only FIQs + orr r1,r1,r0 // mask FIQs + msr cpsr,r1 + bx lr // exit + +FUNC_START_ARM(hal_query_FIQ, r1) + mrs r0,cpsr // current state + bx lr // exit, state in r0 + +#endif + // Dummy/support functions .global __gccmain @@ -1129,7 +1193,9 @@ PTR(__interrupt_stack) #ifdef CYGHWR_HAL_ARM_DUMP_EXCEPTIONS PTR(__dump_procs) #endif - +#ifndef CYGOPT_HAL_ARM_FIQ_DISABLE +PTR(__fiq_stack) +#endif // // Identification - useful to find out when a system was configured _eCos_id: @@ -1187,6 +1253,16 @@ hal_interrupt_objects: .endr __undef_exception_stack: +#ifndef CYGOPT_HAL_ARM_FIQ_DISABLE + .balign 16 +__fiq_stack_base: + .rept CYGNUM_HAL_ARM_FIQ_STACK_SIZE + .byte 0 + .endr + .balign 16 +__fiq_stack: +#endif + // Runtime stack used during all interrupt processing #ifndef CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE #define CYGNUM_HAL_COMMON_INTERRUPTS_STACK_SIZE 4096
