阅读:1002回复:0
请教内核中断问题
请问,在中断服务程序中对某变量(不是全局变量)赋值,普通程序可以正确访问吗?
我在写一个设备驱动时,先定义一个全局变量(其中与本问题无关的部分我都用..........省去,以减少大家阅读量,但还是显得冗余,望见谅): DECLARE_WAIT_QUEUE_HEAD(rx_wq); DECLARE_WAIT_QUEUE_HEAD(tx_wq); struct device_card { .................. unsigned short dma_error; //dma transfer err flag, 0:success, 1:tx fail 2:rx fail int open_count; struct semaphore sem; } *card ; 注:大家只需注意dma_error分量就行。 在模块初始化时,给该结构体赋初值: if((card = kmalloc(sizeof(struct device_card),GFP_KERNEL))==NULL){ printk(KERN_ERR "pci_device:out of memory!\n"); return -ENOMEM; } memset(card,0,sizeof(struct device_card)); ............... card->dma_error = 0; //初始值为0 card->open_count = 0; sema_init(&card->sem,1); 然后在open函数中将该结构体指针存于文件的file->private_data中: static int device_open(struct inode * inode,struct file *file) { struct device_card *dev; dev = (struct device_card *) file->private_data; // get the file private data,namely set dev if(!dev) { dev = card ; file->private_data = dev ; } //request to own the control right if(down_interruptible(&dev->sem) ) { printk("device_open lock sem error!\n"); return -ERESTARTSYS; } if(file->f_flags &O_NONBLOCK ) { //check open mode up(&dev->sem); return -EBUSY; } ................... dev->open_count ++; up(&dev->sem); MOD_INC_USE_COUNT; return 0; } 在实现read时,要根据dma_error的值做一些相关的处理,其中dma_error应当在中断处理程序中根据数据传输结果改变。 ssize_t device_write(struct file *filp,const void *buf,size_t count,loff_t *f_pos) { struct device_card *dev = filp->private_data; if(down_interruptible(&dev->sem) ) { printk("device_write lock sem error!\n"); return -ERESTARTSYS; } ....................... do { .............// 启动中断触发事件 interruptible_sleep_on(&rx_wq); //等待中断唤醒 //dma transfer commpleted! if( dev->dma_error ==2) //根据中断返回结果做处理 memset(dev->dma_buffer,0,MAX_LENGTH); // clear for next time to receive data } while( (dev->dma_error == 2)&&(dma_err_cnt<3) ); //if dma rx err & rx_err_cnt < 3, restart dma if( dev->dma_error ==2) { printk("device_read receive error for more than 3 times! abort dma transfer!\n"); count = -5; // if return -5 ,dma transfer error! goto out; } .....................//做相应的处理 out : memset(dev->dma_buffer,0,MAX_LENGTH); kfree(sglist); up (&dev->sem); return cnt; } 中断处理程序如下: static void device_interrupt(int irq, void *dev_id,struct pt_regs *regs) { struct device_card *card_int =(struct device_card *) dev_id; u8 status; status = inb_p(card_int->iobase +BUS_MASTER_STATUS); //读取状态字 if(!(status & INT_MASK)) { return; //not for us } outw_p(status & INT_MASK,card_int->iobase +BUS_MASTER_STATUS); //clear interrupt flag if( status & DMA_TX ) { // dma send outb_p(0,card_int->iobase + BUS_MASTER_CMD); //stop dma transfer if(status &DMA_ERR ) card_int-> dma_error = 1; else card_int-> dma_error = 0; wake_up_interruptible(&tx_wq); } else { // dma receive if(status &DMA_ERR ) card_int-> dma_error = 2; else card_int-> dma_error = 0; wake_up_interruptible(&rx_wq); } return ; } (终于贴完了) 因为我的每个普通函数(如open、read)都有互斥信号量 sem,不知道在中断服务程序中能否访问改变 dma_error ,改变后也不知read函数中能否访问。 真的很不好意思,搞的那么长,浪费大家时间(但我想把问题说得清楚一点),希望大家谅解并能帮助,我想这个问题比较简单,只是我是初次写driver就问得有点对不住大家了。 |
|