Linux Device Driver to Blink LED

Write a Linux device driver to blink LED every 1-second duration for the Raspberry Pi board.

LED used in the exercise.

– To buy: https://robu.in/product/grove-blue-led/

– Documentation: https://wiki.seeedstudio.com/Grove-LED_Socket_Kit/

Connection details.

– In this example, GPIO 18 of Raspberry Pi is used for controlling the LED.

Connection details for LED blinking device driver.

SIG : where need to give high and low signals which can turn on and off the LED.

VCC: 5V or 3.5V working voltage.

Connection details for LED blinking device driver using Raspberry Pi.

Second raw of Raspberry Pi pinout.

Pin 1 is VCC 5V, connect to VCC of LED.

Pin 6 is GPIO 18, connect to SIG of LED.

PIN 7 is GND, connect to GND of LED.

LED blink device driver.
/*vim led_blink.c
 * blink led every on every 1 second duration
 * Using kernel timers and gpio APIs*/


#include <linux/module.h>      // Needed by all modules
#include <linux/kernel.h>      // Needed for KERN_INFO
#include <linux/init.h>        // Needed for the macros
#include <linux/gpio.h>        // Required for the GPIO functions
#include <linux/timer.h>       // Required for the timer functions

static struct timer_list led_blink_timer;    //timer structure
static unsigned int gpio_led = 18;           // Use GPIO pin 18 for the LED
static bool led_on = false;                 // Is the LED on or off?

/*timer callback, which turns on and off LED every 1sec duration*/
static void led_blink_timer_callback(struct timer_list *timer)
{
        led_on = !led_on;                               // Invert the LED state
        gpio_set_value(gpio_led, led_on);               // Set the GPIO high or low value to processor register

        led_blink_timer.expires = jiffies + msecs_to_jiffies(1000);  //timer of 1sec.
        printk(KERN_INFO "LED is Blinking\n");
        // This will start the timer and upon expiry of timer it will call led_blink_timer_callback
        add_timer(&led_blink_timer);
}

static int __init led_blink_init(void)
{
        int result = 0;
        printk(KERN_INFO "LED Blink: Initializing the LED Blink module\n");

        // Check if GPIO pin is valid
        if (!gpio_is_valid(gpio_led)) {
                printk(KERN_INFO "LED Blink: Invalid GPIO\n");
                return -ENODEV;
        }


        /*gpio_request checks if requested gpis is available to use.
         * If available then reserver for our driver usage.
         * It also sets label for gpio related to our driver which can be useful for debugging.
         * If not available for use then returns error.*/
        if ((result = gpio_request(gpio_led, "sysfs")) < 0)
        {
                printk(KERN_INFO "LED Blink: GPIO request failed\n");
                return result;
        };

        /*set GPIO direction as output.
         * This function goes to the raspberry-pi processor gpio register
         * and configure the register to use as a output direction*/
        gpio_direction_output(gpio_led, false);

        // Initialize the timer
        timer_setup(&led_blink_timer, led_blink_timer_callback, 0);


        led_blink_timer.expires = jiffies + msecs_to_jiffies(1000);        //timer of 1sec.
        // This will start the timer and upon expiry of timer it will call led_blink_timer_callback
        add_timer(&led_blink_timer);

        return result;
}

static void __exit led_blink_exit(void)
{
        printk(KERN_INFO "LED Blink: Exiting the LED Blink module\n");
        gpio_set_value(gpio_led, false);   // Turn the LED off
        gpio_free(gpio_led);               // Free the GPIO
        del_timer(&led_blink_timer);       // Deactivate the timer if running
}

module_init(led_blink_init);
module_exit(led_blink_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("embeddedkernel.com");
MODULE_DESCRIPTION("LED blink driver");
MODULE_VERSION("1");
Makefile.
#vim Makefile
obj-m := led_blink.o
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
KERN_DIR=/home/ek/ek/linux-6.6.27/
HOST_KERN_DIR=/lib/modules/$(shell uname -r)/build/

all:
        make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(PWD) modules
clean:
        make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(PWD) clean
help:
        make ARCH=$(ARCH) CROSS_COMPILE=$(CROSS_COMPILE) -C $(KERN_DIR) M=$(PWD) help
host:
        make -C $(HOST_KERN_DIR) M=$(PWD) modules
hostclean:
        make -C $(HOST_KERN_DIR) M=$(PWD) clean

– KERN_DIR=/home/ek/ek/linux-6.6.27/ – This should be the path on your PC where you have downloaded Linux source code.

Building the module.

– If building on a x64 PC using cross compiler then run :

  • make clean
  • make all

– If building on Raspberry Pi then run :

  • make hostclean
  • make host

Loading the module on Raspberry Pi.

– If a module is built on a PC then copy led_blink.ko to the Raspberry Pi.

– If a module is built on Raspberry Pi then no need to copy it as it is already present on board.

To load on Raspberry Pi run below command
pi@raspberrypi:~/driver/led_blink $ sudo insmod led_blink.ko

To see the logs run below comamnd
pi@raspberrypi:~/driver/led_blink $ dmesg
[89882.485710] LED Blink: Initializing the LED Blink module
[89883.500255] LED is Blinking
[89884.540261] LED is Blinking
[89885.580265] LED is Blinking
[89886.620274] LED is Blinking
[89887.660276] LED is Blinking
[89888.700283] LED is Blinking
[89889.740291] LED is Blinking
[89890.780294] LED is Blinking
[89891.820304] LED is Blinking

To unload the module run below command
pi@raspberrypi:~/driver/led_blink $ sudo rmmod led_blink.ko

pi@raspberrypi:~/driver/led_blink $ dmesg
[91136.777222] LED Blink: Exiting the LED Blink module
Video of blinking LED.

Leave a Comment