Embedded Development Board Learning


Interrupts in FreeRTOS #5 Managing Interruptions

Date: marzo 3, 2025

Author: Guillermo Garcia

Categories: RTOS Tags:

Interrupts in FreeRTOS are a mechanism crucial role in real-time operating systems (RTOS), enabling efficient handling of time-sensitive tasks. FreeRTOS, a popular RTOS for embedded systems, provides a structured approach to managing interrupts.

Understanding Interrupts in FreeRTOS

Interrupts are essential in an embedded system since they allow different events to be handled asynchronously. In this article we will see how to manage interruptions when developing applications based on FreeRTOS.

It is important that we know certain details about using interruptions properly before starting to work with the rest of the FreeRTOS mechanisms.

Interrupt ARM

Microcontrollers with an ARM Cortex-M core have a flexible and powerful system for managing interrupts, a nested vector interrupt controller (NVIC).

When dealing with an operating system like FreeRTOS, the NVIC may seem unintuitive, and if interrupts are not managed well, bad things can happen in the application.

Interrupt Vectors

The ARM Cortex-M architecture distributes interrupts through a vector where each member of the vector represents a specific interrupt to a system service. Let’s see an example for the M0/M0+ and M4/M4.

This vector includes both system exceptions and peripheral interrupts. Negative IRQs (-1 (SysTick) to -14 (NMI) plus reset) are defined by the ARM core, everything else «above» with an IRQ number >=0 are vendor specific and usually correspond to peripheral interrupts like UART, I²C, USB that are assigned by the microcontroller vendor.

Interrupts Priorities

Understanding how interrupts are managed allows us to understand how to assign the correct priorities and also let FreeRTOS know about it. When assigning priorities to an interrupt we have to keep in mind one very important thing:

The lower the priority number assigned, the greater the urgency.

This means that interrupt priority 0 is the most urgent.

The exception/interrupt priority is assigned with an 8-bit priority register and the number of bits implemented depends on the vendor implementation. ARM specifies a minimum of 2 bits for M0/M0+ and 3 bits for M3/M4/M7.

/* Cortex-M specific definitions. */
 #ifdef __NVIC_PRIO_BITS
     /* __BVIC_PRIO_BITS will be specified when CMSIS is being used. */
     #define configPRIO_BITS       		__NVIC_PRIO_BITS
 #else
     #define configPRIO_BITS       		4        /* 15 priority levels */
 #endif

 /* The lowest interrupt priority that can be used in a call to a "set priority"
 function. */
 #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY			0xf
 
 /* The highest interrupt priority that can be used by any interrupt service
 routine that makes calls to interrupt safe FreeRTOS API functions.  DO NOT CALL
 INTERRUPT SAFE FREERTOS API FUNCTIONS FROM ANY INTERRUPT THAT HAS A HIGHER
 PRIORITY THAN THIS! (higher priorities are lower numeric values. */
 #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY	5
 
 /* Interrupt priorities used by the kernel port layer itself.  These are generic
 to all Cortex-M ports, and do not rely on any particular library functions. */
 #define configKERNEL_INTERRUPT_PRIORITY 		( configLIBRARY_LOWEST_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )
 /* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!!
 See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */
 #define configMAX_SYSCALL_INTERRUPT_PRIORITY 	( configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY << (8 - configPRIO_BITS) )

FreeRTOS uses the configKERNEL_INTERRUPT_PRIORITY macro in FreeRTOSConfig.h for interrupts used by the kernel port layer.

As mentioned above, the important point to note is that configKERNEL_INTERRUPT_PRIORITY is set to the lowest urgent interrupt level in the system. This means that kernel interrupts (SysTick and context switches) are executed with the lowest urgency possible. This makes sense since the kernel should not block or interrupt the other interrupts in the system.

Using an RTOS like FreeRTOS means that I have to understand its use of the interrupt system because otherwise it can lead to conflicts and incorrect application behavior. The following table can serve as a guide for setting the priorities in our application with FreeRTOS.

Calling RTOS API Functions from ISR

It is not uncommon to call RTOS functions (e.g. to set or clear a semaphore) from an interrupt service routine (ISR). There is one very important rule with FreeRTOS:

Only RTOS API functions ending with FromISR are allowed to be called from an interrupt service routine.

FromISR functions are interrupt-safe, for example:

Closing

If there is one thing you need to consider before continuing with this serious issue regarding interruptions in FreeRTOS, it is the following points.

  • FreeRTOS task priorities start with 0 as the lowest urgent RTOS task priority, while ARM NVIC uses zero as the highest urgent interrupt priority.
  • Interrupt service routines that call the RTOS API must use the safe FromISR() interrupt variants.
  • Only interrupts with NVIC numeric values ​​greater than or equal to configMAX_SYSCALL_INTERRUPT_PRIORITY can use the RTOS API.


Card image cap
Guillermo Garcia Thanks for reading! I am one of the editors of this site and I am committed to providing you with the best information possible by sharing my experience in embedded systems.


Comments... There are no comments.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Publicidad