从内核中断读取设备

时间:2014-04-08 18:22:23

标签: linux linux-kernel kernel interrupt interrupt-handling

我的目标是在每T秒读取一个设备(ADC)的内核模块。 我已经有一个工作模块,每隔T秒调用一次中断,我还有另一个模块,用于读取用户空间文件(例如ADC),这是我从this example获得的。 两者都可以单独使用

问题在于,当我尝试打开并读取中断例程中的任何文件时,模块崩溃

[   80.636932] Kernel panic - not syncing: Fatal exception in interrupt

我的代码是这样的:

static irqreturn_t timer_irq_handler(int irq, void *dev_id)
{
    uint16_t value;

    // reset the timer interrupt status
    omap_dm_timer_write_status(timer_ptr, OMAP_TIMER_INT_OVERFLOW);
    omap_dm_timer_read_status(timer_ptr);

    omap_dm_timer_set_load(timer_ptr, 1, 0xFFFFFFFF - (time * gt_rate);

    value = read_channel();

    return IRQ_HANDLED;
}

uint16_t read_channel()
{
    // Create variables
    struct file *f;
    char buf[128];
    mm_segment_t fs;
    int i;
    // Init the buffer with 0
    for(i=0;i \< 128;i++)
        buf[i] = 0;

    f = filp_open(device, O_RDONLY, 0);
    if(f == NULL)
        printk(KERN_ALERT "filp_open error!!.\n");
    else{
        // Get current segment descriptor
        fs = get_fs();
        // Set segment descriptor associated to kernel space
        set_fs(get_ds());
        // Read the file
        f->f_op->read(f, buf, 128, &f->f_pos);
        // Restore segment descriptor
        set_fs(fs);
        // See what we read from file
        printk(KERN_INFO "buf:%s\n",buf);
    }
    filp_close(f,NULL);
    return 0;
}

static int __init mq7_driver_init(void)
{
    int ret = 0;
    struct clk *gt_fclk;

    timer_ptr = omap_dm_timer_request();
    if(timer_ptr == NULL){
        printk("No more gp timers available, bailing out\n");
        return -1;
    }

    // set the clock source to system clock
    omap_dm_timer_set_source(timer_ptr, OMAP_TIMER_SRC_SYS_CLK);

    // set prescalar to 1:1
    omap_dm_timer_set_prescaler(timer_ptr, 0);

    // figure out what IRQ our timer triggers
    timer_irq = omap_dm_timer_get_irq(timer_ptr);

    // install our IRQ handler for our timer
    ret = request_irq(timer_irq, timer_irq_handler, IRQF_DISABLED | IRQF_TIMER , "mq7_driver", timer_irq_handler);
    if(ret){
    printk("mq7_driver: request_irq failed (on irq %d), bailing out\n", timer_irq);
    return ret;
    }

    // get clock rate in Hz
    gt_fclk = omap_dm_timer_get_fclk(timer_ptr);
    gt_rate = clk_get_rate(gt_fclk);

    // set preload, and autoreload
    // we set it to the clock rate in order to get 1 overflow every 3 seconds
    omap_dm_timer_set_load(timer_ptr, 1, 0xFFFFFFFF - (5 * gt_rate)); // dobro do tempo

    // setup timer to trigger our IRQ on the overflow event
    omap_dm_timer_set_int_enable(timer_ptr, OMAP_TIMER_INT_OVERFLOW);

    // start the timer!
    omap_dm_timer_start(timer_ptr);

    // get acess to gpio
    ret = gpio_request(gpio, "mq7_driver sck"); 
    if (ret) {
        printk(KERN_ALERT "gpio_request %d failed\n",gpio);
        gpio_free(gpio);
        return -1;
    }
    gpio_direction_output(gpio, 0);

    // Print adc number into address string
    sprintf(device,"/sys/class/hwmon/hwmon0/device/in%d_input",adc);

    return 0;
}

从中断例程中读取文件有什么问题


P.S。:它在Overo(ARM)上运行,发行版是Poky,内核版本是3.5.7。

1 个答案:

答案 0 :(得分:1)

this post中阅读了@VivekS的答案之后,我看了一下Linux设备驱动程序,第10章,其中说明:

  

处理程序无法将数据传输到用户空间或从用户空间传输数据,因为它   不会在流程的上下文中执行。处理程序也做不到   任何会睡觉的东西,比如调用wait_event,分配   内存与GFP_ATOMIC以外的任何内容,或锁定信号量。   最后,处理程序无法调用计划。