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.