My interrupt exception handler now looks like this:
__tx_irq_handler:
/* Jump to context save to save system context. */
B _tx_thread_context_save
__tx_irq_processing_return:
//
/* At this point execution is still in the IRQ mode. The CPSR, point of
interrupt, and all C scratch registers are available for use. In
addition, IRQ interrupts may be re-enabled - with certain restrictions -
if nested IRQ interrupts are desired. Interrupts may be re-enabled over
small code sequences where lr is saved before enabling interrupts and
restored after interrupts are again disabled. */
/* Interrupt nesting is allowed after calling _tx_thread_irq_nesting_start
from IRQ mode with interrupts disabled. This routine switches to the
system mode and returns with IRQ interrupts enabled.
NOTE: It is very important to ensure all IRQ interrupts are cleared
prior to enabling nested IRQ interrupts. */
LDR r0, =ADDR_THRESHOLD @ Get the IRQ Threshold 0x48200068
LDR r1, [r0, #0]
STMFD r13!, {r1} @ Save the threshold value
LDR r2, =ADDR_IRQ_PRIORITY @ Get the active IRQ priority
LDR r3, [r2, #0]
STR r3, [r0, #0] @ Set the priority as threshold
LDR r1, =ADDR_SIR_IRQ @ Get the Active IRQ
LDR r2, [r1]
AND r2, r2, #MASK_ACTIVE_IRQ @ Mask the Active IRQ number
MOV r0, #NEWIRQAGR @ To enable new IRQ Generation
LDR r1, =ADDR_CONTROL
CMP r3, #0 @ Check if non-maskable priority 0
STRNE r0, [r1] @ if > 0 priority, acknowledge INTC
DSB @ Make sure acknowledgement is completed
@
@ Enable IRQ and switch to system mode. But IRQ shall be enabled
@ only if priority level is > 0. Note that priority 0 is non maskable.
@ Interrupt Service Routines will execute in System Mode.
@
MRS r14, cpsr @ Read cpsr
ORR r14, r14, #MODE_SYS
BICNE r14, r14, #I_BIT @ Enable IRQ if priority > 0
MSR cpsr, r14
STMFD r13!, {r14} @ Save lr_usr
/*Even though TX_ENABLE_IRQ_NESTING is not defined the assembly code assumes that IRQ Nesting is enabled*/
#ifdef TX_ENABLE_IRQ_NESTING
BL _tx_thread_irq_nesting_start
#endif
/* For debug purpose, execute the timer interrupt processing here. In
a real system, some kind of status indication would have to be checked
before the timer interrupt handler could be called. */
@ BL TimerTickISR @ Timer interrupt handler
LDR r0, =ADDR_SIR_IRQ @ Address of INTC_SIR_IRQ ADDR_SIR_IRQ
LDR r2, [r0]
ANDS r0, r2, #127
LSLS r0, r0, #2
LDR r1, =fnRAMVectors
LDR r0, [r0, +r1]
BLX r0
LDMFD r13!, {r14} @ Restore lr_usr
/* If interrupt nesting was started earlier, the end of interrupt nesting
service must be called before returning to _tx_thread_context_restore.
This routine returns in processing in IRQ mode with interrupts disabled. */
/*Even though TX_ENABLE_IRQ_NESTING is not defined the assembly code assumes that IRQ Nesting is enabled*/
#ifdef TX_ENABLE_IRQ_NESTING
BL _tx_thread_irq_nesting_end
#endif
@
@ Disable IRQ and change back to IRQ mode
@
CPSID i, #MODE_IRQ
LDR r0, =ADDR_THRESHOLD @ Get the IRQ Threshold
LDR r1, [r0, #0]
CMP r1, #0 @ If priority 0
MOVEQ r2, #NEWIRQAGR @ Enable new IRQ Generation
LDREQ r1, =ADDR_CONTROL
STREQ r2, [r1]
LDMFD r13!, {r1}
STR r1, [r0, #0] @ Restore the threshold value
/* Jump to context restore to restore system context. */
B _tx_thread_context_restore
The TX_ENABLE_IRQ_NESTING
macro is undefined. And, after entering the specific interrupt handler I have to disable the interrupt and after interrupt processing is done, I have to reenable it.
What I have done is taken the code from IRQ Handler provided by TI except for the registers save and restore code at the beginning and the end, and I have put the code after the label __tx_irq_processing_return
.