view src/cs/system/main/gcc/irqfiq.S @ 78:95ef11e76c5b

src/cs/system/main/gcc: asm code pieced from Citrine
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 20 Jul 2018 06:46:56 +0000
parents
children
line wrap: on
line source

/*
 * This module contains the assembly shells for IRQ and FIQ, separated
 * from the architectured vectors only by some simple unconditional
 * branch instructions.
 *
 * Note that TI's way of handling interrupts sacrifices Nucleus' ability
 * to nest interrupts and minimize the IRQ-disabled window: if my (Falcon's)
 * understanding is correct, TI's code leaves all further IRQs disabled
 * for the full execution duration of an IRQ handler.  (IRQ handlers are
 * really LISRs, but TI's GSM fw does not use Nucleus' LISR framework.)
 */

	.text
	.code	32

	.globl	_INT_IRQ
_INT_IRQ:
        STMDB   sp!,{r0-r4}                 @ used to be a1-a4

/*
 * Thanks to TI for discovering and documenting this apparent ARM7TDMI bug:

BUG correction 1st part -------------------
It looks like there is an issue with ARM7 IRQ masking in the CPSR register
which leads to crashes in Nucleus+ scheduler.
Basically the code below  (correct as LOCKOUT = 0xC0) is used in many places by N+ but do not 
prevent from having an interrupt after the execution of the third line (I mean execution, not 
fetch).
        MRS     a1,CPSR                     ; Pickup current CPSR
        ORR     a1,a1,#LOCKOUT              ; Build interrupt lockout value
        MSR     CPSR,a1                     ; Lockout interrupts
       * IRQ INTERRUPT ! *
       Next instructions...

SW workaround:
When a task is interrupted at this point an interrupted context is stored on its task and will 
be resumed later on at the next instruction but to make a long story short it leads to some 
problem as the OS does not expect to be interrupted there.
Further testing tends to show that the CPSR *seems* to be loaded with the proper masking value 
but that the IRQ is still triggered (has been hardwarewise requested during the instruction 
exectution by the ARM7 core?)
*/

        MRS     a1,spsr                     @ check for the IRQ bug:
        TST     a1,#0x80                    @ if the I - flag is set,
        BNE     IRQBUG                      @ then postpone execution of this IRQ
/* Bug correction 1st part end --------------- */

        SUB     r4,lr,#4                    @ Save IRQ's lr (return address)
        BL      TCT_Interrupt_Context_Save  @ Call context save routine

        BL      IQ_IRQ_isr			@ Call  int. service routine

     /* IRQ interrupt processing is complete.  Restore context- Never 
        returns!  */
        B       TCT_Interrupt_Context_Restore

/* BUG correction 2nd part  ------------------ */
IRQBUG: LDMFD  sp!,{r0-r4}                  @ return from interrupt
        SUBS   pc,r14,#4
/* BUG correction 2nd part end  -------------- */

	.globl	_INT_FIQ
_INT_FIQ:
        STMDB   sp!,{r0-r4}                 @ used to be a1-a4
        SUB     r4,lr,#4                    @ Save FIQ's lr (return address)
        BL      TCT_Interrupt_Context_Save  @ Call context save routine

        BL      IQ_FIQ_isr                  @ Call the FIQ ISR

     /* FIQ interrupt processing is complete.  Restore context- Never 
        returns!  */
        B       TCT_Interrupt_Context_Restore