Introduction to critical sections
Knowing about critical sections and their background is an important thing for MCU programming. When starting with basic Arduino code examples on a Sketch level, especially when coming from AVR, everything concerning the execution flow of your program might feel to be pretty much straightforward and as you already know there’s usually no multitasking system in the background going on. So, you might assume: What could possibly go wrong when just calling
The answer is: Quite a lot.
This concise explanation in simple terms phrases the scope pretty good:
In simple terms, a critical section is a group of instructions/statements or a region of code that needs to be executed atomically, such as accessing a resource (file, input or output port, global data, etc.).
In concurrent programming, if one thread tries to change the value of shared data at the same time as another thread tries to read the value (i.e. data race across threads), the result is unpredictable.
Another good one is:
A Critical Section is the part of a program that accesses shared resources. […] We can avoid race conditions by making sure that no two processes enter their Critical Sections at the same time.
But there are no threads?
you might ask. That’s right, but there are interrupts. The concept of protecting your code using critical sections from simultaneously accessing resources doesn’t only come into place when doing multithreaded programming on larger CPUs resp. real multitasking systems, you will also have to protect some of your code from being interleaved by interrupts, otherwise things will probably go south.
So, it’s all about synchronizing access of multiple actors to singleton resources, this piece also has graphics: Process Synchronization in Operating System | Studytonight. In general: There are different mechanisms for synchronizing such things, most commonly they are referred to as “locks” or “mutexes” and there are even “spin-locks”. In this case, we focus on a mechanism called “critical sections”.
In the posts below, we want to outline some aspects specific to the AVR MCUs, but also about the Espressif ESP32 Xtensa dual-core MCU, where we will actually have to take care about symmetric multiprocessing aspects when protecting our code.
As people have been asking again and @weef and me are still trying hard to expose the point of that topic, let’s try from a different angle. This is all about “getting things right” from a software perspective. @weef already mentioned that aspect elsewhere, but nevertheless he also knows about the hardware side of things as well, so we might connect some dots here.