EmbDev.net

Forum: ARM programming with GCC/GNU tools Is my interrupt handler correct?


von Dan M. (gorlash)


Rate this post
useful
not useful
I'm still having problems with interrupts apparently interacting with 
each other. Our design has timer0, ADC, UART0/1, and RTC running. The 
basic problem we're seeing is various anomalies in the UART interrupts, 
which vary depending upon which other interrupts are enabled. Since I 
never found a "canonical" reference for the Interrupt Handler, I've used 
various references over the past year. Originally I was using the 
version from the ST USB demo (RIDE), but that apparently is incomplete. 
I then switched to the version used by IAR, but I really have no 
guarantee that this is complete and correct in our current (Yagarto) 
build environment.

I would be grateful if people here (especially those who are also using 
multiple interrupts, and are building with Yagarto or other GnuArm 
environments) could comment on this code, which I'm enclosing below.

Thank you all very much!!

Dan Miller

/*;********************************************************************* 
**********
;* Macro Name : SaveContext
;* Description : This macro used to save the context before entering
; an exception handler.
;* Input : The range of registers to store.
;* Output : none
;*********************************************************************** 
********/
.macro SaveContext reg1 reg2
STMFD sp!,{\reg1-\reg2,lr} /* Save The workspace plus the current return 
*/
/* address lr_ mode into the stack */
MRS r1, spsr /* Save the spsr_mode into r1 */
STMFD sp!, {r1} /* Save spsr */
.endm

/*;********************************************************************* 
**********
;* Macro Name : RestoreContext
;* Description : This macro used to restore the context to return from
; an exception handler and continue the program execution.
;* Input : The range of registers to restore.
;* Output : none
;*********************************************************************** 
********/
.macro RestoreContext reg1 reg2
LDMFD sp!, {r1} /* Restore the saved spsr_mode into r1 */
MSR spsr_cxsf, r1 /* Restore spsr_mode */
LDMFD sp!, {\reg1-\reg2,pc}^ /* Return to the instruction following */
/* the exception interrupt */
.endm

/*********************************************************************** 
*********
* Function Name : IRQHandler
* Description : This function is called when IRQ exception is entered.
* Input : none
* Output : none
************************************************************************ 
********/
IRQHandler:
# STR9 firmware method from ST (Ride code)
# SUB lr,lr ,#4
# SaveContext r0,r4
# LDR r0, = VectorAddress
# LDR r0, [r0] /* Read the routine address from VIC0 Vector Address 
register */
#
# BLX r0 /* Branch with link to the IRQ handler. */
# RestoreContext r0,r4

# STR9 firmware method from IAR
SUB lr,lr,#4 /* ; Update the link register */
SaveContext r0,r12 /* ; Save the workspace plus the current */
/* ; return address lr_irq and spsr_irq */
LDR r0, = VectorAddress
LDR r0, [r0] /* ; Read the routine address */
LDR r1, = VectorAddressDaisy
LDR r1, [r1]
/* ; Padding between the acknowledge and re-enable of interrupts */
/* ; For more details, please refer to the following URL */
/* ; http://www.arm.com/support/faqip/3682.html */
NOP
NOP
MSR cpsr_c, #Mode_SYS /* Switch to SYS mode and enable IRQ */

STMFD sp!,{lr} /* ; Save the link register. */
LDR lr, =IRQ_ReturnAddress /* ; Read the return address. */
BX r0 /* ; Branch to the IRQ handler. */
IRQ_ReturnAddress:
LDMFD sp!,{lr} /* ; Restore the link register. */
MSR cpsr_c, #Mode_IRQ|I_Bit|F_Bit /* Switch to IRQ mode and disable IRQ 
*/
LDR r0, =VectorAddress /* ; Write to the VectorAddress to clear the */
STR r0, [r0] /* ; respective interrupt in the internal interrupt */
LDR r1, =VectorAddressDaisy /* ; Write to the VectorAddressDaisy to 
clear the */
STR r1,[r1] /* ; respective interrupt in the internal interrupt */
RestoreContext r0,r12 /* ; Restore the context and return to the program 
execution. */

von Erwin Pantuca (Guest)


Rate this post
useful
not useful
Greetings.
We are having similar problems with uart: missing characters and uart 
interrupt stops triggering after some time.  Using STR912FAW44.  At 
other tests with minor modifications, it seems to work properly more 
often like 70%, but the remaining 30% still have the same problems.

We have just inherited this project, and the source code is a mess, and 
we are new to ARM and still learning with difficulty.

We are using an RTOS, but we believe it is not the cause of our 
problems.
We are now investigating STR912 interrupt management issues that may be 
the cause, based on STMicro errata on the cpu revision that we are 
using.
I have noticed your code as similar to ours, except that currently it 
has been modified for some reason in this line:
original:
MSR    cpsr_c,#0x1F
current:
MSR    cpsr_c,#0x1F | I_Bit

Why I_Bit is set we have not yet received information from the original 
team.  This will disable the interrupts.

Other info:
We are having problems with Uart1.  Uart0 is also used but does not seem 
to have any problems.  We have also utilized Uart2 for temporary debug 
output.  Originally Uart1 enabled the FIFO.  But someone from old team 
modified the settings to not use FIFO, without updating the Uart1 
handler.  We are fixing this now.  But this would probably not cause the 
other problem of interrupts getting blocked.
THank you for any info.
Erwin

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.