What if your program could never miss an important event, no matter how busy it is?
Why Queue from ISR (xQueueSendFromISR) in FreeRTOS? - Purpose & Use Cases
Imagine you have a device that needs to respond quickly to events like button presses or sensor signals. You try to handle these events by checking them one by one in your main program loop.
This means your program might miss some events or react too slowly because it's busy doing other tasks.
Checking events manually in the main loop is slow and unreliable. If the program is busy, it can miss events or respond late.
Also, trying to update shared data directly from the event handler can cause errors or crashes because the main program might be using that data at the same time.
Using a queue from an Interrupt Service Routine (ISR) with xQueueSendFromISR lets you quickly and safely send event data to the main program.
This way, the ISR just puts the event in a queue and returns fast, while the main program processes events one by one without missing any.
void ISR_Handler() {
sharedData = eventData; // direct update
}
void mainLoop() {
if (sharedData) {
process(sharedData);
sharedData = 0;
}
}void ISR_Handler() {
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(queueHandle, &eventData, &xHigherPriorityTaskWoken);
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
void mainLoop() {
if (xQueueReceive(queueHandle, &receivedData, 0)) {
process(receivedData);
}
}This lets your program handle events quickly and safely, without missing any or causing crashes.
Think of a smart home sensor that detects motion. The sensor's ISR quickly sends motion events to a queue, and the main program reads these events to turn on lights or send alerts without delay or error.
Manual event handling can miss events or cause errors.
xQueueSendFromISR safely sends data from ISR to main program.
This improves responsiveness and program stability.
Practice
What is the primary purpose of xQueueSendFromISR() in FreeRTOS?
Solution
Step 1: Understand the function context
xQueueSendFromISR()is designed to be called inside an ISR, where normal queue functions that can block are unsafe.Step 2: Identify the function's role
It safely sends data to a queue without blocking, allowing communication from ISR to tasks.Final Answer:
To send data to a queue safely from an interrupt service routine (ISR) -> Option AQuick Check:
Purpose of xQueueSendFromISR = safe queue send from ISR [OK]
- Confusing it with queue creation or deletion
- Thinking it blocks the ISR
- Using normal queue send functions inside ISR
Which of the following is the correct way to call xQueueSendFromISR()?
BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void * pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken);Solution
Step 1: Check parameter types
The function expects a queue handle, a pointer to the data, and a pointer to a BaseType_t variable for task wake flag.Step 2: Match correct call
xQueueSendFromISR(queue, &data, NULL); passes the queue handle, address of data, and NULL for the last parameter, which is valid if you don't care about task wake.Final Answer:
xQueueSendFromISR(queue, &data, NULL); -> Option BQuick Check:
Correct parameters and pointers used = xQueueSendFromISR(queue, &data, NULL); [OK]
- Passing data instead of its address
- Passing queue address instead of handle
- Omitting the third parameter
Given the following code snippet inside an ISR, what will be the value of result after execution?
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
int data = 10;
BaseType_t result = xQueueSendFromISR(myQueue, &data, &xHigherPriorityTaskWoken);Assume myQueue has space available.
Solution
Step 1: Understand return values of xQueueSendFromISR
The function returns pdPASS (1) if the item was successfully sent to the queue, pdFAIL (0) otherwise.Step 2: Analyze queue state
SincemyQueuehas space, the send will succeed, so result will be pdPASS (1).Final Answer:
pdPASS (1) -> Option DQuick Check:
Queue has space, send success = pdPASS (1) [OK]
- Confusing pdPASS with pdTRUE
- Assuming it returns pdFALSE on success
- Ignoring queue capacity
Identify the error in this ISR code snippet using xQueueSendFromISR():
void ISR_Handler(void) {
int value = 5;
BaseType_t xHigherPriorityTaskWoken;
xQueueSendFromISR(myQueue, &value, &xHigherPriorityTaskWoken);
if(xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR();
}
}Solution
Step 1: Check variable initialization
xHigherPriorityTaskWokenmust be initialized to pdFALSE before callingxQueueSendFromISR()to avoid unpredictable behavior.Step 2: Verify other parts
CallingportYIELD_FROM_ISR()conditionally is correct;valueis passed by address; callingxQueueSendFromISR()inside ISR is valid.Final Answer:
xHigherPriorityTaskWokenis not initialized before use -> Option CQuick Check:
Initialize xHigherPriorityTaskWoken = pdFALSE before use [OK]
- Not initializing xHigherPriorityTaskWoken
- Misusing portYIELD_FROM_ISR
- Passing data incorrectly
You want to send multiple sensor readings from an ISR to a task using xQueueSendFromISR(). Which approach correctly ensures the task runs immediately if it has higher priority?
void SensorISR(void) {
static int sensorData = 0;
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
sensorData++;
xQueueSendFromISR(sensorQueue, &sensorData, &xHigherPriorityTaskWoken);
// What should be done here?
}Solution
Step 1: Understand task wake mechanism
After sending data from ISR, if a higher priority task was woken, you must request a context switch immediately.Step 2: Use correct yield function
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);triggers a context switch only if needed, which is the correct approach.Final Answer:
Call portYIELD_FROM_ISR(xHigherPriorityTaskWoken); after sending -> Option AQuick Check:
Use portYIELD_FROM_ISR with xHigherPriorityTaskWoken to yield [OK]
- Calling blocking functions like vTaskDelay in ISR
- Calling taskYIELD unconditionally inside ISR
- Ignoring portYIELD_FROM_ISR call
Ready to prove it?
Pass the test and this pattern moves unknown
