Forum Discussion
Altera_Forum
Honored Contributor
20 years agoSimple device driver using an interrupt
I want to write a simple device driver which uses interrupts.
My Nios2 system has the following componentes: cpu, sdram controller, cfi flash controller, jtag uart and a timer. I have added another interval timer to generate an interrupt (irq number 2) every 10 seconds. I have written a driver based on some examples seen on this forum. My driver is able to register the interrupt but the irq handler never gets executed. The driver is included in the kernel and not loaded as a module. The initialization code seems to be executed and the reserved interrupt can be seen in /proc/interrupts file. Any suggestions? here's my driver module code:#include <linux/config.h># include <linux/version.h># include <linux/sched.h># include <linux/signal.h># include <linux/interrupt.h># include <linux/init.h># include <linux/module.h># include <linux/kernel.h>
# include <asm/io.h># include <asm/irq.h># include <asm/nios.h>
# define IRQ_NUMB 2# define IRQ_NAME "MY_IRQ"
MODULE_LICENSE("GPL");
static irqreturn_t irq_handler(int irq, void *dummy, struct pt_regs * regs)
{
printk(KERN_ALERT "MY_IRQ: Interrupt handler executed!\n");
return IRQ_HANDLED;
}
static int __init hello_init(void)
{
int status = 0;
printk("MY_IRQ: Module initialization started\n");
printk("MY_IRQ: Requesting interrupt\n");
status = request_irq(IRQ_NUMB, irq_handler,0,IRQ_NAME, NULL);
enable_irq (IRQ_NUMB); // required with nios?
if (status == 0)
{
printk("MY_IRQ: IRQ request successful!\n");
}
else
{
printk("MY_IRQ: IRQ request failed!\n");
return status;
}
printk ("MY_IRQ: Module initialization ended\n");
return (0);
}
static void __exit hello_exit(void)
{
printk(KERN_ALERT "MY_IRQ: Module unloaded!\n");
free_irq(IRQ_NUMB, NULL);
}
module_init(hello_init);
module_exit(hello_exit); Here are the kernel initialization messages for the module: ....
io scheduler noop registered
io scheduler deadline registered (default)
Serial: JTAG UART driver $Revision: 1.4 $
ttyJ0 at MMIO 0x82001000 (irq = 1) is a jtag_uart
MY_IRQ: Module initialization started
MY_IRQ: Requesting interrupt
MY_IRQ: IRQ request successful!
MY_IRQ: Module initialization ended
Marvell 88E1101: Registered new driver
....
Sash command shell (version 1.1.1)
/> cat /proc/interrupts
: 0 spurious
0: 2405 L timer
1: 63 jtag_uart
2: 0 MY_IRQ
/>3 Replies
- Altera_Forum
Honored Contributor
--- Quote Start --- originally posted by takulu@Jun 28 2006, 03:29 AM here are the kernel initialization messages for the module:.... io scheduler noop registered io scheduler deadline registered (default) serial: jtag uart driver $revision: 1.4 $ ttyj0 at mmio 0x82001000 (irq = 1) is a jtag_uart my_irq: module initialization started my_irq: requesting interrupt my_irq: irq request successful! my_irq: module initialization ended marvell 88e1101: registered new driver .... sash command shell (version 1.1.1) /> cat /proc/interrupts : 0 spurious 0: 2405 l timer 1: 63 jtag_uart 2: 0 my_irq /><div align='right'><{post_snapback}> (index.php?act=findpost&pid=16460)</div> --- Quote End --- As you can see when you cat /proc/interrupts the linux code is perfectly well but you're not getting interrupts from your hardwre component. Maybe you need to enable interrupts on the device you want to get the interrupts from? You should first check (with signal tap for example) wether the interrupts is actually generated.
- Altera_Forum
Honored Contributor
<div class='quotetop'>QUOTE </div>
--- Quote Start --- As you can see when you cat /proc/interrupts the linux code is perfectly well but you're not getting interrupts from your hardwre component. Maybe you need to enable interrupts on the device you want to get the interrupts from? You should first check (with signal tap for example) wether the interrupts is actually generated. <div align='right'><{post_snapback}> (index.php?act=findpost&pid=16464) --- Quote End --- [/b] --- Quote End --- You are right. The timer interrupts needed to be enabled and the interrupt flag cleared after each interrupt. Thank you for your help! The driver with timer initialization:#include <linux/config.h># include <linux/version.h># include <linux/sched.h># include <linux/signal.h> # include <linux/interrupt.h># include <linux/init.h># include <linux/module.h># include <linux/kernel.h> # include <asm/io.h># include <asm/irq.h># include <asm/nios.h> # define IRQ_NUMB 2# define IRQ_NAME "MY_IRQ" // registers for timer // the timer is always running at constant // frequency only the interrupt can be controlled // on and off. # define TIMER_CONTROL_ITO_MSK 0x01# define TIMER_CONTROL_CONT_MSK 0x02# define TIMER_CONTROL_START_MSK 0x04# define TIMER_CONTROL_STOP_MSK 0x08 # define TIMER_STATUS_TO_MSK 0x01# define TIMER_STATUS_RUN_MSK 0x02 # define TIMER_BASE 0x1800020# define TIMER_CONTROL_OFFSET 4# define TIMER_STATUS_OFFSET 0 MODULE_LICENSE("GPL"); static irqreturn_t irq_handler(int irq, void *dummy, struct pt_regs * regs) { printk(KERN_ALERT "MY_IRQ: Interrupt handler executed!\n"); writew(0,TIMER_BASE+TIMER_STATUS_OFFSET); // clear interrupt flag return IRQ_HANDLED; } static int __init hello_init(void) { int status = 0; printk("MY_IRQ: Module initialization started\n"); printk("MY_IRQ: Requesting interrupt\n"); status = request_irq(IRQ_NUMB, irq_handler,0,IRQ_NAME, NULL); enable_irq (IRQ_NUMB); if (status == 0) { printk("MY_IRQ: IRQ request successful!\n"); } else { printk("MY_IRQ: IRQ request failed!\n"); return status; } printk ("MY_IRQ: Module initialization ended\n"); // initialize timer writew(TIMER_CONTROL_ITO_MSK | TIMER_CONTROL_START_MSK | TIMER_CONTROL_CONT_MSK, TIMER_BASE+(TIMER_CONTROL_OFFSET)); return (0); } static void __exit hello_exit(void) { printk(KERN_ALERT "MY_IRQ: Module unloaded!\n"); free_irq(IRQ_NUMB, NULL); } - Altera_Forum
Honored Contributor
You don't need enable_irq (IRQ_NUMB);
request_irq() already enable it. see kernel arch/nios2nommu/kernel/irq.c . This is a good example. http://forum.niosforum.com/work2/style_emoticons/<#EMO_DIR#>/smile.gif Could you please post it on the nios wiki ?