📖 Scenario: You are working on a simple embedded system using FreeRTOS. The system needs to handle a button press interrupt. Instead of doing all the work inside the interrupt (which should be quick), you will use the deferred interrupt processing pattern. This means the interrupt will only notify a task to do the actual work later.
🎯 Goal: Build a FreeRTOS program that uses a button press interrupt to notify a task. The task will then process the button press event outside the interrupt.
📋 What You'll Learn
Create a binary semaphore to signal the button press
Write an interrupt handler that gives the semaphore
Create a task that waits for the semaphore and processes the button press
Print a message when the button press is processed
💡 Why This Matters
🌍 Real World
Embedded systems often need to respond quickly to hardware events like button presses or sensor signals. Doing heavy work inside interrupts can cause delays. Deferred interrupt processing moves the work to tasks, improving system responsiveness.
💼 Career
Understanding deferred interrupt processing is important for embedded software engineers working with real-time operating systems like FreeRTOS. It helps write efficient, responsive, and maintainable firmware.
Progress0 / 4 steps
1
Create a binary semaphore called xButtonSemaphore
Write code to create a binary semaphore called xButtonSemaphore using xSemaphoreCreateBinary(). This semaphore will be used to signal the button press event.
FreeRTOS
Hint
Use xSemaphoreCreateBinary() to create the semaphore and assign it to xButtonSemaphore.
2
Write an interrupt handler called vButtonISR that gives xButtonSemaphore
Write an interrupt handler function called vButtonISR that uses xSemaphoreGiveFromISR(xButtonSemaphore, &xHigherPriorityTaskWoken) to give the semaphore. Declare BaseType_t xHigherPriorityTaskWoken = pdFALSE; before giving the semaphore and call portYIELD_FROM_ISR(xHigherPriorityTaskWoken); after giving it.
FreeRTOS
Hint
Remember to declare xHigherPriorityTaskWoken as pdFALSE before giving the semaphore and call portYIELD_FROM_ISR() after.
3
Create a task called vButtonTask that waits for xButtonSemaphore
Write a task function called vButtonTask that runs an infinite loop. Inside the loop, use xSemaphoreTake(xButtonSemaphore, portMAX_DELAY) to wait for the semaphore. When the semaphore is taken, print the message "Button pressed! Processing event...".
FreeRTOS
Hint
Use an infinite loop and xSemaphoreTake with portMAX_DELAY to wait forever for the semaphore.
4
Print the message when the button press is processed
Add a printf statement inside vButtonTask to print "Button pressed! Processing event..." when the semaphore is taken. Then, write a main function that calls setup(), creates the vButtonTask with priority 1, and starts the scheduler with vTaskStartScheduler().
FreeRTOS
Hint
Use xTaskCreate to create the task and vTaskStartScheduler() to start FreeRTOS. The message will print when the semaphore is given.
Practice
(1/5)
1. What is the main purpose of the deferred interrupt processing pattern in FreeRTOS?
easy
A. To move heavy processing from the ISR to a task for better system responsiveness
B. To execute all interrupt code inside the ISR for faster response
C. To disable all interrupts during task execution
D. To avoid using semaphores or queues in interrupt handling
Solution
Step 1: Understand ISR limitations
Interrupt Service Routines (ISRs) should be short to keep system responsive.
Step 2: Role of deferred processing
Heavy or time-consuming work is moved to a task, triggered by ISR using semaphores or queues.
Final Answer:
To move heavy processing from the ISR to a task for better system responsiveness -> Option A
Quick Check:
Deferred processing = move work out of ISR [OK]
Hint: Heavy work belongs in tasks, not ISRs [OK]
Common Mistakes:
Thinking all work should be done inside ISR
Believing interrupts should be disabled during tasks
Ignoring use of semaphores or queues
2. Which of the following is the correct way to notify a task from an ISR in FreeRTOS?
easy
A. vTaskDelay()
B. xSemaphoreGive()
C. xSemaphoreGiveFromISR()
D. xQueueSend()
Solution
Step 1: Identify ISR-safe functions
Functions called from ISRs must be ISR-safe variants, like xSemaphoreGiveFromISR().
Step 2: Compare options
xSemaphoreGive() is for tasks, not ISRs; vTaskDelay() is a task delay; xQueueSend() is not ISR-safe.
Final Answer:
xSemaphoreGiveFromISR() -> Option C
Quick Check:
Use FromISR functions inside ISRs [OK]
Hint: Use FromISR suffix functions inside ISRs [OK]
Common Mistakes:
Using task-only functions inside ISR
Calling blocking functions in ISR
Not using FromISR variants
3. Consider this snippet inside an ISR in FreeRTOS:
A. xSemaphoreGive() is not safe to call from an ISR
B. The semaphore is given twice accidentally
C. The ISR does not clear the interrupt flag
D. The task will never unblock
Solution
Step 1: Check function usage in ISR
xSemaphoreGive() is a task-level function and is not safe to call inside an ISR.
Step 2: Correct function to use
Inside ISR, xSemaphoreGiveFromISR() must be used to safely notify the task.
Final Answer:
xSemaphoreGive() is not safe to call from an ISR -> Option A
Quick Check:
Use FromISR functions in ISRs [OK]
Hint: Never call task functions inside ISR, use FromISR versions [OK]
Common Mistakes:
Calling task functions inside ISR
Forgetting to clear interrupt flags
Assuming semaphore gives always unblock tasks
5. You want to implement deferred interrupt processing where an ISR signals a task to process sensor data. Which sequence correctly follows FreeRTOS best practices?
hard
A. Task polls sensor data continuously, ISR disables interrupts
B. ISR processes sensor data directly, then calls vTaskDelay()
C. ISR sends data via xQueueSend(), task never blocks
D. ISR calls xSemaphoreGiveFromISR(), then task waits on semaphore and processes data
Solution
Step 1: ISR role in deferred processing
ISR should be short and only notify the task using xSemaphoreGiveFromISR().
Step 2: Task role in processing
The task waits on the semaphore and processes sensor data when notified.
Final Answer:
ISR calls xSemaphoreGiveFromISR(), then task waits on semaphore and processes data -> Option D
Quick Check:
ISR signals, task processes data [OK]
Hint: ISR signals; task does heavy work [OK]
Common Mistakes:
Doing heavy work inside ISR
Using blocking calls inside ISR
Not synchronizing task and ISR properly
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.