We use xQueueSendFromISR to safely send data to a queue from an interrupt. This helps communication between interrupts and tasks without causing problems.
Queue from ISR (xQueueSendFromISR) in FreeRTOS
BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void * pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken);
// Example:
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xQueueSendFromISR(myQueue, &myData, &xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken) {
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}xQueue is the handle to the queue created earlier.
pvItemToQueue is a pointer to the data you want to send.
pxHigherPriorityTaskWoken is used to check if a context switch is needed after ISR.
// Sending data from ISR when queue is empty BaseType_t xHigherPriorityTaskWoken = pdFALSE; int sensorValue = 100; xQueueSendFromISR(myQueue, &sensorValue, &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(xHigherPriorityTaskWoken); }
// Sending data from ISR when queue is full BaseType_t xHigherPriorityTaskWoken = pdFALSE; int newValue = 200; BaseType_t result = xQueueSendFromISR(myQueue, &newValue, &xHigherPriorityTaskWoken); if (result == errQUEUE_FULL) { // Handle full queue (e.g., discard or overwrite) } if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(xHigherPriorityTaskWoken); }
// Sending data from ISR with only one element in queue BaseType_t xHigherPriorityTaskWoken = pdFALSE; int data = 50; xQueueSendFromISR(myQueue, &data, &xHigherPriorityTaskWoken); if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(xHigherPriorityTaskWoken); }
This program creates a queue and a task that waits for data. The ISR sends data to the queue using xQueueSendFromISR. The task prints the received data.
#include "FreeRTOS.h" #include "task.h" #include "queue.h" #include <stdio.h> QueueHandle_t myQueue; void vTaskReceiver(void *pvParameters) { int receivedValue; while (1) { if (xQueueReceive(myQueue, &receivedValue, portMAX_DELAY) == pdPASS) { printf("Task received: %d\n", receivedValue); } } } void vISR_Handler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; int dataToSend = 42; BaseType_t result = xQueueSendFromISR(myQueue, &dataToSend, &xHigherPriorityTaskWoken); if (result == errQUEUE_FULL) { // Queue full, data lost printf("Queue full in ISR!\n"); } if (xHigherPriorityTaskWoken) { portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } } int main(void) { myQueue = xQueueCreate(2, sizeof(int)); if (myQueue == NULL) { printf("Failed to create queue\n"); return 1; } xTaskCreate(vTaskReceiver, "Receiver", configMINIMAL_STACK_SIZE, NULL, 1, NULL); // Simulate ISR call (normally from interrupt) vISR_Handler(); vTaskStartScheduler(); // Normally the scheduler runs forever, but for this example: return 0; }
Time complexity: O(1) - sending to queue from ISR is fast and predictable.
Space complexity: Depends on queue size and item size.
Common mistake: Not checking pxHigherPriorityTaskWoken and not calling portYIELD_FROM_ISR() when needed, which can delay task switching.
Use xQueueSendFromISR instead of xQueueSend inside ISRs to avoid blocking and ensure safe operation.
xQueueSendFromISR safely sends data to a queue from an interrupt.
Always check pxHigherPriorityTaskWoken and call portYIELD_FROM_ISR() if needed.
Use this function to communicate between ISRs and tasks without blocking.
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
