我的目标是在每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。
答案 0 :(得分:1)
在this post中阅读了@VivekS的答案之后,我看了一下Linux设备驱动程序,第10章,其中说明:
处理程序无法将数据传输到用户空间或从用户空间传输数据,因为它 不会在流程的上下文中执行。处理程序也做不到 任何会睡觉的东西,比如调用wait_event,分配 内存与GFP_ATOMIC以外的任何内容,或锁定信号量。 最后,处理程序无法调用计划。