📖 Scenario: You are working on a FreeRTOS-based embedded system where two tasks share a resource protected by a mutex. You want to understand how priority inheritance helps avoid priority inversion.
🎯 Goal: Build a simple FreeRTOS program with two tasks and a mutex. Observe how priority inheritance works when a low priority task holds the mutex and a high priority task tries to take it.
📋 What You'll Learn
Create two tasks: LowPriorityTask and HighPriorityTask
Create a mutex called xMutex
Use priority inheritance by taking and giving the mutex
Print messages showing task execution order and mutex status
💡 Why This Matters
🌍 Real World
Priority inheritance is important in embedded systems to avoid priority inversion, which can cause delays in critical tasks.
💼 Career
Understanding FreeRTOS mutexes and priority inheritance is essential for embedded software engineers working on real-time systems.
Progress0 / 4 steps
1
Create two tasks and a mutex
Create a mutex called xMutex using xSemaphoreCreateMutex(). Create two tasks named LowPriorityTask and HighPriorityTask with priorities 1 and 2 respectively. Use xTaskCreate() for both tasks.
FreeRTOS
Hint
Use xSemaphoreCreateMutex() to create the mutex. Use xTaskCreate() to create tasks with the specified names and priorities.
2
Add task code to take and give the mutex
In LowPriorityTask, take the mutex xMutex using xSemaphoreTake() with portMAX_DELAY, then simulate work by calling vTaskDelay(1000 / portTICK_PERIOD_MS). Then give the mutex back using xSemaphoreGive(). In HighPriorityTask, delay for 100 ticks first, then try to take the mutex with xSemaphoreTake() and portMAX_DELAY, then give it back immediately.
FreeRTOS
Hint
Use xSemaphoreTake() and xSemaphoreGive() to control the mutex. Use vTaskDelay() to simulate work and delay.
3
Add print statements to show task execution and mutex status
Add printf() statements in LowPriorityTask before taking the mutex, after taking it, and after giving it. Similarly, add printf() in HighPriorityTask before and after taking the mutex. Use messages exactly: "LowPriorityTask waiting for mutex\n", "LowPriorityTask got mutex\n", "LowPriorityTask released mutex\n", "HighPriorityTask waiting for mutex\n", "HighPriorityTask got mutex\n".
FreeRTOS
Hint
Use printf() to show when each task waits for, gets, and releases the mutex.
4
Run and observe the output
Run the program and observe the printed output. The output should show LowPriorityTask waiting for mutex, then LowPriorityTask got mutex, then HighPriorityTask waiting for mutex, then LowPriorityTask released mutex, and finally HighPriorityTask got mutex. Write a printf() statement after vTaskStartScheduler() in main() to print "Scheduler started\n".
FreeRTOS
Hint
Print "Scheduler started\n" before starting the scheduler to confirm the program started. Observe the order of printed messages to understand priority inheritance.
Practice
(1/5)
1. What is the main purpose of priority inheritance in FreeRTOS?
easy
A. To increase the priority of all tasks equally
B. To prevent low priority tasks from blocking high priority tasks for too long
C. To allow tasks to run in a random order
D. To disable task scheduling temporarily
Solution
Step 1: Understand priority inversion problem
Priority inversion happens when a low priority task holds a resource needed by a high priority task, causing delays.
Step 2: Role of priority inheritance
Priority inheritance temporarily raises the low priority task's priority to the high priority task's level to reduce blocking time.
Final Answer:
To prevent low priority tasks from blocking high priority tasks for too long -> Option B
Quick Check:
Priority inheritance prevents blocking = A [OK]
Hint: Priority inheritance helps high priority tasks run faster [OK]
Common Mistakes:
Thinking it raises all tasks' priorities
Confusing it with disabling scheduling
Believing it randomizes task order
2. Which FreeRTOS synchronization primitive automatically supports priority inheritance?
easy
A. Semaphore (binary)
B. Event group
C. Mutex
D. Queue
Solution
Step 1: Identify synchronization primitives
FreeRTOS offers semaphores, mutexes, queues, and event groups for task synchronization.
Step 2: Check which supports priority inheritance
Mutexes in FreeRTOS implement priority inheritance automatically to avoid priority inversion.
Choosing binary semaphore which lacks priority inheritance
Confusing queues or event groups with mutexes
Assuming all synchronization primitives support priority inheritance
3. Consider three tasks: High, Medium, and Low priority. Low holds a mutex needed by High. Medium is ready to run. What happens when priority inheritance is enabled?
medium
A. Medium task runs before Low and High
B. Low task is blocked until Medium finishes
C. High task runs immediately, ignoring mutex
D. Low task inherits High priority, runs before Medium
Solution
Step 1: Analyze priority inversion scenario
Low priority task holds mutex needed by High priority task, but Medium priority task is ready.
Step 2: Effect of priority inheritance
Low task temporarily inherits High priority, so it runs before Medium to release mutex faster.
Final Answer:
Low task inherits High priority, runs before Medium -> Option D
Quick Check:
Priority inheritance boosts Low task priority = B [OK]
Hint: Low task runs at High priority to unblock High task [OK]
Common Mistakes:
Assuming Medium runs before Low despite inheritance
Thinking High runs without mutex
Believing Low is blocked by Medium
4. You wrote code using a binary semaphore to protect a shared resource, but high priority tasks are blocked too long. What is the likely issue?
medium
A. Binary semaphore does not support priority inheritance
B. Mutex was not created properly
C. High priority tasks are not using the semaphore
D. Task priorities are all equal
Solution
Step 1: Identify synchronization primitive used
Binary semaphore is used to protect shared resource.
Step 2: Check priority inheritance support
Binary semaphores do not support priority inheritance, causing priority inversion issues.
Final Answer:
Binary semaphore does not support priority inheritance -> Option A
Quick Check:
Binary semaphore lacks priority inheritance = A [OK]
Hint: Use mutex, not binary semaphore, for priority inheritance [OK]
Blaming task priorities without checking synchronization
Ignoring mutex creation correctness
5. In a system with tasks A (priority 3), B (priority 2), and C (priority 1), task C holds a mutex needed by A. Task B is CPU intensive. How does FreeRTOS priority inheritance help avoid priority inversion here?
hard
A. Task C temporarily inherits priority 3, preempting B to release mutex faster
B. Task B inherits priority 3 to run before C and A
C. Task A runs without waiting for mutex
D. Task C is blocked until B finishes
Solution
Step 1: Understand task priorities and mutex ownership
Task C (low priority) holds mutex needed by Task A (high priority), while Task B (medium priority) is CPU intensive.
Step 2: Apply priority inheritance behavior
Task C inherits Task A's high priority (3) temporarily, allowing it to preempt Task B and release the mutex quickly.
Final Answer:
Task C temporarily inherits priority 3, preempting B to release mutex faster -> Option A
Quick Check:
Priority inheritance boosts C to A's priority = C [OK]
Hint: Low priority task inherits high priority to beat medium task [OK]
Common Mistakes:
Thinking medium priority task inherits high priority
Assuming high priority task runs without mutex
Believing low priority task is blocked by medium task
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.