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.