0% found this document useful (0 votes)
23 views36 pages

Using Synch Mechanisms To Protect Shared Resources

This document discusses synchronization mechanisms for protecting shared resources in microcontroller-based systems, emphasizing the importance of data integrity in the presence of multiple execution contexts. It covers techniques such as volatile variables, atomic operations, mutexes, semaphores, and double buffering, along with their advantages and trade-offs. The document concludes by highlighting best practices for efficient synchronization in embedded systems to prevent race conditions and data corruption.

Uploaded by

nikhil kadu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
23 views36 pages

Using Synch Mechanisms To Protect Shared Resources

This document discusses synchronization mechanisms for protecting shared resources in microcontroller-based systems, emphasizing the importance of data integrity in the presence of multiple execution contexts. It covers techniques such as volatile variables, atomic operations, mutexes, semaphores, and double buffering, along with their advantages and trade-offs. The document concludes by highlighting best practices for efficient synchronization in embedded systems to prevent race conditions and data corruption.

Uploaded by

nikhil kadu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

Using

Synchronization
Mechanisms
to Protect
Shared Resources
in
MCU-Constrained
Systems
Table of Contents
Table of Contents

1. Introduction
2. Understanding the Problem of Shared
Resources
3. Using volatile for Shared Resources
4. Disabling and Restoring Interrupts (cli() and
sei())
5. Using
ATOMIC_BLOCK(ATOMIC_RESTORESTA
TE) for Critical Sections
6. Mutex Simulation in MCU-Based Systems
7. Protecting Shared Resources with Double
Buffering
8. Using Semaphores for Synchronization
9. Best Practices for Efficient Synchronization
Resources
Table of Contents
3. Using volatile for Shared Resources
4. Disabling and Restoring Interrupts (cli() and
sei())
5. Using
ATOMIC_BLOCK(ATOMIC_RESTORESTA
TE) for Critical Sections
6. Mutex Simulation in MCU-Based Systems
7. Protecting Shared Resources with Double
Buffering
8. Using Semaphores for Synchronization
9. Best Practices for Efficient Synchronization
in Embedded Systems
10.Conclusion
1. Introduction
1. Introduction

In microcontroller-based systems, where


hardware resources are limited,
synchronization is crucial to ensure data
integrity when multiple execution contexts
(such as interrupts, state machines, or tasks)
access shared resources. Without proper
synchronization, race conditions, inconsistent
data, and unpredictable system behavior can
occur.

This article explores essential


synchronization mechanisms for protecting
shared resources in AVR MCUs and similar
constrained embedded systems. We will
discuss techniques such as volatile variables,
occur. 1. Introduction

This article explores essential


synchronization mechanisms for protecting
shared resources in AVR MCUs and similar
constrained embedded systems. We will
discuss techniques such as volatile variables,
atomic operations, mutexes, semaphores,
and double buffering, providing real-world
examples and trade-offs between different
approaches.

Different synchronization techniques are used


depending on the system constraints,
resource access patterns, and real-time
requirements. Let’s explore the most
effective methods.
2. Understanding
the Problem of
Shared Resources
2. Understanding the Problem of
Shared Resources
What are Shared Resources?
In an embedded system, a shared resource is
any variable, memory location, or hardware
peripheral accessed by multiple execution
contexts. Examples include:
• Global variables modified by an ISR and
used in the main loop.
• I2C/SPI peripherals accessed by multiple
state machines.
• ADC readings updated in an ISR while the
main program processes the data.
• UART buffers shared between an
interrupt handler and a background
task.
• 2.
ADC readings updated
Understanding theinProblem
an ISR while
of the
Shared
main program Resources
processes the data.
• UART buffers shared between an
interrupt handler and a background
task.
2. Understanding the Problem of
Shared Resources

Why is Synchronization Needed?


Without proper synchronization:
1. Race Conditions: Two tasks accessing a
shared resource simultaneously can cause
unpredictable results.
2. Data Corruption: Multi-byte values
modified by an ISR can result in
inconsistent data reads.
3. System Instability: Uncontrolled
concurrent access may lead to undefined
behavior, causing the program to crash or
enter an infinite loop.
3. Using volatile
for Shared
Resources
3. Using volatile for Shared
Resources

When to Use volatile


A variable declared volatile tells the compiler
not to optimize it, ensuring it is always fetched
from memory. It is essential for:
• Interrupt-driven variables that change
outside the main execution flow.
• Memory-mapped registers for hardware
peripherals.

Example:
Using volatile to Access an ISR-Updated
Variable
• Memory-mapped registers for hardware
3. Using volatile for Shared
peripherals. Resources

Example:
Using volatile to Access an ISR-Updated
Variable

When volatile is NOT Enough


• Multi-byte variables (e.g., 16-bit or 32-bit on
an 8-bit MCU) may require atomic access.
3. Using volatile for Shared
Resources

When volatile is NOT Enough


• Multi-byte variables (e.g., 16-bit or 32-bit on
an 8-bit MCU) may require atomic access.
• Does NOT provide mutual exclusion (other
contexts may still modify the variable).
• Needs additional protection mechanisms
for safe concurrent access.
4. Disabling and
Restoring
Interrupts (cli()
and sei())
4. Disabling and Restoring
Interrupts (cli() and sei())

For short critical sections, you can disable


interrupts before accessing shared resources
and re-enable them afterward.

Example:
Protecting a Shared Variable with cli() and
sei()

Trade-offs
• Simple and effective for small critical
interrupts before accessing shared resources
4. Disabling and Restoring
and re-enable them(cli()
Interrupts afterward.
and sei())

Example:
Protecting a Shared Variable with cli() and
sei()

Trade-offs
• Simple and effective for small critical
sections.
• Disables all interrupts, which can impact
real-time performance if the critical section
• is too long.
5. Using
ATOMIC_BLOCK(
ATOMIC_RESTOR
ESTATE) for
Critical Sections
5. Using
ATOMIC_BLOCK(ATOMIC_RESTO
RESTATE) for Critical Sections

A more refined approach is using


ATOMIC_BLOCK(ATOMIC_RESTORESTATE
), which disables interrupts only temporarily
and restores their original state afterward.

Example:
Reading a Multi-Byte Sensor Value Atomically
), which disables 5. Using only temporarily
interrupts
ATOMIC_BLOCK(ATOMIC_RESTO
andRESTATE)
restores their
fororiginal stateSections
Critical afterward.

Example:
Reading a Multi-Byte Sensor Value Atomically

Advantages:
• Safer than cli()/sei() because it restores the
previous interrupt state.
• Ensures atomic access to shared
5. Using
ATOMIC_BLOCK(ATOMIC_RESTO
RESTATE) for Critical Sections

Advantages:
• Safer than cli()/sei() because it restores the
previous interrupt state.
• Ensures atomic access to shared
resources. Not suitable for longer critical
sections (still blocks interrupts briefly).
6. Mutex
Simulation in
MCU-Based
Systems
6. Mutex Simulation in MCU-
Based Systems

A mutex (mutual exclusion lock) ensures that


only one task accesses a shared resource at
a time.

Example:
Implementing a Mutex with Interrupt
Protection
Implementing a Mutex with Interrupt
6. Mutex Simulation in MCU-
Protection Based Systems

Advantages:
• Prevents simultaneous access to shared
resources.
6. Mutex Simulation in MCU-
Based Systems
Advantages:
• Prevents simultaneous access to shared
resources.
• Requires careful management to prevent
deadlocks.
7. Protecting
Shared Resources
with Double
Buffering
7. Protecting Shared Resources
with Double Buffering

How It Works
One buffer (active buffer) is used for reading.
Another buffer (working buffer) is updated in
the background.
Buffer swapping ensures consistency.

Example:
Double Buffering for Sensor Readings
the background.
7. Protecting Shared Resources
Buffer swapping ensuresBuffering
with Double consistency.

Example:
Double Buffering for Sensor Readings

Advantages:
• Prevents data corruption during updates.
• No need for disabling interrupts during
reads.
8. Using
Semaphores for
Synchronization
8. Using Semaphores for
Synchronization

Semaphores ensure one process accesses a


resource at a time, but they also allow
signaling between tasks.

Example:
Using a Semaphore to Synchronize ISR and
Main Loop
Using a Semaphore to Synchronize ISR and
8. Using Semaphores for
Main Loop Synchronization

Advantages:
• Efficient for ISR and main loop
coordination.
• Needs careful handling to avoid race
conditions.
9. Best Practices
for Efficient
Synchronization
in Embedded
Systems
9. Best Practices for Efficient
Synchronization in Embedded
Systems

• Minimize shared global variables to reduce


synchronization complexity.
• Use the lightest possible synchronization
method based on MCU constraints.
• Optimize ISR execution time to reduce lock
contention.
• Avoid unnecessary disabling of interrupts
to maintain system responsiveness.
10. Conclusion
10. Conclusion

Protecting shared resources is critical in MCU-


constrained systems to avoid race conditions,
data corruption, and system instability. By
choosing the right synchronization
mechanism—whether atomic operations,
mutexes, double buffering, or semaphores—
developers can build reliable and efficient
embedded applications.

You might also like