5.5.10 · D5 · HinglishEmbedded Systems & Real-Time Software

Question bankFreeRTOS — task creation, priorities, xTaskCreate

2,770 words13 min read↑ Read in English

5.5.10 · D5 · Coding › Embedded Systems & Real-Time Software › FreeRTOS — task creation, priorities, xTaskCreate


Pehle picture anchor karo — chaar task states

Traps se pehle, mental model pakka karo. Ek task hamesha exactly ek state mein hota hai, aur is page ke har trap ka matlab actually yahi hai ki task kis state mein hai aur kyun.

Agla figure dikhata hai ki vTaskDelete(NULL) ka memory kab actually reclaim hota hai — ye call karte hi free nahi hota.


Local glossary — is page par use hone wale har symbol ka matlab

Kyunki parent note ne in sab ko assume kiya tha, yahan plain words mein diya gaya hai, taaki neech kuch bhi unexplained na rahe.


Create karne ke do tarike — dynamic vs static

Parent note ne sirf xTaskCreate dikhaya tha, jo stack aur TCB heap se carve karta hai. Ek doosra darwaza bhi hai.


True or false — justify karo

Blocked state mein ek task phir bhi har tick CPU ka ek slice consume karta hai.
False. Blocked ka matlab hai ki use ready list se hata diya gaya hai jab tak uska event (delay, queue, semaphore) fire na ho — yeh zero CPU use karta hai, aur yahi poora reason hai ki blocking exist karta hai.
Kisi task ki priority configMAX_PRIORITIES set karna use sabse zyada urgent banata hai.
False. Valid priorities 0 .. configMAX_PRIORITIES - 1 hain, isliye sabse upar configMAX_PRIORITIES - 1 hai. Max value khud pass karna ek off-by-one bug hai jo silently clamp ho sakta hai.
Equal priority ke do tasks hamesha strict alternation mein run karenge.
Sirf kabhi-kabhi sach hai — aur sirf tab jab configUSE_TIME_SLICING = 1 ho. Tab woh ek-ek tick round-robin karte hain, lekin jo task pehle block karta hai woh apna bacha hua slice doosre ko de deta hai, isliye yeh clockwork alternation nahi hai.
configUSE_TIME_SLICING = 0 ke saath bhi, do equal-priority CPU-bound tasks har tick baari-baari lete hain.
False. Slicing off hone par, running task tab tak CPU rakhta hai jab tak woh block na ho ya explicitly yield na kare (taskYIELD). Same priority par ek peer tab indefinitely starve ho sakta hai — yeh complementary edge case hai jo log bhool jaate hain.
usStackDepth = 256 stack ke 256 bytes reserve karta hai.
False. Stack depth words mein hai, isliye 32-bit Cortex-M par yeh bytes hai. Ise bytes ki tarah padhna stack ko word size ke factor se under-provision karta hai.
Agar xTaskCreate pdPASS return kare, toh task kam se kam ek baar run ho chuka hai.
False. Creation aur pehla execution deliberately alag steps hain: pdPASS ka sirf itna matlab hai ki TCB aur stack allocate ho gaye aur task Ready list par rakh diya gaya. Kernel allocation ko pehle context switch se alag karta hai kyunki running context (ya abhi shuru na hua scheduler) zyada priority ka ho sakta hai, isliye naye task ko wait karna padta hai — allocation success scheduling ke baare mein kuch nahi kehta.
Idle task hamesha tskIDLE_PRIORITY = 0 par run karta hai aur kabhi starve nahi ho sakta.
Doosre hisse par False. Idle task hai priority 0, lekin ek non-blocking higher-priority task use starve karta hai — power-saving hooks, watchdog feeds, aur deleted tasks ki cleanup todta hai.
vTaskStartScheduler() call karna return karta hai jab saare tasks khatam ho jaate hain.
False. Tasks infinite loops hote hain jo kabhi khatam nahi hote, isliye vTaskStartScheduler() normally kabhi return nahi karta; yeh sirf tab return karta hai jab idle/timer task banane ke liye enough heap na ho.
Ek higher-priority task hamesha lower-priority task ko us instant preempt karega jab woh Ready ho jaata hai.
Default preemptive scheduler ke under True hai — lekin sirf tab jab preemption enabled ho (configUSE_PREEMPTION = 1) aur CPU kisi critical section ke andar na ho (interrupts masked). taskENTER_CRITICAL()/taskEXIT_CRITICAL() ke andar switch defer hota hai jab tak critical section khatam na ho, priority difference hone ke bawajood.

Error dhundo

void vTask(void *p){ doWork(); }   // kya toot jaata hai?

::: Task function doWork() ke baad return kar jaata hai. Return karne wala task end ke baad undefined code mein ja girta hai aur scheduler corrupt karta hai. Body ko for(;;) mein wrap karo ya vTaskDelete(NULL) se end karo.

xTaskCreate(vHigh, "hi", 128, NULL, 1, NULL);
xTaskCreate(vLow,  "lo", 128, NULL, 3, NULL);  // vLow heavy math karta hai, kabhi block nahi karta

::: Names jhooth bol rahe hain: vLow ko priority 3 di gayi hai, jo vHigh ki 1 se zyada hai. Kyunki bada = zyada urgent aur vLow kabhi block nahi karta, yeh vHigh ko completely starve karta hai. Intended urgency ulti hai.

void vCritical(void *p){ for(;;){ readSensor(); } }  // top priority, responsive hona zaroori

::: Koi blocking call nahi hai, isliye yeh top-priority loop kabhi yield nahi karta — har lower task, idle sahit, starve ho jaata hai. Responsiveness agli event tak block karne se aati hai, spinning se nahi. vTaskDelay add karo ya queue/semaphore par block karo.

void isr_handler(void){ xTaskCreate(vLog, "log", 128, NULL, 2, NULL); }

::: xTaskCreate ISR-safe nahi hai aur interrupt se call nahi karna chahiye. Task ko startup par pre-create karo aur, ISR se, use signal karne ke liye ...FromISR API use karo — dekho ISR-safe APIs (FromISR) and deferred interrupt handling.

xTaskCreate(vBlink, "L", 128, NULL, 1, NULL);
vTaskDelete(h);   // h uninitialised hai — humne handle ke liye NULL pass kiya tha

::: Handle kabhi capture nahi kiya (pxCreatedTask = NULL), isliye h garbage hai. Baad mein kisi task ko delete ya suspend karne ke liye tumhe &h pass karna hoga aur real handle store karna hoga.

xTaskCreate(vTask, "T", 4096, NULL, 1, &h);  // "sirf 4 KB, heap mein bahut hai"

::: 4096 words mein hai, isliye Cortex-M par yeh per task reserve karta hai — assumed size se chaar guna. Ek chhote MCU par yeh errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY return kar sakta hai.

taskENTER_CRITICAL();
vTaskDelay(pdMS_TO_TICKS(10));   // "bas critical section ke andar ek chhota sa pause"
taskEXIT_CRITICAL();

::: vTaskDelay jaise blocking calls critical section ke andar illegal hain — tum CPU yield nahi kar sakte jab interrupts masked hon. Yeh deadlock ya assert karta hai. Timing critical region ke bahar karo.


Why questions

FreeRTOS stack size bytes ki jagah words mein kyun express karta hai?
Ek "word" CPU ki natural register width hai, aur har push/pop register-sized units move karta hai. Words mein count karna match karta hai ki stack actually kaise grow karta hai aur 8/16/32-bit cores ke across portable rehta hai.
"Bada number = zyada urgent" experienced programmers ke liye bhi ek trap kyun hai?
Kaafi systems (Linux nice, kaafi classic RTOSes) chhote numbers ko zyada important maante hain, isliye muscle memory meaning ko invert kar deti hai. FreeRTOS sirf numerically sabse bade ready priority ko run karta hai.
Ek real-time high-priority task ko apna zyaada time Blocked kyun bitaana chahiye?
Ek preemptive scheduler CPU ko sabse zyada Ready task ko deta hai; agar woh kabhi block na kare toh woh hamesha Ready rehta hai aur core monopolise karta hai, sab ko starve karta hai. Next event tak block karna hi baaki kaam ke liye jagah banata hai jabki response deterministic rehta hai.
TaskHandle_t output abhi na chahiye hone par bhi kyun store karein?
Handle hi ek maatra tarika hai baad mein us task ko suspend, resume, delete, ya priority change karne ka. Iske bina control APIs ka koi target hi nahi hoga.
pdMS_TO_TICKS(500) exist kyun karta hai, seedha tick count likhne ki jagah?
FreeRTOS time ko ticks mein measure karta hai jiska rate (configTICK_RATE_HZ) har project mein alag hota hai. Macro milliseconds ko ticks mein convert karta hai — — taaki code real time mein padha jaaye aur tick rate badalne par portable rahe.
Critical section preemption defer kyun karta hai jab configUSE_PREEMPTION = 1 bhi ho?
taskENTER_CRITICAL() interrupts mask karta hai (ek threshold tak), aur preemption tick interrupt aur doosre IRQs se drive hoti hai. Woh masked hone par, scheduler literally fire nahi kar sakta jab tak tum exit na karo — isliye critical sections ko jitna ho sake chhota rakhna chahiye.
Har task ka apna alag stack kyun chahiye, sharing kyun nahi?
Har task ko mid-function preempt kiya ja sakta hai, isliye uske local variables aur return addresses independently preserve hone chahiye. Ek shared stack ek task ke frames ko doosre ke frames se har context switch par overwrite karne deta — dekho Context Switching and the TCB.
Equal-priority tasks fairly CPU share kar sakte hain lekin unequal wale nahi kar sakte, kyun?
Scheduler sirf same, highest ready priority wale tasks ke beech time-slice karta hai (aur sirf tab jab configUSE_TIME_SLICING = 1 ho). Ek lower-priority task ko simply kabhi choose nahi kiya jaata jab koi higher-priority task Ready ho, isliye "fairness" sirf ek priority level ke andar exist karta hai.

Edge cases

Kya hoga agar saare tasks ek saath block ho jaayein (kuch bhi Ready na ho)?
Scheduler priority 0 par idle task run karta hai, jo low-power sleep mein ja sakta hai aur watchdog feed karta hai jab tak koi event kisi real task ko unblock na kare.
configUSE_TICKLESS_IDLE = 1 idle task aur low-power sleep ke behavior ko kaise badalta hai?
Har periodic tick par jaagne ki jagah, kernel tick timer band kar deta hai jab woh ek lamba idle predict karta hai, deeply sleep karta hai, aur jaagne par elapsed time ke liye tick count correct karta hai. Isliye idle ab fixed cadence par nahi chalta — woh run karta hai, ek computed span ke liye sota hai, aur tick "jump" karta hai. Battery life ke liye bahut achha, lekin timing sources ko sleep survive karna chahiye.
Agar tum vTaskStartScheduler() call karne se pehle task create karo toh?
Yeh normal pattern hai — task Ready ban jaata hai lekin tab tak run nahi karta jab tak scheduler start na ho. main() mein create kiye gaye saare setup tasks sirf vTaskStartScheduler() ke baad execute hona shuru karte hain.
Agar do tasks alag priorities par exact ek hi tick mein Ready ho jaayein toh kya hoga?
Koi contest nahi — scheduler hamesha higher-priority wale ko Run karne ke liye choose karta hai; lower-priority wala Ready rehta hai. "Same tick" sirf tab sharing cause karta hai jab priorities equal hon.
Agar usStackDepth task ke actual usage ke liye bahut chhota set ho toh kya hoga?
Task apna stack overflow kar deta hai, silently adjacent memory corrupt karta hai (aksar TCB ya doosra task). Mystery crash ki jagah hook ke zariye pakadne ke liye configCHECK_FOR_STACK_OVERFLOW enable karo.
vTaskDelete(NULL) kya karta hai, aur uski memory actually kab free hoti hai?
Ek task khud ko delete karne ke liye NULL pass karta hai. Uska TCB/stack immediately free nahi hota — ek running task apna stack free nahi kar sakta — isliye kernel sirf use mark karta hai aur idle task apni next baari par woh memory reclaim karta hai (timeline figure dekho). Ek aur wajah ki idle starve nahi hona chahiye.
Kya ek task runtime par apni priority khud change kar sakta hai, aur kya risk hai?
Haan, vTaskPrioritySet ke zariye. Risk yeh hai ki khud ko raise karke doosron ko starve karo, ya agar yeh shared resources ke saath interact kare toh priority-inversion scenarios create ho — dekho Priority Inversion and Priority Inheritance.
Agar configSUPPORT_DYNAMIC_ALLOCATION = 0 ke saath build kiya ho toh kya toot jaayega?
Plain xTaskCreate compile/link nahi hoga — carve karne ke liye koi heap nahi hai. Tumhe xTaskCreateStatic use karna hoga apne stack aur TCB storage ke saath (configSUPPORT_STATIC_ALLOCATION = 1 chahiye).

Recall Ek-line self-test

Bada number = zyada urgent, stack words mein hai, tasks kabhi return nahi karte, high-priority tasks block karni chahiye, aur xTaskCreate ISR-safe nahi hai. Agar tum paanch ko justify kar sako, toh yeh topic tumhara hai.