Allocate an interrupt line using request_irq and Implementation of IRQ / Interrupt Handler in Linux kernel device driver

Following driver implements, how we can allocate an interrupt line using request_irq kernel API and how to implement an interrupt handler ( e.g. my_interrupt_handlerin this example ) and how to pass a structure with some values from module to IRQ handler.

This code is almost self explainatory with added comments inline. If you want to know ” What is the difference between setup_irq and request_irq in Linux kernel interrupts ” ?

#include <linux/module.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/moduleparam.h>

// execute it as 
// sudo insmod ./interrupt.ko interupt_name="some_name" irq=1
// for testing use irq numbers from cat /proc/interrupts

// remove module as
// sudo rmmod interrupt

static int irq;
static char *interrupt_name;

module_param(interrupt_name, charp,0);
MODULE_PARM_DESC(interrupt_name, "Name for the Interrupt");
module_param(irq, int, 0);
MODULE_PARM_DESC(irq, "The IRQ of the network interface");

struct info_to_pass {
	int *some_int;
	char *some_string;
}dev_info;

static irqreturn_t my_interrupt_handler(int irq, void *dev_id) {
	static int mycount = 0;
	// info is what we passed as &dev_info to request_irq
	// this variable is just a argument carrier from module_init to IRQ handler.
	struct info_to_pass *info = dev_id;

	// static counter to just print debug message 10 times,
	// saying we received interrupt, after 10, we don't print anything
	// but interrupt might have came.
	if (mycount < 10) {
		printk("We received from module init : %s\n", info->some_string);
		printk("Interrupt! = %d\n", mycount);
		mycount++;
	}

	return IRQ_HANDLED;
}

static int __init mymodule_init(void) {
	printk ("My module initialised!\n");

/* request_irq: allocate a given interrupt line */
// int request_irq(unsigned int irq,
//                irq_handler_t handler,
//                unsigned long flags,
//                const char *name,
//                void *dev)
	dev_info.some_string = "helloworld";

	if (request_irq(irq, &my_interrupt_handler, IRQF_SHARED, interrupt_name, &dev_info)) {
		printk(KERN_ERR "myirqtest: cannot register IRQ %d\n", irq);
		return -EIO;
	}

//The second parameter, handler, is a function pointer to the actual interrupt handler that services this interrupt. This function is invoked whenever the operating system receives the interrupt.

// IRQF_SHARED. This flag specifies that the interrupt line can be shared among multiple interrupt handlers. Each handler registered on a given line must specify this flag; otherwise, only one handler can exist per line.

	printk("Request on IRQ %d succeeded\n", irq);
	return 0;
}

static void __exit mymodule_exit(void) {
	free_irq(irq, &dev_info);
	printk("Freeing IRQ %d\n", irq);

	printk ("Unloading my module.\n");
	return;
}

module_init(mymodule_init);
module_exit(mymodule_exit);

MODULE_LICENSE("GPL");

The Simple makefile to compile this driver on Linux laptop is as follows,

obj-m += interrupt.o

all:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules

clean:
        make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean

Compile the driver as,

 $ make 
 $ sudo insmod ./interrupt.ko interrupt_name=somename irq=30 

Currently we have choosen random shared IRQ number 30 for testing to make sure we receive actual interrupt ( As in our driver, we dont consider real hardware interrupt with unique IRQ pin ) from /proc/interrupt

SHUFFLED :   Integrating Linux kernel module inside Linux kernel source and building it as part of kernel compilation

More Reference – https://notes.shichao.io/lkd/ch7/

Android Android Commands Android Java Applications Application Libraries Bash / Shell Scripts Bluetooth driver Build Frameworks Commands and Packages Core Kernel C Programs Development Environment Setup Documents / Books Errors & Failures File Systems Framebuffer / Display Driver git Go Language Programs Hardware Platforms Home Kernel & Device Drivers Kernel Booting and Porting Linux, OS Concepts and Networking Linux Device Drivers Linux Host, Ubuntu, SysAdmin Linux Kernel Linux Networking Middleware Libraries, HAL NDK / Middleware / HAL Network Driver OS Concepts PHP Procfs Filesystem Programming Languages RaspberryPi Scripting and Automation Search Engine Optimisation ( SEO ) Social Media Socurce Code Management ( SCM ) System Administration, Security Testing and Debugging Uncategorized Userspace Utilities Web design and development Wordpress Yocto / Bitbake / Openembedded
Tags:

Leave a Reply