CS 273: The Real Time Interrupt (RTI)

The real-time interrupt provides a simple way to have an interrupt occur on a regular basis, independent of your programs activity. It's based on a "free-running counter", which means a hardware counter that keeps running regardless of your programs activity.

About the only control you have over the RTI is how fast it runs, and whether it actually triggers an interrupt. You can't stop it, you can't set a specific value in it, and you can't read it.

Controlling the RTI Speed

The speed of the RTI interrupt is determined by two bits in the Pulse Accumulator Control Register (PACTL) located at address $1026.

DDRA7 PAEN PAMOD PEDGE 0 0 RTR1 RTR0

Bits 4-7 aren't used by the RTI system; they are initialized to 0 on reset and can be left alone. Bits 1 and 0 (RTR1 and RTR0) set the rate at which the RTI requests interrupts, as follows:

RTR1RTR0Rate
004.10 ms
018.19 ms
1016.38 ms
1132.77 ms

(these numbers are for our particular clock speed. There's a table in the Reference Guide that shows the results for other clock speeds)

Enabling the RTI Interrupt

RTI interrupts are masked by the global interrupt mask, so you need to execute a CLI to enable any interrupts at all.

In addition, the RTI interrupt itself has its own interrupt enable bit, which is in Timer Interrupt Mask Register 2 (TMSK2), located at $1024:

TOI RTII PAVI PAII 0 0 PR1 PR0

As usual, there are quite a few bits in here that we don't need to worry about; the important one is RTII. This is an interrupt enable bit, so we need to write a 1 into this bit to enable RTI interrupts.

Handling RTI Interrupts

There are two things you need to keep track of in writing your interrupt service routine: first you need to set the interrupt vector to point to it, and second you need to make sure you properly set up the interrupt service routine itself so that you get back to your main program and reset the interrupt request.

Interrupt Vector

The RTI interrupt vector is located at address $fff0. This means you need to put the address of your RTI interrupt service routine at that address. Let's take a quick example.

Suppose your interrupt service routine starts at a label rtiint, like this:

* RTI Interrupt.
rtiint

Then, after your program code and before your end statement, you need to put

        org $fff0
        fdb rtiint

Interrupt Service Routine

In addition to whatever work your ISR needs to accomplish to do its job, there are two tasks it needs to perform: it needs to clear the interrupt request, and it needs to return to the main program.

Clearing the interrupt request

To clear the interrupt request, it writes a 1 to the RTI flag in Timer Interrupt Flag 2 Register (TFLG2), located$1025.

TOF RTIF PAOFV PAIF 0 0 0 0

The bits in this register are all screwy: you clear them by trying to write a 1 to them. Yes, it's backwards and doesn't make sense; no, I don't know why. The easiest way to do this is (paradoxically enough) to try to clear all the other bits in the register, so

        bclr   TFLG2,x   #%10111111

Note: Freescale says the most common problem with using the RTI interrupt is to forget this!

Returning from the interrupt

This step is actually the same for every interrupt service routine: you need to use an RTI instruction to return from the service routine. This restores all the registers to their state before the interrupt occurred.


Last modified: Wed Nov 11 11:42:16 MST 2009

Valid HTML 4.01 Transitional