Holon 11 Interrupt Service Routines
An interrupt service routine (ISR) is a subroutine that is called by an event instead of the program. ISRs run in parallel to your program. This is very elegant, but the elegance comes at a price. You must take care of several steps.
With Holon 11 you can implement and test all steps separately. This is probably best seen with an example. I assume that you are using Holon 11 with the monitor PMON on the target system, and consider the monitors EMON and IMON later.
The example presents a simple interrupt service routine for the real time interrupt (RTI) of the internal 68HC11 timer. The routine increments memory location $100. Holon 11 lets you watch the memory of a running program, and you can see the RTI in action.
Label RTI-ISR
inc $100
ldaa # $40 staa TFLG2 \ clear this RTI event
rti
An interrupt service routine ends with the instruction rti (return from interrupt) instead of rts (return from subroutine). Connect the routine with the event and enable the source of the RTI. When a real time interrupt occurs, the CPU jumps to the location that is contained in the RTI vector located at vRTI =$FFF0. The RTI is enabled, when the RTII bit in the 68HC11 register TMSK2 is set to one.
: SetRTI
RTI-IRS vRTI ! \ set interrupt vector
2 PACTL c! \ set RTI period = 16 ms
$40 TMSK2 c! \ set RTII in TMSK2, enable RTI
;
Load the code and execute the word SetRTI. See the contents of memory location $100 change (press F6, then Alt+F6 and enter the address 100. Be sure to see the target memory - press T)
The example is very simple and it will probably run. However, in the general case it is nice to be able to test every step. Here's how Holon 11 helps you.
Does the ISR do what you intended?
Is the interrupt vector set correctly?
Check the interrupt vector location with F6=Code: Does vRTI =$FFF0 contain the code address of RTI-ISR? The code address is displayed in the WORD window.
You can also set the interrupt vector interactively at the command line. Go to test mode (Ctl+F4) and enter the command RTI-ISR vRTI ! .
Are the interrupts enabled in the CPU?
Is the interrupt source enabled? Most interrupt sources are masked and must be enabled individually.
Is the interrupt acknowledged? The interrupt source must learn that the IRQ has been serviced, otherwise the IRQ stays pending. The interrupt is acknowledged in the ISR. Every source has its own rules, typically: read a register, set or clear a flag.
If the RTI-IRQ doesn't set this bit, a new RTI occurs instantly. The program spends the rest of its life in the RTI service routine. You can only stop it with a reset of the target system.
The monitor EMON operates in the internal EEPROM at $FF00 ff. This means that the interrupt vector space is in EEPROM and you can't simply write to the RTI vector here. It is possible to write into EEPROM, but EMON offers another solution. The interrupt vectors in EMON are redirected to a table of pseudo-vectors in the internal system RAM. A pseudo- vector consists of the opcode JMP and the address of the ISR.The RTI is directed to location evRTI=$3F1. The word SetRTI now inserts a JMP to the RTI-ISR at this pseudo-vector location.
: SetRTI
$7E evRTI c! RTI-ISR evRTI 1+ !
2 PACTL c! \ set RTI period = 16 ms
$40 TMSK2 c! \ set RTII in TMSK2
;
The example does not work with the monitor IMON, because IMON runs with interrupts disabled. You can use interrupts in your application, but you can't watch the memory while your program runs. However, you can watch external signals. For example generate a short pulse on bit 0 of port A and watch it with a logic probe.
Label RTI-ISR
ldaa PORTA anda # $FE staa PORTA ora # $01 staa PORTA
ldaa # $40 staa TFLG2
rti
Now create and run a simple program that is interrupted by the RTI, say, an infinite loop.
: main
1 DDRA c! \ turn PORTA bit 0 into an output
begin again ;
When you start the program from the monitor, interrupts are enabled. Therefore you should now detect pulses on port A/0.
Reset the target system to return control to the host (this is only needed with IMON, because the communication is polled. The monitor is offline while the user program runs.)
We also must be able to set an interrupt vector without activating target code. Holon 11 provides the compiler directive SetVector. Example:
( Set_RTI_vector )
RTI-ISR vRTI SetVector
When you load this script, the host writes the ISR address in the vector location in target memory. (A script is a Holon word that is interpreted when loaded. The name of the script is written in parentheses and the compiler ignores it.)
You can create pure assembler programs in Holon 11. The monitors IMON, PMON and EMON are assembler applications that are written in Holon 11.
In an assembler program replace the word SetRTI by the equivalent code in assembler.