Introduction to RTOS Part 9 - Hardware Interrupts | Digi-Key Electronics

Introduction to RTOS Part 9 - Hardware Interrupts | Digi-Key Electronics

Integration of Hardware Interrupts with FreeRTOS

Understanding Hardware Interrupts

  • The importance of using specific FreeRTOS function calls within interrupt service routines (ISRs) is emphasized due to the critical role interrupts play in embedded systems.
  • Microcontrollers often have built-in peripherals that generate hardware interrupts, such as timers or user inputs like button presses.
  • Communication buses in microcontrollers can notify the CPU about data transmission events without direct CPU involvement, highlighting the asynchronous nature of hardware interrupts.
  • An electrical signal indicates an asynchronous event, prompting the processor to pause its current task and handle the interrupt.

Prioritization and Execution of ISRs

  • In FreeRTOS, hardware interrupts take precedence over any running tasks, regardless of their priority levels.
  • Some microcontrollers support nested interrupts, allowing one interrupt to preempt another; however, this complexity is not covered in detail here.
  • Upon completion of an ISR, execution returns to a task which may not necessarily be the previously running task.

Creating a Timer Interrupt on ESP32

  • The ESP32 features four timers with 16-bit prescalers and 64-bit counters. The default timer clock operates at 80 MHz.
  • Setting a prescaler allows for adjusting timer speed; for example, dividing by 80 results in a timer counting at 1 MHz.
  • A simple LED blinking project is introduced where a timer-driven ISR toggles an LED state every second.

Synchronizing ISRs with Tasks

  • The ISR should reside in internal RAM for faster access. In this case, it simply toggles an LED state when triggered by the timer.
  • Configuration steps include setting up the LED pin as output and starting hardware timer number 0 with specified parameters for triggering the ISR periodically.

Managing Critical Sections and Spin Locks

  • To synchronize tasks and ISRs effectively while preventing race conditions, global variables must be declared volatile if they are modified within ISRs.
  • A two-second delay is added to allow multiple ISR executions before resuming task execution.
  • Spin locks are introduced as mutex alternatives in FreeRTOS to manage critical sections across cores but require careful handling to avoid indefinite waiting scenarios.

Conclusion on Critical Section Management

  • Special functions protect critical sections using spin locks while disabling all interrupts on the current core during execution.

Understanding Critical Sections and ISRs in FreeRTOS

Managing Critical Sections

  • The FreeRTOS documentation advises against calling other API functions from within a critical section. The focus is on incrementing a global variable before releasing the lock and re-enabling interrupts.
  • A task named "print values" is created to decrement a global counter in a loop, printing its value each time. This function must be protected as a critical section to prevent concurrent access issues.

Interrupt Handling

  • Unlike mutexes, which cannot block an interrupt, non-ISR critical section functions are used to disable interrupts and prevent context switching during execution.
  • If an interrupt occurs during the critical section's execution, it will not be dropped; instead, it triggers once the current execution leaves the critical section.

Task Synchronization with ISRs

  • Observations from running the code show that the global variable counts down every two seconds, with occasional repeats indicating ISR activity between print statements.
  • FreeRTOS provides functions for synchronizing variables and passing data between ISRs and tasks. Functions ending in "from isr" should be used when called from within an ISR.

Using Binary Semaphores

  • A scenario is described where two tasks run at different priorities. When task B (higher priority) waits for a semaphore, task A continues executing until interrupted by an ISR.
  • Upon completion of its operations, the ISR gives the semaphore back to allow task B to process data made available by the ISR. This approach exemplifies deferred interrupt handling.

Efficient Data Processing

  • The ISR should remain short; heavy processing tasks like FFT computations should be deferred to regular tasks to maintain system responsiveness.
  • In demo code, adjustments are made so that an ISR samples from an ADC every second while signaling through a binary semaphore for data availability.

Special Considerations for ISRs

  • Inside ISRs, special "from isr" functions are utilized since blocking actions like waiting for semaphores aren't permissible within ISRs.
  • Many "from isr" functions include parameters that determine if higher-priority tasks need immediate scheduling after being unblocked by semaphore availability.

Implementation Details

  • The ESP-IDF version does not require certain parameters; thus simple conditional checks can manage task scheduling post-interrupt effectively.
  • In setup routines, binary semaphores are created and checked for nullity post-initialization. Tasks can then wait indefinitely until they receive signals from their respective ISRs.

Final Demonstration Insights

  • Running this implementation on ESP32 results in ADC values printed once per second—demonstrating effective synchronization between tasks and ISRs using binary semaphores.

Advanced Features

  • Newer versions of FreeRTOS offer direct-to-task notifications as faster alternatives to semaphores when specific tasks await particular data pieces.

Real-Time Operating System (RTOS) Design Considerations

Buffer Management and Task Synchronization

  • The design involves collecting 10 samples over one second, after which an interrupt service routine (ISR) wakes up Task A to compute the average of these samples.
  • It is recommended to use a double buffer or circular buffer for efficient data handling, allowing reading from one part while the ISR fills another.
  • Careful synchronization between tasks and interrupts is crucial, especially in managing buffer overruns where the ISR may write to an element not yet read by Task A.
  • This design pattern is common in RTOS applications, where one task processes incoming data while another manages user input/output.
  • The implementation allows for real-time interaction with a serial terminal, echoing inputs while simultaneously sampling data.

Real-Time Data Processing

  • When entering "avg" into the terminal, it displays the most recently computed average value, demonstrating effective real-time processing.
Video description

Hardware interrupts are important in many embedded systems. They allow us to respond to external events (such as a button being pressed) or internal events (such as a timer expiring) in an asynchronous manner, which means that the processor can stop whatever it was doing to run an interrupt service routine (ISR). The solution to the challenge in the video can be found here: https://www.digikey.com/en/maker/projects/introduction-to-rtos-solution-to-part-9-hardware-interrupts/3ae7a68462584e1eb408e1638002e9ed Code for this video series (including demonstrations, challenges, and solutions) can be found here: https://github.com/ShawnHymel/introduction-to-rtos In most RTOSes, such as FreeRTOS, hardware interrupts occur at a higher priority than all other tasks. This means, unless specifically disabled, hardware interrupts will halt the execution of any currently running task. The CPU will be forced to handle the interrupt before returning to the task. A few tips when working with interrupts: ISRs should never block, which means you should only use FreeRTOS kernel function calls that end in “FromISR” You should keep ISRs as short as possible to avoid delaying tasks longer than necessary Any global variables that get updated in an ISR should be declared with the “volatile” qualifier Rather than perform processing inside an ISR, you can “defer processing” by collecting data into a buffer and letting a task do the processinging. In the video, we look at how to accomplish deferred processing using semaphores (note that you can also use queues and task notifications). When an ISR is done, it can set a lock (e.g. “give” a semaphore), which will unblock a task. This task can then use any data collected by the ISR (e.g. a new ADC value, a buffer filled with data from the serial port, etc.). With this method, you can keep ISRs short while relying on a task to perform any necessary processing. Product Links: https://www.digikey.com/en/products/d...​ Related Videos: Introduction to RTOS Part 1 - What is a Real-Time Operating System (RTOS)? - https://youtu.be/F321087yYy4​ Introduction to RTOS Part 2 - Getting Started with FreeRTOS - https://youtu.be/JIr7Xm_riRs​ Introduction to RTOS Part 3 - Task Scheduling - https://youtu.be/95yUbClyf3E​ Introduction to RTOS Part 4 - Memory Management - https://youtu.be/Qske3yZRW5I​ Introduction to RTOS Part 5 - Queue - https://youtu.be/pHJ3lxOoWeI​ Introduction to RTOS Part 6 - Mutex - https://youtu.be/I55auRpbiTs​ Introduction to RTOS Part 7 - https://youtu.be/5JcMtbA9QEE​ Introduction to RTOS Part 8 - https://youtu.be/b1f1Iex0Tso Introduction to RTOS Part 9 - https://youtu.be/qsflCf6ahXU Introduction to RTOS Part 10 - https://youtu.be/hRsWi4HIENc Introduction to RTOS Part 11 - https://youtu.be/C2xKhxROmhA Introduction to RTOS Part 12 - https://youtu.be/LPSHUcH5aQc Related Project Links: https://www.digikey.com/en/maker/projects/introduction-to-rtos-solution-to-part-9-hardware-interrupts/3ae7a68462584e1eb408e1638002e9ed Related Articles: https://www.digikey.com/en/maker/videos/shawn-hymel/getting-started-with-stm32-and-nucleo-part-3-how-to-run-multiple-threads-with-cmsis-rtos-interface Learn more: Maker.io - https://www.digikey.com/en/maker Digi-Key’s Blog – TheCircuit https://www.digikey.com/en/blog Connect with Digi-Key on Facebook https://www.facebook.com/digikey.electronics/ And follow us on Twitter https://twitter.com/digikey