A queue holds storage for length × itemSize bytes plus two lists of blocked tasks: tasks waiting to send and tasks waiting to receive.
Receive on an empty queue: caller is moved to the "waiting to receive" list with a timeout. When a Send arrives, the kernel copies the item and unblocks the highest-priority waiting receiver.
Priority inversion (BAD) With inheritance (GOOD)
H ──wants lock──▒▒▒ blocked H ──wants──▒ short block
M ════runs forever════ L boosted to H, finishes lock
L holds lock, starved M can't preempt boosted L
Imagine one teacher (the CPU) helping many kids (tasks) one at a time. A queue is a tray of notes — a kid drops a note, another kid picks it up later, in order. A semaphore is a jar of tokens: take a token to use the slide; if the jar is empty you sit and wait until someone drops one in. A mutex is the single bathroom key — only the kid who took it can give it back, and if a slow kid has the key while an important kid is bursting, the teacher tells the slow kid "hurry, go first" so the key comes back fast. An event group is a checklist on the wall — a kid waits until both "lunch ready" and "hands washed" are ticked before going to eat.
What does a FreeRTOS queue transfer by — value or reference?
By value (it copies the item's bytes into kernel storage), unless you deliberately send a pointer.
Binary semaphore vs counting semaphore?
Binary: count 0/1 (one event flag). Counting: 0..N, remembers how many events/resources are available.
A semaphore is internally equivalent to what queue?
A queue with itemSize = 0; the count is the number of zero-byte items present.
Why use a mutex instead of a binary semaphore for locking?
Mutex has an owner (only taker can give) and supports priority inheritance to avoid priority inversion.
What is priority inversion and how does a mutex fix it?
A low-priority task holding a lock blocks a high-priority task while a medium task starves the low one; the mutex boosts the holder's priority to the waiter's until release.
Why must you NOT use a mutex from an ISR?
An ISR has no task identity to own the mutex or inherit priority; use a binary/counting semaphore's FromISR variant instead.
Which IPC lets a task wait for ALL or ANY of several conditions?
An event group (bits with AND/OR wait, optional clear-on-exit).
Why call xSemaphoreGiveFromISR + portYIELD_FROM_ISR in an ISR?
Give signals the waiting task without blocking; the yield switches to it immediately if it's higher priority, minimizing latency.
What happens when a task does xQueueReceive on an empty queue with portMAX_DELAY?
It blocks (removed from ready list) until an item is sent, then the kernel copies the item and unblocks it — CPU stays free meanwhile.
Risk of sending a pointer through a queue?
Dangling pointer if the pointed-to data is freed/overwritten before the receiver reads it; must manage ownership explicitly.
Dekho, FreeRTOS me ek hi CPU pe bahut saare tasks "ek saath" chalte hain, par actually kernel beech me kabhi bhi ek task ko rok ke doosra chala sakta hai (preemption). Agar do tasks ek hi variable ya hardware ko chhoo rahe hain, to ek task aadha kaam karke ruk jaaye aur doosra wahi cheez padh le — to data corrupt ho jaata hai. Isi race condition se bachne ke liye IPC objects bane hain.
Char main tools yaad rakho. Queue ek FIFO mailbox hai jo data ki copy bhej deta hai — producer note daalta hai, consumer baad me uthata hai, bilkul order me. Semaphore ek token jar hai: binary (0/1) ka matlab "event hua/nahi hua" flag, aur counting (0..N) ka matlab "kitne resource/event available hain". ISR se task ko jagaane ke liye xSemaphoreGiveFromISR use karte hain — ISR chhota rakho, heavy kaam task me karo. Mutex ek key hai shared resource (jaise I2C bus) ke liye; sirf wahi task release kar sakta hai jisne liya, aur priority inheritance se low-priority holder ki priority temporarily boost ho jaati hai taaki high-priority task zyada der na atke (priority inversion fix). Event group bits ka set hai — jab tumhe "WiFi up AND config loaded" jaisi combination pe wait karna ho, tab kaam aata hai.
Sabse common galti: mutex ko ISR se mat use karo (ISR ka koi owner task nahi hota — inheritance ka matlab hi nahi banta); ISR signaling ke liye binary/counting semaphore ka FromISR version lo. Aur queue me bada data bhejne ke liye pointer bhejo to ownership sambhaalo, warna dangling pointer ban jaayega. Yaad rakhna: Queue=data, Semaphore=signal/count, Mutex=owned lock, Event=AND/OR bits.