How to Easily Debug Embedded Interrupts Using Logic: Part 1

Interrupts are some of the most useful features of typical microcontrollers. As with all things embedded, being able to get hands-on and eyes-on visibility into your interrupt code can make the difference between quickly resolving a coding error and confidently moving on to the next task, or spending a late night debugging by trial and error. The Saleae Logic 4 provides the visibility you need, in an easy to configure user interface allowing you to quickly understand and solve your interrupt issues.

This series of blog posts will show you how to use the Logic 4 to capture, view, and measure interrupt signals generated by a typical embedded system. For an example Device Under Test (DUT), we are using a micro-controller development kit from SiLabs, for their ‘F960 8051 derivative; however, the general ideas here should be useful for other parts as well. Example code demonstrating the handling of external interrupts is provided with many development kits, and this code has been modified to suit this example.

The Hardware

The F960 dev kit provides switches, connectors, lights, and power for the 80C51F960 microcontroller. We use one switch as an external interrupt on INT0, and two GPIO pins, which we call Output1 and Output2, to give Logic visibility into the code. Output1 and Output2 are active low and are pulled up to the positive rail when inactive. Jumper plugs connect one of the switches to the INT0 pin.

The Software

The software provides the necessary configuration for using External Interrupt 0 (/INT0) as an interrupt source connected to a switch. The code executes the initialization routines and then spins in an infinite while() loop. When the interrupt switch is pressed, the edge-triggered /INT0 input will cause an interrupt. The Interrupt Service Routine (ISR) drives Output1 and Output2 low at ISR entry, and does some simulated work (just a counter decrementing from twenty). After the simulated work is complete (the counter reaches zero) Output 1 is set inactive, and the ISR terminates. Output 2 is set inactive in main (with global interrupts disabled).

This software and hardware setup allow us to measure, by triggering on the falling edge of INT0 with the Logic 4, the following:

ISR response time
The time from assertion of the interrupt signal to ISR entry (from
INT0 active to Output 1 active)

ISR running time
The time required by the work done in the ISR (from Output1 active
to Output1 inactive)

ISR service time
The time from assertion of INT0 until the ISR has completed,
control has returned to main, and the system is ready to process
another interrupt

In this example, the software configures the system to use the low-power RC oscillator at 50 KHz for the clock.

Setting-up the Hardware

The hardware including the DUT and Logic were set up according to manufacturer recommendation, with particular care given to anti-static and electrical supply considerations. The Logic User Guide suggests most wall-wart powered devices are mains-isolated, however it is worth using an Ohmmeter to check your setup before applying power. The signals needed for this example are INT0, Output1, and Output2, shown  connected to Logic 4 along with the SYSCLK.

[![Debug embedded interrupts - Hardware Setup](http://blog.saleae.com/wp-content/uploads/2014/10/HardwareSetup1-700x466.jpg)](http://blog.saleae.com/wp-content/uploads/2014/10/HardwareSetup1.jpg)
Logic 4 Connected to DUT

Setting-up the Software

The key parts of the software relevant to this example are main() and the INT0 ISR, shown here.

// MAIN Routine
// Output1 is LED3
// Output2 is LED4
//—————————————————————————–
void main (void)
{

PCA0MD &= ~0x40; // Disable Watchdog timer

OscillatorInit(); // Initialize the system clock
Port
Init (); // Initialize crossbar and GPIO
ExtInterruptInit(); // Initialize External Interrupts

LED3 = LEDOFF; // Output1 off
LED4 = LED
OFF; // Output2 off
IE_EA = 1; // Global interrupt enable

// Infinite while loop waiting for an interrupt from /INT0

while(1)
{

IEEA = 0; // Global interrupt disable
LED3 = LED
OFF;
LED4 = LED_OFF; // ISR done, in main

IE_EA = 1; // Global interrupt enable

}

}

Debug embedded interrupts - Screenshot

//—————————————————————————–
// /INT0 ISR
//—————————————————————————–
//
// Whenever a negative edge appears on SW1, INT0ISR is run.
// The interrupt pending flag is automatically cleared by vectoring to the ISR
//
//—————————————————————————–
INTERRUPT(INT0
ISR, INT0_IRQn)
{

int count = 20;
SFRPAGE = LEGACYPAGE;
LED3 = LED
ON; // ISR start
LED4 = LEDON;
while(–count > 0); // Simulate ISR work
LED3 = LED
OFF; // ISR work done

}

Debug embedded interrupts - isr

Configure the Logic 4

The next step is to launch and configure the Logic 4. Channel 0 is connected to INT0, Channel 1 to Output1, Channel 2 to Output2, and Channel 3 to SYSCLK. We want to trigger on a switch press, which is connected to INT0, so click on the trigger mode box in the Channel 0 configuration menu and select the falling edge trigger. Name the signals to your preference by clicking on the name in the Channel box and typing a new name. Click on the up-down arrow in the green ‘Start’ button, to configure the capture duration (we don’t need many samples for this example, and Logic accepts fractional seconds here, so I entered 0.1). Over on the right, go to Options->Preferences and select 1M Pre-trigger buffer size. This video shows how to do it.

Now that we have shown you how to configure the Logic 4, learn how to capture here.

herb

0