CS452 - Real-Time Programming - Spring 2011
Lecture 11 - ARM Interrupts
Pubilic Service Announcement
- Kernel 1 comments
Hardware Interrupts
What is a Hardware Interrupt?
What the CPU does for you
- Test interrupt signal before fetching the next instruction
- actually AND of INT and CPSR bit
- If asserted, change mode to IRQ
- Disable interrupt in CPSR
- Execute instruction at 0x18
In the Interrupt Control Unit (ICU)
- Vectored operation is possible: several interrupts may be present when
an interrupt occurs
- One is chosen, by a priority mechanism
- Put in a special place
- Software can choose to ignore priority mechanism in ICU
- Clearing one interrupt may just expose another one
In the Peripheral Hardware
- Several interrupts may be present
- ORed in peripheral hardware
- ORed in glue hardware
- Rare that there is a priority mechanism
- Clearing one interrupt can expose another one
When two interrupts are present
May have been two present when interrupt processing started
- in which case interrupt occurring now is known to be of lower
priority
May have occurred since interrupt processing started
- in which case interrupt occurring now may be of higher priority
What happens next?
- Kernel executes with interrupts disabled
- Context switch into user task turns on interrupts
- Before fetching the first user task instruction test interrupt
signal
- If asserted, re-initiate interrupt processing
Kernel Provision for Interrupts
- Initialize the kernel with interrupts disabled
- Turn on interrupts by having user PSW with interrupts enabled
- First instruction of user task might not execute immediately
- Find source of interrupt
- Turn off source of interrupt
- In device
- In ICU
- PSR remains with IRQ disabled
- Handle interrupt
- Find waiting task
- Make waiting task READY
- Reschedule and activate
Three Free Choices
- Rescheduling
- Volatile Data
- Re-enabling interrupts
The Hardware in the Trains Lab
32-bit Timer
Base address: 0x80810080
Three registers:
| Offset |
Function |
R/W |
Bits |
Comments |
| 0x0 |
Timer3Load |
R/W |
32: <Load/Reload Value> |
|
| 0x4 |
Timer3Value |
R |
32:<Current value> |
Set when Load is written,
even when counting |
| 0x8 |
Timer3Control |
R/W |
3:xxx<CLKSEL>xx<MODE><ENABLE> |
<CLKSEL>: 0, 2KHz clock; 1, 508KHz
<MODE>: 1, count continuously; 0, count once
<ENABLE>: Clock turned on
|
| 0xc |
Timer3Clear |
W |
32: |
Writing anything clears the interrupt |
Interrupt Control Unit (ICU)
ARM PL190.
The logic in this design is completely asynchronous, so it functions when
the CPU clock is turned off.
- Important (= essential) for low power operation.
All input signals from device are
- active high
- level sensitive
Base addresses
- VIC1:
0x800B0000
- VIC2:
0x800C0000
Basic Operation
VIC powers up with
- all vectored interrupts disabled.
- all interrupts masked
- all interrupts giving IRQ (not FIQ)
- protection off
Procedure
Initialization
- leave protection off
- enable in VICxIntEnable when you are ready to handle the interrupt
On an interrupt
- Read VICxIRQStatus
- Choose which interrupt you wish to handle
- Clear the interrupt source in the device
For debugging
- Use VICxSoftInt and VICxSoftIntClear to turn interrupt sources off and
on in software
Hardware Definitions
Registers for Basic Operation
| Register Name |
Offset |
R/W |
Description |
| VICxIRQStatus |
0x00 |
R |
One bit for each interrupt source
1 if interrupt is asserted and not masked
These are the interrupts you respond to
|
| VICxFIQStatus |
0x04 |
R |
As above, for FIQ |
| VICxRawIntr |
0x08 |
R |
As for IRQStatus, but not masked |
| VICxIntSelect |
0x0c |
R/W |
0: IRQ, 1: FIQ |
| VICxIntEnable |
0x10 |
R/W |
0: Masked, 1: Enabled |
| VICxIntEnClear |
0x14 |
W |
Clears bits in VICxIntEnable |
| VICxSoftInt |
0x18 |
R/W |
Asserts interrupt from software |
| VICxSoftIntClear |
0x1c |
W |
Clears interrupt from software |
| VICxProtection |
0x20 |
R/W |
Bit 0 enables protection from user mode access
Writable only in priveleged modes |
| VICxVectAddr |
0x30 |
R/W |
Enables priority hardware
See documentation. |
Helpful Features of the ICU
- Several places where you can read state
- Several places where you can block interrupt flow
- Trigger hardware interrupt from software
- What makes interrupts hard is that you are doing two semi-hard things
at once
- Making the hardware produce the interrupt
- Responding to the interrupt
- This allows you to separate them in developing/debugging
Non-vectored Operation
Initialization
- Enable interrupt in device
- Enable interrupt in ICU
- Enable interrupt in CPU, usually by MOVS
Interrupt occurs
- AND of IRQ and NOT( IRQ disabled ) is checked before each instruction
fetch.
- If set IRQ exception is taken in place of next instruction fetch.
- Possibly zero instructions of active task are executed.
- Make sure that this case works
- Context switch into kernel
Context switch novelties
Difference from Software Interrupts
- It is impossible to predict where they occur
- You probably made some assumptions about when they occur
- Scratch Registers must be saved
- Two Link Registers
- One to return from interrupt
- One to return from the interrupted task to whatever called
it
- Turn off interrupt in device
- Should turn off interrupt in ICU
- What about IRQ?
You are now ready to process the interrupt in the kernel
Vectored Operation
Procedure
Initialization
- Write kernel entry point into VICxDefVectAddr
- If desired write special entry point into VICxVectAddry
- When ready to accept interrupts write source and enable into
VICxVectCntly
When an interrupt occurs
- Read VICxVectAddr to find address
- Move result to PC
- When service is complete write VICxVectAddr to start priority
hardware
Look carefully at what's in 0x18
- Usually,
ldr pc, [pc, #offset]
<IRQ> is the offset from the pc to the kernel
entry
- How is the instruction encoded
- 31:28 - condition codes
- 27:20 - op code and flags, 0101<offset sign>001
- 19:16 - base register
- 15:12 - destination register
- 11:00 - 12-bit offset
- With a 12 bit offset and pc=0x18 you can address
- from
0x18 + 0x8 - 0xffc = -0xfdc
=0xfffff020
- to
0x18 + 0x8 + 0xffc = 0x1020
- You could have the kernel entry point in
- either
0x800b0030
- or
0x800c0030
- Both are out of range. What could you do?
| Register Name |
Offset |
R/W |
Description |
| VICxVectAddr |
0x030 |
R/W |
Read: address of vector for highest priority interrupt
Write: service complete, enable priority hardware
|
| VICxDefVectAddr |
0x034 |
R/W |
Default vector address |
| VICxVectAddry |
0x100+4y |
R/W |
Vector address for interrupt y |
| VICxVectCntly |
0x200+4y |
R/W |
Control register for interrupt y
Bit[0-4]: interrupt source for interrupt y
Bit[5]: enable vectored interrupt y
|
Return to: