5.5.10 · D4 · HinglishEmbedded Systems & Real-Time Software

ExercisesFreeRTOS — task creation, priorities, xTaskCreate

3,568 words16 min read↑ Read in English

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

Shuru karne se pehle, teen words jinpe hum baar baar rely karenge:

Ab ek picture us model ki jo har timing question is page par rely karta hai:

Figure — FreeRTOS — task creation, priorities, xTaskCreate

Level 1 — Recognition

Yahaan hum sirf rules identify karte hain. Abhi timelines ki computation nahi.

Exercise 1.1 (L1)

Do tasks create kiye gaye hain:

xTaskCreate(vA, "A", 128, NULL, 2, NULL);
xTaskCreate(vB, "B", 128, NULL, 5, NULL);

Dono READY hain. Kaun run karega, aur kyun?

Recall Solution 1.1

B run karega. Scheduler preemptive aur priority-based hai: numerically largest READY priority ko hamesha CPU milta hai. Kyunki , task B jeet jaata hai. (Trap: "priority 2 zyada important lagti hai" — aisa nahi hai. Bada number = FreeRTOS mein zyada urgent.)

Exercise 1.2 (L1)

Tum Cortex-M par usStackDepth = 200 pass karte ho. Task stack ke kitne bytes reserve karega?

Recall Solution 1.2

200 register-sized boxes stacked up imagine karo; har box 4 bytes wide hai Cortex-M par, toh boxes ki count ko ek box ki width se multiply karo: "×4" mein koi mystery nahi — ye bas "ek word mein kitne bytes fit hote hain" hai, usi tarah jaise "×12" feet ko inches mein convert karta hai.

Exercise 1.3 (L1)

Char task states ke naam batao aur kaho kaun zero CPU use karta hai wait karte waqt.

Recall Solution 1.3

Running, Ready, Blocked, Suspended. Blocked state zero CPU use karta hai — task parked rehta hai kisi event ka wait karte hue (delay expire hona, queue item, semaphore).


Level 2 — Application

Ab hum rules mein numbers plug karte hain.

Exercise 2.1 (L2)

configTICK_RATE_HZ = 1000. vTaskDelay(pdMS_TO_TICKS(250)) ticks mein kya translate hota hai?

Recall Solution 2.1

Ruler analogy socho: ek tick time-ruler par ek notch hai, aur yahaan har notch 1 ms worth hai (kyunki 1000 notches 1000 ms mein fit hote hain). 250 ms measure karne ke liye bas count karo ki usme kitne notches fit hote hain: Toh task 250 ticks ke liye block hota hai. (Kyunki 250 whole number hai, pdMS_TO_TICKS ke paas yahaan truncate karne ke liye koi fraction nahi — Tick definition ke rounding edge case se contrast karo.)

Exercise 2.2 (L2)

Ek task ko 1.5 KB stack chahiye. sizeof(StackType_t) = 4. Tumhe kaun sa usStackDepth (words mein) pass karna chahiye? (1 KB = 1024 bytes use karo.)

Recall Solution 2.2

Ye Exercise 1.2 ka reverse hai: wahaan humne boxes ko bytes mein turn kiya (×4); yahaan hamare paas byte budget hai aur humein find karna hai ki kitne 4-byte boxes fit hote hain, isliye hum divide karte hain 4 se. usStackDepth = 384 pass karo.

Exercise 2.3 (L2)

Tumhare heap mein 5000 bytes free hain. Har task ko stack 256 words plus 100 bytes ka TCB chahiye. Kitne aisi tasks xTaskCreate fit kar sakta hai errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY return karne se pehle?

Recall Solution 2.3

Ek task ki cost = stack bytes + TCB bytes (yaad raho: xTaskCreate dono stack aur TCB allocate karta hai): Ab, floor kyun? Imagine karo 1124-byte bricks ek 5000-byte shelf mein lay karna. Char bricks bytes use karte hain aur 504 bytes free chodh dete hain — lekin ek task all-or-nothing hai: tum "half a stack + half a TCB" allocate karke ek working task nahi pa sakte, isliye 504 leftover bytes 5th task ke liye useless hain. Yahi floor (round-down) capture karta hai — sirf whole bricks count karo jo fit hote hain: 4 tasks fit hote hain; 5tha xTaskCreate fail hota hai kyunki — heap 5th stack + TCB fit nahi kar sakta, isliye wo errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY return karta hai. Dekho Heap memory management (heap_1..heap_5) in FreeRTOS ki heap actually ye kaise carve karta hai.


Level 3 — Analysis

Ab hum timelines aur who preempts whom ke baare mein reason karte hain.

Exercise 3.1 (L3)

void vHigh(void *p){ for(;;){ work_2ms(); vTaskDelay(pdMS_TO_TICKS(10)); } }
void vLow (void *p){ for(;;){ crunch(); } }   // never blocks
xTaskCreate(vLow,  "low",  256, NULL, 1, NULL);
xTaskCreate(vHigh, "high", 256, NULL, 3, NULL);

work_2ms() 2 ms leta hai. 30 ms window mein (assume karo dono par start karte hain, vHigh pehle run karta hai), vLow actually CPU par kitne milliseconds pata hai?

Recall Solution 3.1

Pehle, vHigh ka true loop period. Uske for(;;) ka ek trip do cheezein back-to-back karta hai: 2 ms ka work_2ms(), phir ek vTaskDelay(10 ms) jo use sleep put kar deta hai. vTaskDelay(N) N ticks ke liye sota hai jis moment delay call reach hoti hai us moment se measure karke — yaani work ke baad. Toh loop period hai: vHigh isliye ms par READY hota hai — ek 12 ms rhythm, 10 ms nahi. (vTaskDelayUntil iske bajaay work length ki parwah kiye bina 10 ms period fix karta — dekho FreeRTOS — vTaskDelay vs vTaskDelayUntil.)

Ab 30 ms window ke andar bursts count karo. vHigh har wake par ek 2 ms burst run karta hai:

  • burst 1: ms
  • burst 2: ms
  • burst 3: ms
  • agla wake ms hoga — 30 ms window ke bahar.

Toh exactly 3 bursts mein land karte hain, total ms high-priority CPU. Kyunki , har burst vLow ko instantly preempt karta hai, aur vLow (jo kabhi block nahi hota) simply har remaining instant soak up karta hai: vLow ko 24 ms milta hai. Key subtlety: 12 ms period aur 30 ms window coincidentally 3 bursts dete hain, lekin tumhe pehle period 2+10 derive karna hoga — "har 10 ms" assume karna wakes ko galat 0,10,20,30 par place kar deta aur blocks galat hote. Ye preemptive scheduling action mein hai.

Figure — FreeRTOS — task creation, priorities, xTaskCreate

Exercise 3.2 (L3)

Same code, lekin ab vHigh bhi priority 1 hai (vLow ke equal), aur configUSE_TIME_SLICING = 1. Kya vHigh abhi bhi har 10 ms reliably apna sensor read karta hai? Kyun ya kyun nahi?

Recall Solution 3.2

Nahi — reliably nahi. Equal priority ke saath, jab vHigh ka delay expire hota hai toh wo READY hota hai lekin vLow ko preempt nahi karta; ye bas ek tick at a time round-robin karte hain. Lekin vLow kabhi block nahi hota, toh wo apni turns leta rehta hai. vHigh phir bhi eventually run karta hai (ye forever starve nahi hota, kyunki equal-priority tasks share karte hain), phir bhi uska exact wake-to-run latency ab depend karta hai ki vLow round-robin mein kahan hai — timing jittery ho jaati hai, deterministic nahi. 10 ms sensing guarantee karne ke liye, vHigh strictly higher priority par hona chahiye. Period tighten karne ke liye dekho FreeRTOS — vTaskDelay vs vTaskDelayUntil.

Exercise 3.3 (L3)

Priority 3 wala ek task ek mutex hold karta hai. Priority 5 wala task phir usi mutex ko lene ki koshish karta hai aur block ho jaata hai. Priority-4 task READY hai. Bina kisi special mechanism ke, kya unwanted cheez ho sakti hai, aur kaun sa feature fix karta hai?

Recall Solution 3.3

Priority-4 task run kar sakta hai aur priority-3 mutex holder ko delay kar sakta hai, jo badle mein higher priority-5 waiter ko delay karta hai — ek lower-priority task effectively ek higher wale se aage nikal jaata hai. Ye priority inversion hai. Fix hai priority inheritance: mutex temporarily holder (3) ko waiter ki priority (5) tak boost karta hai taaki wo jaldi finish aur release kare. Full treatment Priority Inversion and Priority Inheritance aur FreeRTOS — Semaphores and Mutexes mein.


Level 4 — Synthesis

Ab hum ideas design aur combine karte hain across features.

Exercise 4.1 (L4)

Tumhe run karna hai: (a) ek safety-critical motor watchdog har 5 ms mein, (b) ek UART logger, (c) ek background statistics computation. Har ek ke liye priorities assign karo aur blocking strategy describe karo. Justify karo.

Recall Solution 4.1

Ek sound design:

Task Priority Blocking strategy
Motor watchdog 3 (highest) vTaskDelayUntil(5 ms) — fixed period, sab kuch preempt karna zaruri
UART logger 2 Log messages ki [[FreeRTOS — Queues and inter-task communication
Statistics 1 Busy-compute kar sakta hai; lowest taaki doosron ko kabhi delay na kare

Kyun: watchdog time-critical hai, isliye ye top par baithta hai aur precisely har 5 ms mein block karta hai (drift avoid karne ke liye vTaskDelay nahi, vTaskDelayUntil use karo). Logger event-driven hai — queue par block karne ka matlab hai wo zero CPU use karta hai jab tak koi message appear na ho. Statistics "jo bhi time bacha hai" wala hai, isliye ye lowest hai aur use kabhi block nahi karne diya jaata kyunki iske neeche kuch bhi starve nahi ho sakta. Priority 0 par idle task tab bhi run karta hai jab statistics ke paas bhi kuch karne ko nahi, hardware watchdog ko feed karta / low power enter karta hai.

Exercise 4.2 (L4)

Ek interrupt tab fire hota hai jab button press hota hai. Tum chahte ho ek task slow debounce + action handle kare. Correct architecture sketch karo. ISR ke andar xTaskCreate kyun nahi call kar sakte?

Recall Solution 4.2

Correct architecture (deferred handling):

  1. Scheduler start hone se pehle main() mein handler task pre-create karo.
  2. Task ek semaphore (ya task notification) par wait karte hue block karta hai.
  3. ISR almost kuch nahi karta: wo xSemaphoreGiveFromISR(...) call karta hai task ko signal karne ke liye, phir return karta hai.
  4. Scheduler handler task ko unblock karta hai, jo slow work task level par karta hai.

ISR mein xTaskCreate kyun nahi: zyaadatar creation/allocation paths ISR-safe nahi hote — ye heap aur kernel lists touch kar sakte hain interrupts enabled assume karke, corruption ka risk hota hai. ISRs short hone chahiye aur sirf ...FromISR APIs use karni chahiye. Dekho ISR-safe APIs (FromISR) and deferred interrupt handling.


Level 5 — Mastery

Deep, multi-constraint reasoning.

Exercise 5.1 (L5)

Heap free = 8 KB (8192 bytes), sizeof(StackType_t) = 4, TCB = 100 bytes each. Tumhe chahiye:

  • 1 control task: stack 512 words
  • 2 sensor tasks: stack 256 words each
  • 1 logger: stack 384 words

Kya sab fit hota hai? Agar haan, toh kitna heap bacha? Agar nahi, toh kaun sa task fail karta hai? (Assume karo tasks listed order mein create hote hain.)

Recall Solution 5.1

Har task ki cost = stack_words × 4 + 100 (stack + uska TCB).

  • Control:
  • Sensor (each):
  • Logger:

8192 ke against running total: Sab fit ho jaata hai. Bacha hua heap: (Real heaps mein per-allocation alignment/overhead bhi hota hai — dekho Heap memory management (heap_1..heap_5) in FreeRTOS — lekin is model par, 2160 bytes remain.)

Exercise 5.2 (L5)

Teen tasks, sab priority 2, configUSE_TIME_SLICING = 1, configTICK_RATE_HZ = 1000. Har ek pure CPU work hai aur kabhi block nahi karta. Task X ko ek job finish karne ke liye total 15 ms CPU chahiye. Perfectly fair 1-tick round-robin assume karte hue, X ki job finish hone se pehle kitna wall-clock time pass hota hai?

Recall Solution 5.2

Teen equal tasks ek ek tick ki baari lete hain, toh CPU X ko har 3 mein se 1 tick deta hai. Timeline ko X, Y, Z, X, Y, Z, … colour karo: har 3 ms wall-clock ke liye, exactly 1 ms X ka hai. 15 ms of apna work bank karne ke liye X ko 15 aise turns chahiye, aur har turn 3 ms door hai: ≈ 45 ms wall-clock X ke 15 ms apna execution bank karne mein — baaki 30 ms do peers ko gaye. Ye equal-priority sharing ki cost hai; agar X higher priority hota toh ~15 ms mein finish karta.

Figure — FreeRTOS — task creation, priorities, xTaskCreate

Exercise 5.3 (L5)

State machine use karke exactly wo sequence of state transitions explain karo jo ek task karta hai ek iteration mein:

for(;;){ readSensor(); vTaskDelay(pdMS_TO_TICKS(10)); }

jab ek higher-priority task exist karta hai.

Recall Solution 5.3

Ek iteration, higher-priority task present hone ke saath:

  1. Task Running hai — readSensor() execute karta hai.
  2. vTaskDelay(10 ms) hit karta hai → Running → Blocked move karta hai (delay timer par parked, 0 CPU).
  3. Scheduler highest READY task pick karta hai (possibly higher-prio wala, ya idle).
  4. 10 ms baad delay expire hota hai → Blocked → Ready.
  5. Jab wo highest READY priority hota hai, scheduler use dispatch karta hai → Ready → Running, loop repeat hota hai.

Note karo ye kabhi Suspended nahi touch karta — wo sirf explicit vTaskSuspend se hota hai. TCB ka pairing step 2 par stack pointer store karta hai aur step 5 par restore karta hai, taaki readSensor() seamlessly resume ho. Ye constant Blocked→Ready→Running cycle hi reason hai ki ek well-written real-time task apni zyaadatar life Blocked mein bitata hai.


Recall Quick self-test (cloze)

Scheduler hamesha numerically largest READY priority run karta hai. usStackDepth words mein measure hota hai, isliye Cortex-M par bytes = words × 4. Delay par wait karta ek task Blocked state mein hota hai aur zero CPU use karta hai. Equal-priority tasks round-robin time-slicing se share karte hain.