0
0
Power-electronicsHow-ToBeginner · 3 min read

How to Share Data Between ISR and Main in Embedded C

To share data between an ISR and the main program in Embedded C, use a volatile variable to prevent compiler optimizations. Protect shared data access by disabling interrupts briefly or using atomic operations to avoid data corruption.
📐

Syntax

Use the volatile keyword to declare variables shared between ISR and main. Disable interrupts around critical sections in main to safely access shared data.

  • volatile: tells the compiler the variable can change anytime.
  • Disable interrupts: prevents ISR from running during critical access.
c
volatile int shared_data;

void ISR_Handler(void) {
    shared_data = 42; // ISR updates shared data
}

int main(void) {
    int local_copy;
    __disable_irq(); // Disable interrupts
    local_copy = shared_data; // Read shared data safely
    __enable_irq(); // Enable interrupts
    // Use local_copy safely
    return 0;
}
💻

Example

This example shows an ISR updating a shared variable and the main function reading it safely by disabling interrupts briefly.

c
#include <stdio.h>
#include <stdbool.h>

volatile int shared_counter = 0;
volatile bool data_ready = false;

// Simulated ISR
void ISR_Handler(void) {
    shared_counter++;
    data_ready = true;
}

int main(void) {
    int local_counter = 0;

    // Simulate ISR call
    ISR_Handler();

    // Main loop reading shared data safely
    if (data_ready) {
        __disable_irq(); // Disable interrupts
        local_counter = shared_counter;
        data_ready = false;
        __enable_irq(); // Enable interrupts

        printf("Shared counter value: %d\n", local_counter);
    }

    return 0;
}

// Dummy functions to simulate interrupt control for this example
void __disable_irq(void) {}
void __enable_irq(void) {}
Output
Shared counter value: 1
⚠️

Common Pitfalls

Common mistakes include:

  • Not declaring shared variables as volatile, causing compiler optimizations to cache values incorrectly.
  • Accessing multi-byte shared variables without disabling interrupts, leading to corrupted reads or writes.
  • Using complex operations on shared data without atomicity, causing race conditions.

Always keep critical sections short and simple.

c
volatile int shared_var = 0;

// Wrong: reading shared_var without disabling interrupts
int read_shared_wrong(void) {
    return shared_var; // May read corrupted data if ISR updates simultaneously
}

// Right: disable interrupts to read safely
int read_shared_right(void) {
    int temp;
    __disable_irq();
    temp = shared_var;
    __enable_irq();
    return temp;
}
📊

Quick Reference

Tips for sharing data between ISR and main:

  • Declare shared variables as volatile.
  • Keep shared data types simple (preferably single-byte or atomic types).
  • Disable interrupts briefly in main when accessing shared data.
  • Use flags to signal data readiness.
  • Minimize time spent with interrupts disabled to avoid missing events.

Key Takeaways

Always declare variables shared between ISR and main as volatile to prevent optimization issues.
Protect multi-byte shared data access by disabling interrupts briefly in main code.
Use simple flags and atomic operations to signal and share data safely.
Keep critical sections short to maintain system responsiveness.
Avoid complex operations on shared data inside ISR to reduce timing issues.