5.5.11 · D1Embedded Systems & Real-Time Software

Foundations — FreeRTOS IPC — queues, semaphores, mutexes, event groups

4,242 words19 min readBack to topic

Before you can understand queues or mutexes, you must be fluent in the words the parent note assumes you already know. This page builds every one of them from nothing, in an order where each idea leans on the previous.


1. The kernel — the invisible manager

Why the topic needs it: every IPC object in the parent is described as a kernel object. The kernel is the neutral referee that makes ordering and atomicity trustworthy — without a single manager, no promise could be enforced.


2. Task — a program that thinks it owns the whole CPU

Figure s01 below draws exactly this: three task boxes, each with its own stack and priority, all fed by a single CPU block whose dashed arrows jump between them — "switches fast, one at a time." Trace one dashed arrow at a time to feel that the hands are never in two places.

Figure — FreeRTOS IPC — queues, semaphores, mutexes, event groups

Why the topic needs it: IPC = Inter-Process Communication. There is no "communication" problem unless you first have two separate things — the tasks — that must talk. See Producer–Consumer Pattern for the full treatment.


3. The scheduler and preemption — the hands that move

Why the topic needs it: this is the source of all danger. If the scheduler could never interrupt you, shared data could never be caught half-updated. Full detail lives in RTOS Scheduling — preemption & priorities.


4. Priority — a plain number that means "how urgent"

Why the topic needs it: the parent's whole discussion of priority inversion (the Mars Pathfinder bug — see Priority Inversion & the Mars Pathfinder bug) is a story about which numbered shirt gets the hands. You cannot follow it without this symbol.


5. Ready, Blocked, Running — the three states of a task

Figure s02 below is the state map you should keep in your head for the rest of the topic: the three boxes (Running, Ready, Blocked) and the labelled arrows between them — scheduled, preempted, take/wait (sleep), and event / timeout. Notice the two ways out of Blocked: an event or a timeout, exactly the alarm-clock picture above.

Figure — FreeRTOS IPC — queues, semaphores, mutexes, event groups

Why the topic needs it: every IPC object's real job is to move a task between Blocked and Ready at the right moment. "Wait on a queue", "take a semaphore", "wait for bits" all mean "put me in the back room until my condition is true (or my alarm rings)."


6. Atomic — "all-or-nothing", so nobody sees a half-done thing

Why the topic needs it: a plain count = count + 1 is three steps (read, add, write) — perfectly choppable. The parent says Give/Take on a semaphore are "atomic ops". That word is a promise the kernel makes — implemented by briefly disabling interrupts — that the counter can never be seen mid-update.


7. Race condition — the disease all IPC cures

Figure s03 below is that exact disaster on a timeline: Task A reads 5, an orange dashed preempt arrow freezes it, Task B reads the same 5 and writes 6, then A wakes and also writes 6. Read the bottom line — the whiteboard goes 5 → 6 → 6 when we expected 7. This one picture is why IPC exists.

Figure — FreeRTOS IPC — queues, semaphores, mutexes, event groups

Why the topic needs it: mutexes and critical sections (Critical Sections & taskENTER_CRITICAL) and queues are the tools that make such interleavings impossible.


8. FIFO — First In, First Out ordering

Why the topic needs it: a FreeRTOS queue (next section) is defined as a FIFO buffer. This word tells you the ordering guarantee you get for free.


9. Queue — the safe mailbox between tasks

Why the topic needs it: the queue is the parent's foundation object, and it combines three ideas built above (FIFO order, copy-by-value, Blocked/Ready). Everything else — even semaphores — is described as a stripped-down queue.


10. Copy by value vs. by pointer — what actually travels

Why the topic needs it: the parent's core safety claim ("self-contained and lifetime-safe") and its biggest trap ("send a pointer to avoid copying") both hinge on this distinction.


11. The notation 0b, |, and 1 << n — bit-flags

Why the topic needs it: event groups (Section 14) are literally a bank of these switches. You must know each named bit is one lit switch and | combines them before you meet the event-group API.


12. ISR — the Interrupt Service Routine

Why the topic needs it: the parent's ...FromISR functions, the "never block in an ISR" rule, and the "no owner ⇒ no mutex in an ISR" rule all follow from these two facts. Deeper treatment: Interrupt Service Routines & Deferred Processing.


13. The counter , Give and Take

Why the topic needs it: , Give, and Take are the only symbols in the semaphore section. All the ISR-signaling examples are just "ISR drops a token, task grabs one or sleeps."


14. Mutex and priority inheritance — the exclusive key

Why the topic needs it: the parent devotes a whole section to why a mutex beats a plain semaphore for locking. Both the ownership rule and priority inheritance are the reasons — you must have both pictures to follow it.


15. Event group — waiting on a combination of switches

Why the topic needs it: the parent introduces event groups precisely for logical combinations ("both WiFi AND config") and broadcasts. Without the switch-panel picture, xEventGroupWaitBits with its AND/OR flags is unreadable.


How these feed the topic

Kernel = manager

Scheduler + preemption

Stack = private notepad

Task = worker

Producer Consumer pair

Priority number H M L

Round-robin on ties

Race condition

Atomic all-or-nothing

Timeout xTicksToWait

Blocked Ready Running states

All IPC objects

FIFO ordering

Queue = mailbox

Value vs pointer

Counter c Give Take

Semaphore

Bit flags 0b and 1 shift n

Event group

ISR no context no block

Mutex priority inheritance


Equipment checklist

Self-test: cover the right side and answer out loud before revealing.

What is the kernel, in one line?
The always-present manager software (FreeRTOS) that owns the IPC objects, decides who runs, and is the only code allowed to block/wake tasks.
What is a stack and why does each task get its own?
Private scratch memory for locals and return addresses; separate stacks stop one task's scribbles from corrupting another's.
What is a task, in one line?
An independent forever-loop function with its own private stack and priority, written as if it owned the whole CPU.
What is the Producer–Consumer Pattern?
One task makes data (producer), another uses it (consumer); a queue between them buffers their speed mismatch.
What does "preemption" allow the scheduler to do?
Pause a running task mid-work to run a more urgent (higher-priority) one.
What does the scheduler do when several Ready tasks share the same priority?
Round-robin time-slicing — give each an equal one-tick turn in rotation so none starves.
In FreeRTOS, does a bigger priority number mean more or less urgent?
More urgent — the highest number that is ready runs.
Name the three task states and which one frees the CPU.
Running, Ready, Blocked — Blocked (sleeping) frees the CPU instead of busy-waiting.
What is a timeout / xTicksToWait?
The max ticks a task will stay Blocked before the kernel wakes it anyway; 0 = don't wait, portMAX_DELAY = wait forever.
What does "atomic" promise, and how does FreeRTOS deliver it?
All-or-nothing with no half-state visible; delivered by briefly disabling interrupts (taskENTER_CRITICAL) or locking the scheduler.
Describe a race condition in one sentence.
A bug where the outcome depends on the unlucky timing of preemption between tasks touching the same data.
What does FIFO guarantee about a queue?
First item in is the first item out — ordering is preserved, no cutting in line.
What is a queue as an IPC object (beyond FIFO)?
A kernel-owned buffer that copies same-size items task→task and blocks a full sender or an empty receiver.
Difference between copy-by-value and passing a pointer?
Value copies the actual bytes (self-contained); a pointer copies only an address, which can dangle if the target is freed.
What is 0b011 and what is 1 << 2?
0b011 is binary for 3 (switches 1 and 0 on); 1 << 2 is 4 (switch 2 on).
What are the two atomic moves on a semaphore counter ?
Give () and Take (, blocking while ).
What is an ISR and why can it never block?
An Interrupt Service Routine — a function hardware runs instantly on an event; it has no task identity, so it can't be put to sleep.
What makes a mutex different from a plain binary semaphore?
It has an owner (only the taker can release it) and supports priority inheritance.
What is priority inheritance and what does it prevent?
Temporarily raising a low task holding a key to the waiting high task's priority, preventing unbounded priority inversion.
What can an event group do that a single semaphore cannot?
Wake a task on an AND/OR combination of bits, and broadcast one bit-set to many waiters.