0
0
Power-electronicsHow-ToBeginner · 3 min read

How to Write ISR in Embedded C: Syntax and Example

In Embedded C, an ISR (Interrupt Service Routine) is a special function triggered by hardware interrupts. You write it using the void ISR_name(void) __interrupt() syntax or compiler-specific keywords, and it must be kept short and fast to handle the interrupt efficiently.
📐

Syntax

An ISR is a function that runs automatically when an interrupt occurs. The syntax depends on your compiler, but generally it looks like this:

  • void: The function returns nothing.
  • ISR_name: The name you give to your ISR.
  • void: No parameters are passed.
  • __interrupt(): A keyword or attribute telling the compiler this is an ISR.

Some compilers require specifying the interrupt vector number.

c
void ISR_name(void) __interrupt() {
    // ISR code here
}
💻

Example

This example shows a simple ISR for a timer interrupt that toggles an LED. It demonstrates how to define the ISR and clear the interrupt flag.

c
#include <xc.h>  // Example for PIC microcontroller

volatile int led_state = 0;

void __interrupt() Timer_ISR(void) {
    if (TMR0IF) {          // Check Timer0 interrupt flag
        TMR0IF = 0;        // Clear interrupt flag
        led_state = !led_state;  // Toggle LED state
        LATBbits.LATB0 = led_state; // Set LED pin
    }
}

int main(void) {
    TRISBbits.TRISB0 = 0;  // Set RB0 as output
    LATBbits.LATB0 = 0;    // LED off initially

    TMR0 = 0;              // Reset timer
    TMR0IE = 1;            // Enable Timer0 interrupt
    PEIE = 1;              // Enable peripheral interrupts
    GIE = 1;               // Enable global interrupts

    while(1) {
        // Main loop does nothing, ISR handles LED toggle
    }
    return 0;
}
Output
LED connected to RB0 toggles on each Timer0 interrupt
⚠️

Common Pitfalls

Common mistakes when writing ISRs include:

  • Not clearing the interrupt flag inside the ISR, causing repeated interrupts.
  • Writing long or blocking code inside the ISR, which can delay other interrupts.
  • Using non-volatile variables without proper synchronization.
  • Not declaring the ISR with the correct compiler-specific keyword or attribute.
c
/* Wrong: Missing interrupt flag clear */
void __interrupt() Bad_ISR(void) {
    // Interrupt flag not cleared
    // This causes the ISR to run repeatedly
}

/* Correct: Clear interrupt flag */
void __interrupt() Good_ISR(void) {
    if (INT_FLAG) {
        INT_FLAG = 0; // Clear flag
        // ISR code
    }
}
📊

Quick Reference

Remember these tips when writing ISRs in Embedded C:

  • Use the correct __interrupt() keyword or attribute for your compiler.
  • Always clear the interrupt flag inside the ISR.
  • Keep ISR code short and fast.
  • Use volatile for variables shared with main code.
  • Disable interrupts only if absolutely necessary and re-enable them quickly.

Key Takeaways

Write ISRs using the compiler-specific interrupt keyword and void return type.
Always clear the interrupt flag inside the ISR to avoid repeated triggers.
Keep ISR code short to maintain system responsiveness.
Use volatile for variables shared between ISR and main code.
Test ISRs carefully to avoid unexpected behavior or system crashes.