5.5.11 · D2 · HinglishEmbedded Systems & Real-Time Software

Visual walkthroughFreeRTOS IPC — queues, semaphores, mutexes, event groups

2,313 words11 min read↑ Read in English

5.5.11 · D2 · Coding › Embedded Systems & Real-Time Software › FreeRTOS IPC — queues, semaphores, mutexes, event groups

Queue ko touch karne se pehle hume teen words pe agree karna hoga: task, ready list, aur block. Hum inhe tab tak use nahi karenge jab tak ye draw na ho jaayein.


Step 1 — "Bahut saare tasks, ek CPU" actually kaisa dikhta hai

KYA. Ek task sirf ek aisi function hai jo ek loop mein hamesha chalti rahti hai, saath mein thoda saved state (iska stack, iske registers). CPU ek waqt mein sirf ek task chala sakta hai. Kernel ka ek hissa jise scheduler kehte hain woh decide karta hai kaunsa task chalega, aur woh preempt bhi kar sakta hai — current task ko beech mein freeze karke switch kar sakta hai — jaise RTOS Scheduling — preemption & priorities mein cover kiya gaya hai.

WHY yahan se shuru karein. Queue jo kuch bhi karta hai woh hai ek task ko do piles ke beech move karna. Toh pehle hume woh piles dekhni chahiye. Ek Ready list hoti hai (tasks jo CPU chahte hain aur sirf apni baari ka intezaar kar rahe hain) aur, har kernel object ke liye, ek Blocked list (tasks jo so rahe hain, kisi specific cheez ka intezaar kar rahe hain).

PICTURE. Do coloured boxes dekho. Lavender Ready box mein woh tasks hain jo abhi run kar sakte hain; CPU (woh chota chip) highest-priority wala task choose karta hai. Blocked box abhi khali hai — koi kisi cheez ka intezaar nahi kar raha abhi.

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

Step 2 — Queue teen parts wala ek box hai

KYA. Hum queue banate hain xQueueCreate(length, itemSize) se. Concretely kernel teen cheezein allocate karta hai:

Term by term padhein: length hai kitne items fit hote hain; itemSize hai har item kitne bytes ka hai; unka product total mailbox storage hai. Dono lists khali start hoti hain — woh tabhi bharta hai jab kisi task ko wait karna padta hai.

WHY teen parts. Sirf storage senders ko spin karne par majboor kar deta ("kya abhi room hai? kya abhi room hai?"). Data ke paas hi do lists of sleeping tasks rakhne se, kernel ek task ko so daal sakta hai aur baad mein exactly sahi wale ko jagaa sakta hai — bina spinning ke.

PICTURE. Paanch mint slots (is queue ki length = 5 hai), sab khali. Unke neeche, do khali trays jisme likha hai senders waiting aur receivers waiting.

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

Step 3 — Khali queue pe Receive → task so jaata hai

KYA. Consumer xQueueReceive(q, &got, portMAX_DELAY) run karta hai. Queue khali hai. Copy karne ke liye kuch nahi hai.

WHY woh return karne ki jagah block karta hai. Humne portMAX_DELAY (hamesha) tak wait karne ko kaha. Kyunki storage khali hai, kernel useful kaam karta hai: woh Consumer ko Ready se nikaalkar queue ki receivers-waiting list mein daal deta hai. Ab scheduler ise ignore karta hai. CPU kisi aur ko run karne ke liye free hai.

PICTURE. Arrow dekho: Consumer task lavender Ready box se queue ke receivers waiting tray mein jaata hai. Woh ab grey hai (so raha hai). Storage slots abhi bhi khali hain.

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

Step 4 — Send aata hai → bytes ko ek slot mein copy karo

KYA. Ab Producer xQueueSend(q, &v, ...) run karta hai. Yahan v Producer ki local value hai aur &v woh hai jahan se copy karna hai. Kernel itemSize bytes v se pehle free storage slot mein copy karta hai.

WHY poori value copy karo (pointer nahi). Jis second Producer preempt ho jaata hai, uski local v overwrite ho sakti hai ya scope se bahar ja sakti hai. Raw bytes ko kernel-owned storage mein copy karna message ko self-contained bana deta hai — uski lifetime ab sender pe depend nahi karti. (Yeh woh copy-by-value guarantee hai jo parent note ne emphasize kiya tha.)

PICTURE. Ek coral arrow v ke bytes Producer ke stack se mint storage ke slot 0 mein copy karta hai. Slot 0 coral ho jaata hai (ab occupied); slots 1–4 khali rehte hain.

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


Step 5 — Wake-up: kernel highest-priority receiver ko unblock karta hai

KYA. Copy karne ke turant baad, kernel receivers-waiting list check karta hai. Woh khali nahi hai — Consumer wahan baitha hai. Toh kernel:

  1. bytes ko slot se us address (&got) mein copy karta hai jo Consumer ne chhoda tha,
  2. Consumer ko receivers-waiting se hataata hai,
  3. use wapas Ready list mein daal deta hai.

WHY highest-priority. Agar kai tasks wait kar rahe the, toh kernel highest-priority wale ko pehle jagaata hai, priority rules ka paalan karte hue. Yeh RTOS ka "sabse urgent kaam pehle" waada poora karta hai.

PICTURE. Do arrows: ek butter arrow slot 0 → got mein copy karta hai; ek lavender arrow Consumer ko soye hue tray se wapas Ready mein le jaata hai. Slot phir se khali ho jaata hai.

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

Step 6 — Preemption: kya waker abhi turant run karta hai?

KYA. Consumer ab Ready hai. Maano uski higher priority hai Producer se. Ek preemptive scheduler ko immediately usi mein switch karna chahiye, xQueueSend call ke Producer ko return karne se pehle bhi.

WHY. Hum RTOS isliye run karte hain taaki bounded latency mile: jis second koi zyaada urgent task runnable ho jaaye, use run karna chahiye. Toh xQueueSend spot pe context switch trigger karta hai agar usne abhi higher-priority task ko unblock kiya ho.

PICTURE. Ek timeline. Producer ki xQueueSend line wahan hai jahan arrow control flip karta hai (coral → lavender): Consumer send call ke andar run karta hai, phir baad mein control Producer ko wapas jaata hai.

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

Step 7 — Mirror case: bhare hue queue pe Send karna

KYA. Roles palat do. Saare 5 slots occupied hain aur Producer xQueueSend(q, &v, xTicksToWait) call karta hai. Room nahi hai.

WHY ab yeh block karta hai. Wahi machine, doosri list: Producer ko senders-waiting list mein uske timeout ke saath move kar diya jaata hai. Jab baad mein ek receiver ek item leta hai aur ek slot free karta hai, toh kernel soye hue sender ki value wahan copy karta hai aur use jagaa deta hai — Steps 3–5 ke bilkul symmetrically.

PICTURE. Saare paanch slots coral (full). Producer arrow senders waiting tray mein jaata hai. Baad mein ek Receive slot 0 free karta hai aur Producer ko wapas Ready mein le aata hai.

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

Yeh Producer–Consumer Pattern apne complete form mein hai: dono ends so sakte hain, toh ek fast producer aur ek slow consumer (ya ulta) automatically ek doosre ko throttle karte hain bina kisi busy-waiting ke.


Step 8 — Degenerate & edge cases (koi gap mat chhodo)

KYA / WHY / PICTURE, chaar situations, har ek ek mini-panel ke roop mein draw ki gayi:

  • Timeout = 0 (xTicksToWait = 0): kernel task ko waiting list mein move hi nahi karta. Empty-on-receive → turant pdFALSE return karo. Yeh polite non-blocking poll hai.
  • Timeout expire ho jaata hai: ek blocked task jinke ticks khatam ho jaate hain use kernel ke tick handler dwara wapas Ready mein move kar diya jaata hai aur call pdFALSE return karti hai (kuch transfer nahi hua).
  • ISR se: ek ISR ki koi task identity nahi hoti, isliye woh block nahi kar sakta. xQueueSendFromISR use karo; agar queue full hai toh yeh sirf pdFALSE return karta hai — yeh kabhi so nahi sakta. Yeh report karta hai ki koi higher-priority task jaga ya nahi, taki tum portYIELD_FROM_ISR kar sako.
  • itemSize = 0: storage har item ke liye zero bytes carry karta hai — queue degenerate hokar ek pure counter ban jaati hai ki kitne "empty messages" present hain. Woh counter hi ek semaphore hai. Wahi code, koi data nahi. Yehi reason hai ki parent keh sakta tha "a semaphore is a degenerate queue."
Figure — FreeRTOS IPC — queues, semaphores, mutexes, event groups

Yahan left side mein zero-byte items ki count hai jo present hain; right side mein semaphore ka counter hai — woh literally ek hi integer hain.


Ek picture mein summary

Upar ki saari cheez ek task ka teen jagahon ke beech chalna hai — Ready, storage, aur ek waiting list — jisme kernel bytes copy karta hai aur decide karta hai kaun jaagta hai. Yeh single diagram Steps 1–8 compress karta hai: send ek slot fill karta hai aur ek soye hue receiver ko jagaata hai; ek full queue sender ko soota hai; highest-priority waiter hamesha jeetta hai; aur itemSize ko zero karne se poori cheez ek semaphore ban jaati hai.

Figure — FreeRTOS IPC — queues, semaphores, mutexes, event groups
Recall Feynman: poora walkthrough plain words mein batao

Ek teacher hai (CPU) aur paanch cubbies wali ek shelf hai (queue). Ek baccha jo note chahta hai lekin cubbies khali paata hai woh khada tap nahi karta — teacher use "note ke intezaar mein" corner mein so bhejta hai aur kisi aur ki help karta hai. Jab doosra baccha ek cubby mein note daalta hai, teacher turant use soye hue bacche ke haath mein copy karta hai, use jagaata hai, aur — agar woh baccha baaki sab se zyaada urgent hai — use abhi jaane deta hai, chahe drop-off beech mein hi kyun na ho. Agar saari cubbies bhari hain, toh daalne wala baccha "jagah ke intezaar mein" corner mein so jaata hai jab tak koi note na le le. Aur agar notes pe koi writing nahi hai bilkul, toh poori cheez sirf ek tally ban jaati hai ki shelf pe kitne blank notes hain — jo exactly ek semaphore hai. Ek choti si machine, do sleeping corners, aur ek rule ki sabse urgent baccha pehle jaagta hai: yahi ek FreeRTOS queue hai.

Recall Quick self-check

Khali queue pe receive CPU waste kyun nahi karta? ::: Task Ready list se nikal ke receivers-waiting list mein chala jaata hai, toh scheduler ise tab tak run nahi karta jab tak data na aaye — zero CPU use hota hai. Successful transfer mein bytes do baar copy kyun hote hain? ::: Sender → kernel slot (sender preemption se bachta hai), phir slot → receiver ka address; har copy message ko doosre task ki timing se independent banata hai. Ek queue ko semaphore mein badalne ke liye kya single change karna hota hai? ::: itemSize = 0 set karna, taki "item count" koi data ke bina pure counter ban jaaye. ISR mein xQueueSend ki jagah xQueueSendFromISR kyun use karna padta hai? ::: ISR mein, jiska koi task context nahi hota aur isliye woh kabhi block nahi kar sakta; FromISR variant turant return kar deta hai agar woh act nahi kar sakta.