ST AN1776 Application note

ST AN1776 Application note

AN1776

APPLICATION NOTE

INTERRUPT HANDLING FOR STR7 MICROCONTROLLERS

by MCD Application Team

INTRODUCTION

An exception occurs when the normal flow of a program has to be halted temporarily. The reasons for an exception to occur can be due to an interrupt from a hardware peripheral, a coding error or incompatibility or even a user-defined exception. In each of these cases, the exception needs to be 'handled'. This means, the normal program execution needs to be paused, and the processor needs to be directed to a specially written section of code which performs a series of predetermined actions. The process of performing these special actions is called exception handling. This document gives a description of the use of the STR7 interrupt controller (EIC), as well as how to configure the EIC to be able to handle IRQ and FIQ exception, and therefore how it can be customized for your own application requirements.

All examples provided with this application note are developed with RVDK 2.1 for ST and optimized for the STR710-Demoboard.

This document assumes that the reader is familiar with the ARM7TDMI core and ARM assembler. For more details on the ARM core architecture, refer to the ARM Developer Suite Guide and the ARM Technical Reference Manual. These documents are available from the ARM website.

AN1776/1105

1/13

1

INTERRUPT HANDLING FOR STR7 MICROCONTROLLERS

1 EXCEPTION ENTRY AND EXIT

1.1 ENTERING AN EXCEPTION

This first section of this application note gives an introduction to Exception Handling by describing the basic default configuration of the ARM processors.

When an exception occurs, the ARM processor switches automatically to the ARM state and to the exception mode, copies the Current Program Status Register (CPSR) into SPSR_<mode> (where SPSR is the Saved Program Status Register, here in a particular mode), saves the return address in to LR_<mode>, sets the appropriate CPSR bits. The return address is stored in the Link Register, LR_<mode> to ensure that normal execution can resume following the exception handling. Finally, the Program Counter (PC) is set to the vector address to where the exception can be handled.

After handling the exception, the reverse process needs to be applied where CPSR is restored from SPSR_<mode> and the PC is restored from LR_<mode>.

Remember that exception handling can only be exited in ARM state, so if previously in Thumb state, prior to exit the exception, the core should switch states to ARM.

1.2 LEAVING AN EXCEPTION

To return from an exception, a data procession instruction is used however the exact instruction depends on the exception being handled.

In the ARM state, the use of the S bit normally sets the conditional flag. However, when in privileged modes, with the S bit set and the PC as the destination register, the instruction will update the PC and copy the SPSR_<mode> into the CPSR. Finally, still in privileged mode, LDM can be used with the ^ qualifier if LR_<mode> is adjusted before being stacked.

For SWI and Undefined exception handlers

MOVS pc, lr

For FIQ, IRQ and Prefect Abort exception handlers

SUBS pc, lr, #4

For Data Abort exception handlers

SUBS pc, lr, #8

LDM can be used with the ^ qualifier if LR adjusted before being stacked

LDMFD sp!,{pc}^

2/13

2

INTERRUPT HANDLING FOR STR7 MICROCONTROLLERS

2 EXCEPTION PRIORITIES

It is important to remember that several exceptions can occur simultaneously. However, all exceptions are assigned priorities and are served in a predefined order.

The exception with the highest priority is Reset. Next, in order of decreasing priority, there is the Data Abort, FIQ (Fast), IRQ (Normal), Prefetch Abort, SWI, and finally the Undefined instruction with the lowest priority.

3 EXCEPTION VECTORS

The Reset Vector is at address 0x0000. This is followed by the undefined instruction vector, the SWI vector, the Prefetch Abort vector, Data abort vector, IRQ vector and FIQ vector.

The exception vector should contain a valid instruction to branch to the exception handler.

A branch instruction (B Exception_Handler) or data instruction (LDR pc,[pc,#offset]) may be used to jump to the exception handler.

The B instruction can be used if the exception handler is within 32MByte of the exception vector. The LDR pc,[pc,#offset] instruction loads a content of a memory to the PC, this memory points the exception handler. This memory location is pointed to by the contents of the program counter content plus an offset. This is done this way since the exception handler is outside the 32 Mbytes branch instruction range. Note also that the offset has to be within a 4Kbyte boundary, however, this is not a problem since this address itself doesn't need to contain any code.

The other method of accessing the exception handler is by using the MOV instruction. When the MOV PC instruction is used, only an appropriate address boundary can be used.

Specially for FIQ exception, since the FIQ vector is the last vector in the table, the handler can be written directly starting from the FIQ vector. This is quite normal for the FIQ handler, since it allows for it to be executed immediately, as fast as possible, without having to jump elsewhere.

4 ARM OR THUMB ?

It may be necessary to have an application which contains a mixture of ARM and Thumb code. When an exception occurs, the processor will switch the state automatically to ARM. This is because the instruction held in the vector table associated with the exception vector must be an ARM instruction. This vector instruction will jump the program counter to an exception handler. Once the execution of this exception handler has finished, the processor returns to execute the application in the state it was originally running in, either ARM or Thumb.

3/13

INTERRUPT HANDLING FOR STR7 MICROCONTROLLERS

Note that the exception handler itself can be written in either ARM or Thumb instruction code. Any exception handler code written with the Thumb instruction set will return the processor to ARM state as the program counter will have to back to the original application code (i.e. main loop) with ARM instructions.

5 INTERRUPT HANDLING

This section of the application note gives an introduction to interrupt handling from the peripherals. In particular, the IRQ and FIQ interrupt modes are discussed. Many of the peripherals can be configured to generate interrupts in certain circumstances, for example a Timer might be set up to trigger an interrupt after a certain amount of time, periodically. How this Timer interrupt is handled by the exception handler is to be decided by the user-defined section of the handler of the code.

The ARM core has two levels of external interrupt handling, IRQ and FIQ, however the STR7 microcontrollers have a large number of interrupt sources. To manage all of the peripheral interrupts together with their priorities, the STR7 family of microcontrollers includes an Enhanced Interrupt Controller. The EIC has hardware handling of multiple interrupt channels, interrupt priority and automatic vectorization.

5.1 FIQ INTERRUPTS VERSUS IRQ INTERRUPTS

FIQ interrupts have a higher priority than IRQs which means that they will be serviced first when situations arise with both IRQ and FIQ events simultaneously. Servicing an FIQ will disable an IRQ and therefore IRQs will not be serviced until the FIQ handler completely exits.

FIQ interrupts are designed to be run as quickly as possible. The handler for FIQ can be placed directly at the end of the exception vectors table since the vector is the last in the table. A jump to another address therefore is not necessary and can be run immediately. In addition, FIQ mode has an additional 5 banked registers which means that there is less time wasted saving the non-banked registers before serving the FIQ exception handling and restoring them before exiting the exception.

5.2 SIMPLE INTERRUPT HANDLED IN C

The following example shows a simple interrupt handler written in C. In addition, the related assembly code is shown, compiled with and without __irq.

Note that the assembly code differs between one compiler to another.

__irq void IRQHandler (void)

 

 

{

*IRQChannel =

(u32 *)0xFFFFF804

 

 

u16

//

which interrupt was it

if

(* IRQChannel

== 0)

 

Channel0_IRQHandler();

//

process the interrupt

// insert checks for other interrupt sources here

4/13

Loading...
+ 9 hidden pages