Bird
Raised Fist0
FreeRTOSprogramming~7 mins

Queue from ISR (xQueueSendFromISR) in FreeRTOS

Choose your learning style10 modes available
Introduction

We use xQueueSendFromISR to safely send data to a queue from an interrupt. This helps communication between interrupts and tasks without causing problems.

When an interrupt needs to send data to a task for processing.
When you want to notify a task about an event detected in an ISR.
When you want to pass sensor data collected in an ISR to a task.
When you want to avoid blocking or delays inside an ISR.
When you want to safely share information between ISRs and tasks.
Syntax
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.

Examples
This sends data when the queue is empty, so the task waiting on the queue can run immediately.
FreeRTOS
// 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);
}
This shows how to check if the queue is full and handle that case.
FreeRTOS
// 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);
}
Works the same way even if the queue has one element already.
FreeRTOS
// 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);
}
Sample Program

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.

FreeRTOS
#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;
}
OutputSuccess
Important Notes

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.

Summary

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

(1/5)
1.

What is the primary purpose of xQueueSendFromISR() in FreeRTOS?

easy
A. To send data to a queue safely from an interrupt service routine (ISR)
B. To create a new queue in the system
C. To delete a queue from an ISR
D. To block a task until data is received

Solution

  1. Step 1: Understand the function context

    xQueueSendFromISR() is designed to be called inside an ISR, where normal queue functions that can block are unsafe.
  2. Step 2: Identify the function's role

    It safely sends data to a queue without blocking, allowing communication from ISR to tasks.
  3. Final Answer:

    To send data to a queue safely from an interrupt service routine (ISR) -> Option A
  4. Quick Check:

    Purpose of xQueueSendFromISR = safe queue send from ISR [OK]
Hint: Remember: xQueueSendFromISR is for sending data inside interrupts [OK]
Common Mistakes:
  • Confusing it with queue creation or deletion
  • Thinking it blocks the ISR
  • Using normal queue send functions inside ISR
2.

Which of the following is the correct way to call xQueueSendFromISR()?

BaseType_t xQueueSendFromISR(QueueHandle_t xQueue, const void * pvItemToQueue, BaseType_t *pxHigherPriorityTaskWoken);
easy
A. xQueueSendFromISR(queue, data, NULL);
B. xQueueSendFromISR(queue, &data, NULL);
C. xQueueSendFromISR(&queue, &data, NULL);
D. xQueueSendFromISR(queue, &data);

Solution

  1. 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.
  2. 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.
  3. Final Answer:

    xQueueSendFromISR(queue, &data, NULL); -> Option B
  4. Quick Check:

    Correct parameters and pointers used = xQueueSendFromISR(queue, &data, NULL); [OK]
Hint: Always pass data address and pxHigherPriorityTaskWoken pointer [OK]
Common Mistakes:
  • Passing data instead of its address
  • Passing queue address instead of handle
  • Omitting the third parameter
3.

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.

medium
A. pdFAIL (0)
B. pdFALSE (0)
C. pdTRUE (1)
D. pdPASS (1)

Solution

  1. Step 1: Understand return values of xQueueSendFromISR

    The function returns pdPASS (1) if the item was successfully sent to the queue, pdFAIL (0) otherwise.
  2. Step 2: Analyze queue state

    Since myQueue has space, the send will succeed, so result will be pdPASS (1).
  3. Final Answer:

    pdPASS (1) -> Option D
  4. Quick Check:

    Queue has space, send success = pdPASS (1) [OK]
Hint: If queue has space, xQueueSendFromISR returns pdPASS (1) [OK]
Common Mistakes:
  • Confusing pdPASS with pdTRUE
  • Assuming it returns pdFALSE on success
  • Ignoring queue capacity
4.

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();
    }
}
medium
A. value should be a pointer, not an int
B. portYIELD_FROM_ISR() is called incorrectly
C. xHigherPriorityTaskWoken is not initialized before use
D. xQueueSendFromISR() cannot be called inside ISR

Solution

  1. Step 1: Check variable initialization

    xHigherPriorityTaskWoken must be initialized to pdFALSE before calling xQueueSendFromISR() to avoid unpredictable behavior.
  2. Step 2: Verify other parts

    Calling portYIELD_FROM_ISR() conditionally is correct; value is passed by address; calling xQueueSendFromISR() inside ISR is valid.
  3. Final Answer:

    xHigherPriorityTaskWoken is not initialized before use -> Option C
  4. Quick Check:

    Initialize xHigherPriorityTaskWoken = pdFALSE before use [OK]
Hint: Always init xHigherPriorityTaskWoken to pdFALSE before sending [OK]
Common Mistakes:
  • Not initializing xHigherPriorityTaskWoken
  • Misusing portYIELD_FROM_ISR
  • Passing data incorrectly
5.

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?
}
hard
A. Call portYIELD_FROM_ISR(xHigherPriorityTaskWoken); after sending
B. Call vTaskDelay(1); inside the ISR
C. Call taskYIELD(); inside the ISR unconditionally
D. Do nothing; the task will run eventually

Solution

  1. 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.
  2. Step 2: Use correct yield function

    portYIELD_FROM_ISR(xHigherPriorityTaskWoken); triggers a context switch only if needed, which is the correct approach.
  3. Final Answer:

    Call portYIELD_FROM_ISR(xHigherPriorityTaskWoken); after sending -> Option A
  4. Quick Check:

    Use portYIELD_FROM_ISR with xHigherPriorityTaskWoken to yield [OK]
Hint: Use portYIELD_FROM_ISR with flag to yield only if needed [OK]
Common Mistakes:
  • Calling blocking functions like vTaskDelay in ISR
  • Calling taskYIELD unconditionally inside ISR
  • Ignoring portYIELD_FROM_ISR call
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard