FreeRTOS requires certain rules for interrupt priorities to keep the system stable and responsive. These rules help avoid conflicts between interrupts and the FreeRTOS kernel.
FreeRTOS interrupt priority restrictions
/* Example: Setting interrupt priority in FreeRTOS (C) */ #define configMAX_SYSCALL_INTERRUPT_PRIORITY 5 void ISR_Handler(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; // Use FreeRTOS API safe for ISRs xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); }
The macro configMAX_SYSCALL_INTERRUPT_PRIORITY defines the highest interrupt priority that can safely call FreeRTOS API functions.
Interrupts with priority numerically equal to or higher (lower urgency) than this can use FreeRTOS APIs; others cannot.
#define configMAX_SYSCALL_INTERRUPT_PRIORITY 5 // ISR with safe priority void Safe_ISR(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); }
configMAX_SYSCALL_INTERRUPT_PRIORITY and must not call FreeRTOS APIs.// ISR with too high priority (numerically lower) void Unsafe_ISR(void) { // Calling FreeRTOS API here can cause issues // Do not call FreeRTOS API functions in this ISR }
This program creates a binary semaphore and a task that waits for it. The ISR safely gives the semaphore using FreeRTOS API functions at a safe interrupt priority.
#include "FreeRTOS.h" #include "task.h" #include "semphr.h" #include <stdio.h> #define configMAX_SYSCALL_INTERRUPT_PRIORITY 5 SemaphoreHandle_t xSemaphore; void Safe_ISR(void) { BaseType_t xHigherPriorityTaskWoken = pdFALSE; xSemaphoreGiveFromISR(xSemaphore, &xHigherPriorityTaskWoken); portYIELD_FROM_ISR(xHigherPriorityTaskWoken); } void vTaskFunction(void *pvParameters) { for(;;) { if(xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) { // Semaphore taken, do work // For demo, just print printf("Semaphore received in task\n"); } } } int main(void) { xSemaphore = xSemaphoreCreateBinary(); xTaskCreate(vTaskFunction, "Task", 1000, NULL, 1, NULL); vTaskStartScheduler(); return 0; }
Interrupt priorities in FreeRTOS are often inverted: lower numeric value means higher priority.
Always set configMAX_SYSCALL_INTERRUPT_PRIORITY according to your hardware's priority scheme.
Calling FreeRTOS API functions from interrupts with priority above the allowed limit can cause system crashes or unpredictable behavior.
FreeRTOS restricts which interrupt priorities can safely call its API.
Use configMAX_SYSCALL_INTERRUPT_PRIORITY to define this limit.
ISRs with priority above this limit must not call FreeRTOS API functions.