Extra 5% OFF Use Code: OL05
Free Shipping over ₹999

Interrupts Basics

In FreeRTOS, interrupts are a critical part of handling events that need immediate attention, such as button presses, sensor readings, or receiving data from a communication protocol. When an interrupt occurs, the associated Interrupt Service Routine (ISR) is triggered, which can perform simple tasks directly or notify FreeRTOS tasks.

Key Concepts in FreeRTOS Interrupts

  1. ISR (Interrupt Service Routine):
    • A function that executes in response to an interrupt.
    • Should be kept short to avoid blocking other interrupts.
  2. Handling Interrupts in FreeRTOS:
    • You can use an ISR to interact with FreeRTOS tasks by giving a semaphore, sending to a queue, or notifying a task.
    • xSemaphoreGiveFromISR(), xQueueSendFromISR(), and vTaskNotifyGiveFromISR() are FreeRTOS functions designed for ISRs.
  3. Interrupt Priority:
    • Configured to control the priority level of interrupts.
    • Lower numbers indicate higher priority.

Example: Setting Up and Handling Interrupts

In this example, we set up an interrupt to respond to a button press, and the ISR notifies a FreeRTOS task to toggle an LED.

Example Code

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "driver/gpio.h"

// Pin definitions
#define BUTTON_PIN 0   // GPIO0 for the button input
#define LED_PIN 2      // GPIO2 for the LED output

// Semaphore handle
SemaphoreHandle_t xButtonSemaphore;

// ISR for handling button press
void IRAM_ATTR button_isr_handler(void* arg) {
    // Give semaphore from ISR
    xSemaphoreGiveFromISR(xButtonSemaphore, NULL);
}

// Task to toggle LED on button press
void vTaskButtonHandler(void* pvParameters) {
    // Configure LED_PIN as output
    gpio_pad_select_gpio(LED_PIN);
    gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
    
    while (1) {
        // Wait for the semaphore to be given by the ISR
        if (xSemaphoreTake(xButtonSemaphore, portMAX_DELAY) == pdTRUE) {
            // Toggle LED
            static int ledState = 0;
            ledState = !ledState;
            gpio_set_level(LED_PIN, ledState);
            printf("Button pressed, LED toggled\n");
        }
    }
}

void app_main(void) {
    // Initialize button semaphore
    xButtonSemaphore = xSemaphoreCreateBinary();
    if (xButtonSemaphore == NULL) {
        printf("Failed to create semaphore\n");
        return;
    }

    // Configure BUTTON_PIN as input with interrupt on the rising edge
    gpio_pad_select_gpio(BUTTON_PIN);
    gpio_set_direction(BUTTON_PIN, GPIO_MODE_INPUT);
    gpio_set_intr_type(BUTTON_PIN, GPIO_INTR_POSEDGE);

    // Install ISR for BUTTON_PIN
    gpio_install_isr_service(0);
    gpio_isr_handler_add(BUTTON_PIN, button_isr_handler, NULL);

    // Create task to handle button press and toggle LED
    xTaskCreate(vTaskButtonHandler, "Button Task", 2048, NULL, 1, NULL);
}

Explanation of the Code

  1. Defining the GPIO Pins:
    • BUTTON_PIN is set as the input pin for a button.
    • LED_PIN is set as the output pin for an LED.
  2. Creating a Semaphore:
    • xButtonSemaphore is created using xSemaphoreCreateBinary(). This semaphore is given from the ISR and taken by the task when the button is pressed.
  3. Setting up the ISR:
    • gpio_set_intr_type() sets up an interrupt on BUTTON_PIN to trigger on the rising edge, meaning the button press.
    • gpio_install_isr_service(0) installs the ISR service.
    • gpio_isr_handler_add() assigns the button_isr_handler ISR function to BUTTON_PIN.
  4. Button ISR:
    • When the button is pressed, button_isr_handler is called.
    • It gives the semaphore xButtonSemaphore using xSemaphoreGiveFromISR(), which wakes up the task that’s waiting for the button press event.
  5. Task Handling the Button Press:
    • vTaskButtonHandler waits for xButtonSemaphore.
    • When xButtonSemaphore is given by the ISR, it toggles the LED connected to LED_PIN.
  6. app_main Function:
    • Sets up GPIO configurations, initializes the semaphore, and creates the task.

Output Explanation

When you press the button connected to BUTTON_PIN, the following happens:

  1. The button ISR (button_isr_handler) gives the semaphore xButtonSemaphore.
  2. vTaskButtonHandler takes the semaphore and toggles the LED.
  3. You’ll see a message like Button pressed, LED toggled on the console.

Summary

  • ISR: Triggered by an interrupt (button press), executes quickly, and uses xSemaphoreGiveFromISR() to notify a task.
  • Semaphore: Used to synchronize between ISR and task.
  • Task: Waits for the semaphore, and upon receiving it, toggles the LED.

This setup allows you to handle interrupts efficiently in FreeRTOS without blocking tasks, while keeping the ISR short and responsive.

    Leave a Reply

    Your email address will not be published.

    Need Help?