免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6634 | 回复: 1
打印 上一主题 下一主题

使用wait_event_interruptible 函数的困惑 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-09-08 14:55 |只看该作者 |倒序浏览
大家好,我最近在编写tl16c554串口扩展的驱动,其中在读串口时候调用wait_event_interruptible ()函数等待串口接收数据的到来,以便唤醒read函数,而在串口接收中断处理中调用wake_up_interruptible()以唤醒读进程。现在问题是当用户按下CTRL+C时要中断读函数,而wait_event_interruptible怎么判断是CTRL+C信号中断,还是wake_up_interruptible()唤醒的呢。附上目前的我的问题代码请大家帮帮看看

中断处理函数

  1. static irqreturn_t uart0_irq_handle(int irq, void *dev_id, struct pt_regs *regs){
  2.     volatile unsigned char lsr,isr;
  3.     struct Queue *qCOM_rx_buf;
  4.     int inc = 0;
  5.    // printk(KERN_INFO" uart0 irq handled\n");
  6.   unsigned long flag;
  7.   local_irq_save(flag);
  8.     if (!EXT_COM_USE[0])
  9.     {
  10.         //clear int
  11.         readb(vEXT_COM_BASE_ADDR[0] + ISR);
  12.         readb(vEXT_COM_BASE_ADDR[0] + RBR);
  13.         readb(vEXT_COM_BASE_ADDR[0] + LSR);
  14.         readb(vEXT_COM_BASE_ADDR[0] + MSR);
  15.         printk(KERN_INFO"COM0 is not used\n");
  16.         return IRQ_RETVAL(IRQ_HANDLED);
  17.     }
  18.     if ((qCOM_rx_buf = COM_rx_buf[0])){
  19.         isr = readb(vEXT_COM_BASE_ADDR[0] + ISR);
  20.         while(!(isr&0x01)) {
  21.             isr=(isr&0x0E)>>1;
  22.             switch(isr) {
  23.                 case 3:
  24.                     readb(vEXT_COM_BASE_ADDR[0] + LSR);  
  25.                     break;
  26.                 case 2:
  27.                 case 4:
  28.                 case 6:
  29.                     while ((!qCOM_rx_buf->full) && ((lsr = readb(vEXT_COM_BASE_ADDR[0] + LSR))& 0x01)) {
  30.                         //recive data ready, read later is clear
  31.                         if(!(lsr & 0x8a))
  32.                         {
  33.                         if(++(qCOM_rx_buf->rear) == (qCOM_rx_buf->buf+qCOM_rx_buf->num)){
  34.                             qCOM_rx_buf->rear = qCOM_rx_buf->buf;
  35.                         }
  36.                         if (qCOM_rx_buf->rear == qCOM_rx_buf->front){
  37.                             qCOM_rx_buf->full = 1;
  38.                         }
  39.                         *(qCOM_rx_buf->rear) = readb(vEXT_COM_BASE_ADDR[0] + RBR);
  40.                         //printk("recv data is : %x \n",*(qCOM_rx_buf->rear));
  41.                      
  42.                         rmb();
  43.                         inc++;
  44.                       }
  45.                       else//data error
  46.                       {
  47.                        //printk("recv data error,lsr is %d\n",lsr);
  48.                        readb(vEXT_COM_BASE_ADDR[0] + RBR);
  49.                       }
  50.                     }
  51.                     if (inc){
  52.                         qCOM_rx_buf->emp = 0;
  53.                         wake_up_interruptible(rx_queue[0]);
  54.                     }
  55.                     break;
  56.                
  57.                   
  58.                    // printk("Character time-out indicator\n");  
  59.                     //break;
  60.                 case 0:
  61.                     readb(vEXT_COM_BASE_ADDR[0] + MSR);
  62.                     //printk("Modem status int \n");
  63.                     break;
  64.                 default:
  65.                   
  66.                     printk("Unknow interrupt type : 0x%x!\n",isr);
  67.                     break;
  68.             }
  69.             isr = readb(vEXT_COM_BASE_ADDR[0] + ISR);
  70.         }//end while
  71.   local_irq_restore(flag);
  72.     }
  73.     return IRQ_RETVAL(IRQ_HANDLED);[code]
复制代码

}

[/code]

读函数

  1. static ssize_t uart_read(struct file *filp, char *buf, size_t count, loff_t *f_pos){
  2.     unsigned long flag;
  3.     char rx_buf[BUFSIZE];
  4.     size_t rx_buf_count = 0;
  5.     //unsigned int i;
  6.     struct inode *inode = filp->private_data;
  7.     struct Queue *qCOM_rx_buf = COM_rx_buf[MINOR(inode->i_rdev)];
  8.     printk("uart_read MINOR is %d, filp->f_count is %d\n", MINOR(inode->i_rdev),
  9.             (filp->f_count));
  10.     //local_irq_save(flag);
  11.     while (rx_buf_count < count){
  12.         if (!qCOM_rx_buf->emp){
  13.             if (++qCOM_rx_buf->front == (qCOM_rx_buf->buf + qCOM_rx_buf->num)) {
  14.                 qCOM_rx_buf->front = qCOM_rx_buf->buf;
  15.             }
  16.             if (qCOM_rx_buf->front == qCOM_rx_buf->rear){
  17.                 qCOM_rx_buf->emp = 1;//is empty
  18.             }
  19.             rx_buf[rx_buf_count++] = *qCOM_rx_buf->front;
  20.             qCOM_rx_buf->full = 0;
  21.         }
  22.         else{
  23.             if(wait_event_interruptible(*(rx_queue[MINOR(inode->i_rdev)]),!qCOM_rx_buf->emp) == -ERESTARTSYS);
  24.              return -ERESTARTSYS;
  25.             //printk(KERN_INFO"out sleep\n");
  26.         }
  27.     }
  28.     copy_to_user(buf, rx_buf, rx_buf_count);
  29.     //local_irq_restore(flag);
  30.     return rx_buf_count;
  31. }
复制代码


目前如果有串口数据达到或按下CTRL+C,read函数都会返回,而注释掉return -ERESTARTSYS;
时驱动又无法响应CTRL+C,请问大侠们应该如何改动

论坛徽章:
0
2 [报告]
发表于 2009-09-08 20:28 |只看该作者
如果正常唤醒,那么会返回0,如果是信号中断,那么会返回错误代码-ERESTARTSYS
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP