GPIO Interrupt

This program was an introduction to attaching interrupts on a GPIO pin. An interrupt can be generated for every GPIO pin in four scenarios: the GPIO is logical 1, the GPIO is logical 0, there is a falling edge or there is a rising edge. The resources for the project include the C SDK User Guide, the RP2040 Datasheet and Prof. Hunter's website.


The complete code

/*
 * Parth Sarthi Sharma (pss242@cornell.edu)
 * Code based on examples from Raspberry Pi Foundation.
 * This code is a demonstration of the GPIO interrupt on the RaspberryPi
 * Pico.
 */
#include <stdio.h> //The standard C library
#include "pico/stdlib.h" //Standard library for Pico
#include "hardware/gpio.h" //The hardware GPIO library

#define PIN 2 //The GPIO pin for interrupt

volatile unsigned long long int counter = 0; //The counter variable

void gpio_callback(uint gpio, uint32_t events) { //The GPIO callback function to handle interrupts
    counter++; //Increment the counter
    printf("%llu\n", counter); //Print the new value of the counter
}

int main() { //The program running on core 0
    stdio_init_all(); //Initialize all of the present standard stdio types that are linked into the binary

    gpio_set_irq_enabled_with_callback(PIN, GPIO_IRQ_EDGE_FALL, true, &gpio_callback); //Enable interrupts for the GPIO pin. Note: Currently the GPIO parameter is ignored, and this callback will be called for any enabled GPIO IRQ on any pin

    while (1){ //Empty eternity
    }

    return 0;
}


Stepping through the code

Includes

The first lines of code in the C source file include some header files. One of these is standard C headers (stdio.h) and the others are headers which come from the C SDK for the Raspberry Pi Pico. The first of these, pico/stdlib.h is what the SDK calls a "High-Level API." These high-level API's "provide higher level functionality that isn’t hardware related or provides a richer set of functionality above the basic hardware interfaces." The architecture of this SDK is described at length in the SDK manual. All libraries within the SDK are INTERFACE libraries.

The next include pulls in hardware APIs which are not already brought in by pico/stdlib.h. This is the hardware/gpio.h library which gives us access to the API associated with the hardware GPIO on the RP2040.

Don't forget to link these in the CMakeLists.txt file!

#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"


Global declarations and defines

The next section of the code is the #define's and the global variables which will be used throughout the code. These are the pin number (I attached a push button to this pin) and the counter variable to keep track of the number of times the button was pressed.

Note: The counter variable needs to be volatile as it is being changed by an interrupt.

#define PIN 2
volatile unsigned long long int counter = 0;


The interrupt handler

The gpio_callback() is the function that is called every time the pushbutton calls the interrupt. Since there can only be one interrupt callback associated with the GPIO pins, it takes in the GPIO pin and the event as arguments to take decisions based on them. My interrupt handler increments the counter variable and prints it out on the console.

void gpio_callback(uint gpio, uint32_t events) {
    counter++;
    printf("%llu\n", counter);
}


The main function

Initializing UART

The first line in main() is a call to stdio_init_all(). This function initializes stdio to communicate through either UART or USB, depending on the configurations in the CMakeLists.txt file.

stdio_init_all();


Initializing the Interrupt

I used the gpio_set_irq_enabled_with_callback() function enable interrupts for the GPIO pin. Note: Currently the GPIO parameter is ignored, and this callback will be called for any enabled GPIO IRQ on any pin.

gpio_set_irq_enabled_with_callback(PIN, GPIO_IRQ_EDGE_FALL, true, &gpio_callback);


The infinite while loop

The infinite while loop for this program is an empty while loop which serves only to keep the core running and not let it exit.

while(1){
}


The output

In order to view the output, I used PuTTY. As it shows, the counter variable increments as I press the button.

The output of the button presses

CMakeLists.txt

cmake_minimum_required(VERSION 3.13)

include(pico_sdk_import.cmake)

project(HelloIRQ)

pico_sdk_init()

add_executable(HelloIRQ HelloIRQ.c)

pico_enable_stdio_usb(HelloIRQ 1)
pico_enable_stdio_uart(HelloIRQ 0)

pico_add_extra_outputs(HelloIRQ)

target_link_libraries(HelloIRQ pico_stdlib hardware_gpio)