# 5.5 The Core Challenge: ISRs and Tasks Synchronization

### <span class="ng-star-inserted">Understanding the Problem: Shared Data and Race Conditions</span>

<span class="ng-star-inserted">When a hardware interrupt occurs, the CPU immediately stops executing the current task and jumps to the ISR. This can happen at any time, even in the middle of a single line of C code that takes multiple machine instructions to execute. If the ISR and the task both access the same global variable, the system is vulnerable to a </span>**<span class="ng-star-inserted">race condition</span>**<span class="ng-star-inserted">.</span>

<span class="ng-star-inserted">A race condition is an undesirable situation that occurs when the outcome of a process depends on the uncontrollable sequence of events. In our case, it's a bug that occurs when the timing of the interrupt corrupts shared data.</span>

**<span class="ng-star-inserted">A Classic Example of a Race Condition:</span>**  
<span class="ng-star-inserted">Imagine a global variable </span>`<span class="inline-code ng-star-inserted">volatile int counter = 0;</span>`<span class="ng-star-inserted">.</span>

- <span class="ng-star-inserted">An ISR, triggered by a timer, is programmed to increment the counter: </span><span class="inline-code ng-star-inserted">`counter++`;</span><span class="ng-star-inserted">.</span>
- <span class="ng-star-inserted">A task in the main application is programmed to decrement it: </span><span class="inline-code ng-star-inserted">`counter--`;</span><span class="ng-star-inserted">.</span>

<span class="ng-star-inserted">Let's trace a potential failure scenario. Assume </span>`<span class="inline-code ng-star-inserted">counter</span>`<span class="ng-star-inserted"> is currently </span>`<span class="inline-code ng-star-inserted">10</span>`<span class="ng-star-inserted">.</span>

1. **<span class="ng-star-inserted">Task Executes:</span>**<span class="ng-star-inserted"> The task reads the value of </span>`<span class="inline-code ng-star-inserted">counter</span>`<span class="ng-star-inserted"> (10) into a CPU register.</span>
2. **<span class="ng-star-inserted">Task Calculates:</span>**<span class="ng-star-inserted"> The CPU calculates the new value, </span>`<span class="inline-code ng-star-inserted">10 - 1 = 9</span>`<span class="ng-star-inserted">.</span>
3. **<span class="ng-star-inserted">CONTEXT SWITCH (INTERRUPT):</span>**<span class="ng-star-inserted"> Before the task can write the value </span>`<span class="inline-code ng-star-inserted">9</span>`<span class="ng-star-inserted"> back to the </span>`<span class="inline-code ng-star-inserted">counter</span>`<span class="ng-star-inserted"> variable in memory, a hardware interrupt occurs!</span>
4. **<span class="ng-star-inserted">ISR Executes:</span>**<span class="ng-star-inserted"> The ISR runs. It reads the value of </span>`<span class="inline-code ng-star-inserted">counter</span>`<span class="ng-star-inserted"> from memory (which is still </span><span class="inline-code ng-star-inserted">10</span><span class="ng-star-inserted">).</span>
5. **<span class="ng-star-inserted">ISR Calculates:</span>**<span class="ng-star-inserted"> The ISR calculates </span>`<span class="inline-code ng-star-inserted">10 + 1 = 11</span>`<span class="ng-star-inserted">.</span>
6. **<span class="ng-star-inserted">ISR Writes:</span>**<span class="ng-star-inserted"> The ISR writes the value </span>`<span class="inline-code ng-star-inserted">11</span>`<span class="ng-star-inserted"> back to the </span><span class="inline-code ng-star-inserted">counter</span><span class="ng-star-inserted"> variable in memory.</span>
7. **<span class="ng-star-inserted">ISR Finishes:</span>**<span class="ng-star-inserted"> The interrupt is complete, and the CPU returns control to the task, restoring its state exactly where it left off.</span>
8. **<span class="ng-star-inserted">Task Resumes:</span>**<span class="ng-star-inserted"> The task is completely unaware that it was interrupted. Its next step is to write its calculated value (</span>`<span class="inline-code ng-star-inserted">9</span>`<span class="ng-star-inserted">) back to the </span>`<span class="inline-code ng-star-inserted">counter</span>`<span class="ng-star-inserted"> variable.</span>
9. **<span class="ng-star-inserted">Corruption:</span>**<span class="ng-star-inserted"> The value </span>`<span class="inline-code ng-star-inserted">11</span>`<span class="ng-star-inserted"> that the ISR correctly calculated is now overwritten with </span>`<span class="inline-code ng-star-inserted">9</span>`<span class="ng-star-inserted">. The increment operation has been completely lost.</span>

<span class="ng-star-inserted">This is the fundamental problem of concurrency: protecting shared resources from uncontrolled, simultaneous access.</span>

### <span class="ng-star-inserted">The ISR Context and </span>`<span class="inline-code ng-star-inserted">...FromISR()</span>`<span class="ng-star-inserted"> Functions</span>

<span class="ng-star-inserted">To solve the synchronization problem, we need tools to manage access to shared data. However, as we learned in Part 2, ISRs operate in a special </span>**<span class="ng-star-inserted">interrupt context</span>**<span class="ng-star-inserted">. They are not tasks and are not managed by the RTOS scheduler. This leads to a critical rule: </span>**<span class="ng-star-inserted">an ISR can never block</span>**<span class="ng-star-inserted">.</span>

<span class="ng-star-inserted">If an ISR tried to wait for a resource (like calling </span>`<span class="inline-code ng-star-inserted">xQueueSend()</span>`<span class="ng-star-inserted"> and the queue was full), it would effectively block. But since the ISR is not a task, the scheduler has no other context to switch to. The entire system would freeze, leading to a crash.</span>

<span class="ng-star-inserted">To solve this, FreeRTOS provides a special set of ISR-safe functions that are non-blocking. You can recognize them by their` `</span>`<strong class="ng-star-inserted"><span class="inline-code ng-star-inserted">...FromISR()</span></strong>`<span class="ng-star-inserted"> suffix.</span>

- `<span class="inline-code ng-star-inserted">xQueueSend()</span>`<span class="ng-star-inserted"> -&gt; </span>`<span class="inline-code ng-star-inserted">xQueueSendFromISR()</span>`
- `<span class="inline-code ng-star-inserted">xSemaphoreGive()</span>`<span class="ng-star-inserted"> -&gt; </span>`<span class="inline-code ng-star-inserted">xSemaphoreGiveFromISR()</span>`

<span class="ng-star-inserted">These functions include an optional parameter, </span>`<span class="inline-code ng-star-inserted">pxHigherPriorityTaskWoken</span>`<span class="ng-star-inserted">. An ISR uses this parameter to inform the RTOS if its action (e.g., giving a semaphore) has unblocked a task that has a higher priority than the task that was originally interrupted. If so, the RTOS can perform an immediate context switch to the higher-priority task as soon as the ISR finishes, ensuring the system remains as responsive as possible.</span>