Bike Spoke Images; timer interrupt woes

Interrupts are wonderful things for programmers, both for embedded system programmers using PICs, but also for PCs. Their utility comes from the fact that the processor is an inherently serial device[1]; it processes one instruction, and then another, and then another. And for the large part, that’s how we write code; one statement following another, following another.

Clock ticks

Imagine that you were writing a piece of code to tell the time, and that you didn’t have a seperate “clock unit”[1]. You know how fast the instruction clock is, and how many cycles each instruction takes, and so you could count how many cycles have gone since the last “time increment”. But you’d have to do that by hand, based on the source code. Could be do-able for a RISC chip like a PIC; the instructions all take 2 cycles (if I remember correctly). But for a complex instruction set (CISC) beastie like the long-in-the-tooth 8086 chip, different addressing modes would change the number of clock cycles from 6 to 12 [reference: http://zsmith.co/intel.html#clock]. Impossible.

Interrupts to the rescue! Interrupts literally interrupt the processor in what its doing, and say “go do this bit now”, where “this bit” is a separate piece of code stored at a a specific location. There’s what’s called a context switch first; basically a bookmark placed in the code (along with register contents) so that it can come back to it later; the interrupt routine is then free to do its job, and at the end of that says “that’s it, done”, and the processer does another context switch back to the pre-running code.

An historical aside

MS-DOS programmers had an meaning for “interrupt”, because the 8086 allowed you call interrupts with a “INT xx” command. Microsoft provided an API on INT 21, and the PC hardware would provide API on lower INT numbers. The wonderful Ralf Brown Interrupt List (http://www.ctyme.com/rbrown.htm) detailed them all. Sharp eyed readers will note that some viruses add their own install checks in there as well! I still remember the lever arch file full of the printout that I used back in the day.

Interrupt sources

For a PIC, interrupts can be generate from internal or external events. (No handy API for PIC programmers!). External events can be a peripheral[2] wanting attention (eg UART for RS232 comms[3], ADC finished it’s conversion), or an externally applied voltage going high, or internal, which is really just one of the timers.

The externally applied voltage we’re going to use for the output from the Hall Effect switch.

The timer we should use to do the timing to ensure that the relative timing works.

Testing timers

According to the documentation, an interrupt will be generated if

  1. The ToIE bit (bit 5 of INTCON register) is set, and
  2. The clock counter TMR0 overflows (i.e. goes from 255 to 0), and
  3. Interrupts are enabled.

Again, according to the docs, software should clear the interrupt.

So I wrote some initalization code that does this, and a C code interrupt handler:

void interrupt general_ISR(void) {
 // interrupt service routine. 
 if (INTCON & 0b00100100 == 0b00100100) { 
    // if bit 2 and 5 set, interrupt called
    counter++;
    INTCON = INTCON & 0b11111011; // clear bit 2
 }

}

This did not work for me. Neither in hardware, nor in the MPLAB provided simulator[4]. But reading the supplied lessons (!) showed that the following should work:

void interrupt general_ISR(void) {
 // interrupt service routine. 
 // two interrupts to check; GPIO and timer0 overflow...
 if (T0IE && T0IF) { //are TMR0 interupts enable and is TMR0 interrupt set?
    T0IF = 0; // clear in software
    counter++;
 }
}

Success! It works! I can only assume that something subtle  is happening in the compile process, but playing with the debugger shows that this is now called, and after a quick code change to light the LED, it works in hardware as well. Phew! It’s worth saying that this took 2 evenings of fiddling/reading/recompiling/head-wall interfacing to try alternatives/read docs/swear loudly… But now it works, and we can move on…

[1] I have a project in mind that will use a Real Time Clock chip.

[2] The PIC team have an odd idea about peripherals. For me, a peripheral is an external device. For the PIC team, a peripheral is an internal piece of circuitry that can be disabled; eg the ADC unit.

[3]  Not a feature of the PIC I’m using here, but a previous work related PIC project has used serial comms from a PC, and the UART takes all the pain out. Don’t do USB or RS232 comms in software; let the hardware handle it!

[4] Which I’d not played with before. I’ve used PICkit3, with its in circuit debugger[5], and PICkit1 (which I have at home) does have that, so I thought I was restricted to staring at the code and thinking hard. But one of the debugger tools in MPLAB is MPLAB SIM which is a full up simulator of the PIC device. And for a situation like this with no complicated external circuits, it was easy to show that my code never actually ran.

[5] Fantastic bit of kit. Single step through some PIC code whilst all the external hardware is attached? Yes please; great for debugging.

Advertisements

One thought on “Bike Spoke Images; timer interrupt woes

  1. Pingback: Bike Spoke Images; final breadboard? | Astrospanner's Project Blog

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s