Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
19 years ago

Simple 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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored 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&#39;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's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored 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&#39;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);
    }