Scan to followLearn Embedded Together, learn and grow together

This is a series of introductory articles on FreeRTOS. While organizing my own knowledge, I hope to help beginners quickly get started and master the basic principles and usage methods of FreeRTOS.
FreeRTOS Quick Start – Initial Exploration of the System
FreeRTOS official Chinese website is now online!
FreeRTOS Coding Standards and Data Types
FreeRTOS Quick Start – Task Management
FreeRTOS Learning: Detailed Explanation of Message Queues
FreeRTOS Learning: Counting Semaphores
FreeRTOS Learning: Mutex Semaphores
FreeRTOS Learning: Event Groups
FreeRTOS Learning: Task Notifications
FreeRTOS Learning: Software Timers
FreeRTOS Learning: Memory Management
FreeRTOS Learning: Resource Management
This article introduces the interrupt management related content of FreeRTOS.
As a real-time operating system, the interrupt management mechanism is one of its core functions.
Good interrupt management is crucial for the performance of real-time systems, as it directly affects the system’s response time, throughput, and reliability.
The Importance of Interrupts in RTOS
In real-time operating systems, interrupts are the primary mechanism for notifying the CPU of external events.
Compared to polling, interrupts provide faster response times because the CPU is only notified when an event occurs, rather than continuously checking the event status.
Characteristics of Interrupt Handling
FreeRTOS’s interrupt management has the following characteristics:
- Supports interrupt nesting
- Provides interrupt-safe APIs (FromISR versions)
- Configurable interrupt priorities
- Works in conjunction with the task scheduler
- Lightweight design, suitable for resource-constrained embedded systems
FreeRTOS Interrupt Mechanism
Interrupt Priorities
FreeRTOS uses numerical values to represent priorities, with higher numbers indicating higher priorities.
In most architectures:
- configMAX_SYSCALL_INTERRUPT_PRIORITY: Defines the highest priority (numerically lowest) of interrupts that FreeRTOS can manage
- configKERNEL_INTERRUPT_PRIORITY: Defines the interrupt priority used by the kernel itself
/* Typical configuration example (ARM Cortex-M) */
#define configKERNEL_INTERRUPT_PRIORITY 255
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 191
Interrupt Service Routines (ISR)
ISRs in FreeRTOS must follow specific rules:
void vAnInterruptHandler(void)
{
/* Interrupt handling prologue */
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Actual interrupt handling */
// ... interrupt handling logic
/* May need to wake a task */
xHigherPriorityTaskWoken = pdTRUE;
/* Interrupt handling epilogue */
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
}
Critical Section Protection
FreeRTOS provides two critical section protection mechanisms:
- taskENTER_CRITICAL() / taskEXIT_CRITICAL()
- Completely disables interrupts
- Applicable in task context
- Used in ISR
- Only disables interrupts with a priority lower than configMAX_SYSCALL_INTERRUPT_PRIORITY
Interrupt and Task Communication
Waking Tasks from Interrupts
FreeRTOS provides several mechanisms for passing information from interrupts to tasks:
-
Binary Semaphores: Used for simple event notifications
void vISRHandler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -
Counting Semaphores: Used to count the number of occurrences of events
void vISRHandler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; xSemaphoreGiveFromISR(xCountingSemaphore, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -
Queues: Used to pass data
void vISRHandler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; uint32_t ulDataToSend = 123; xQueueSendToBackFromISR(xQueue, &ulDataToSend, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } -
Direct Task Notifications: The most efficient communication method
void vISRHandler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; vTaskNotifyGiveFromISR(xTaskHandle, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); }
Deferred Interrupt Handling
For time-consuming interrupt handling, a “deferred interrupt handling” mode can be adopted:
- Only perform the necessary handling in the ISR (e.g., clearing the interrupt flag)
- Wake a high-priority task via semaphore or task notification
- Complete the remaining handling work in that task
This mode can significantly reduce interrupt disable time and improve system responsiveness.
FreeRTOS Interrupt API
Common FromISR APIs
FreeRTOS provides a series of dedicated APIs for interrupt context, which end with “FromISR”:
<span>xQueueSendToBackFromISR() / xQueueSendToFrontFromISR()</span><span>xQueueReceiveFromISR()</span><span>xSemaphoreGiveFromISR()</span><span>xSemaphoreTakeFromISR()</span><span>xTaskResumeFromISR()</span><span>vTaskNotifyGiveFromISR()</span><span>xTaskNotifyFromISR()</span>
Usage Example
// Queue sending example
void vUARTInterruptHandler(void)
{
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
char cReceivedChar;
// Read UART data
cReceivedChar = UART_DR;
// Send to queue
if(xQueueSendToBackFromISR(xUARTQueue, &cReceivedChar, &xHigherPriorityTaskWoken) != pdPASS)
{
// Queue is full, handle error
}
// If needed, perform context switch
portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}
Interrupt Nesting and Priority Management
Interrupt Nesting
FreeRTOS fully supports interrupt nesting. When one interrupt is executing, a higher-priority interrupt can preempt the current interrupt.
Priority Grouping
On architectures like ARM Cortex-M, FreeRTOS uses a priority grouping mechanism:
// Set priority grouping on ARM Cortex-M
NVIC_SetPriorityGrouping(4); // 4 bits for preemption priority, 0 bits for sub-priority
Interrupt Priority Configuration
// Configure UART interrupt priority
NVIC_SetPriority(UART_IRQn, configMAX_SYSCALL_INTERRUPT_PRIORITY - 1);
Usage Recommendations
Principles for Optimizing Interrupt Handling
- Keep ISRs Short: Only do the necessary work
- Avoid Blocking Calls: Do not use non-FromISR APIs in ISRs
- Set Priorities Reasonably: Set critical interrupts to high priority, but not higher than configMAX_SYSCALL_INTERRUPT_PRIORITY
- Use Deferred Handling: Delegate time-consuming operations to tasks
- Minimize Critical Sections: Minimize interrupt disable time
Common Mistakes and Avoidance Methods
- Using Non-FromISR APIs in ISRs
- Error: Using xQueueSend() instead of xQueueSendFromISR()
- Consequence: May lead to system crashes or data corruption
- Error: Ignoring the return value of xQueueSendFromISR()
- Consequence: May lose important data
- Error: Setting interrupt priority higher than configMAX_SYSCALL_INTERRUPT_PRIORITY
- Consequence: FreeRTOS cannot manage these interrupts, potentially leading to data races
- Error: Performing time-consuming operations in critical sections
- Consequence: Increases system latency, affecting real-time performance
Port Layer and Hardware-Related Handling
Key Points for Porting
FreeRTOS’s interrupt management relies on the hardware abstraction layer, with key porting functions including:
<span>portENABLE_INTERRUPTS() / portDISABLE_INTERRUPTS()</span><span>portSET_INTERRUPT_MASK_FROM_ISR() / portCLEAR_INTERRUPT_MASK_FROM_ISR()</span><span>portYIELD_FROM_ISR()</span>
Context Switching Mechanism
When an interrupt may cause a higher-priority task to become ready, FreeRTOS performs context switching in one of the following ways:
- Manual Switching: Call
<span>portYIELD_FROM_ISR(xHigherPriorityTaskWoken)</span> - Automatic Switching: Some ports automatically check the switch flag upon exiting the interrupt
Debugging and Troubleshooting
Common Debugging Tips
- Check Interrupt Priorities: Ensure that all interrupts using FreeRTOS APIs have priorities not higher than configMAX_SYSCALL_INTERRUPT_PRIORITY
- Use Tracing Tools: FreeRTOS provides trace macros to log interrupt and task activities
- Check Stack Usage: Ensure that the interrupt stack is sufficiently large
- Validate FromISR API Usage: Ensure that only FromISR versions of APIs are used in ISRs
Typical Problem Solutions
Problem 1: System crashes in interrupt
- Possible Cause: Non-FromISR APIs used in ISR
- Solution: Check all ISRs to ensure only FromISR version APIs are used
Problem 2: Data loss or corruption
- Possible Cause: Improper interrupt priority settings leading to data races
- Solution: Reconfigure interrupt priorities to ensure critical resources are protected
Problem 3: System response is slow
- Possible Cause: Long interrupt handling times
- Solution: Adopt deferred interrupt handling mode, moving time-consuming operations to tasks
Conclusion
FreeRTOS’s interrupt management provides a powerful and flexible mechanism for handling hardware events while maintaining system real-time performance and reliability.
By properly using interrupt priorities, FromISR APIs, and task communication mechanisms, developers can build efficient and responsive embedded systems.

Follow 【Learn Embedded Together】 to become better together..
If you find this article helpful, click “Share”, “Like”, or “Recommend”!