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.
SIG : where need to give high and low signals which can turn on and off the LED.
VCC: 5V or 3.5V working voltage.
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