免费注册 查看新帖 |

Chinaunix

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

usb转串口的疑惑 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2012-05-10 10:34 |只看该作者 |倒序浏览
大家好,这几天做一个linux-2.6.9环境下通信的小项目。硬件是R8610 x86结构,就是一个嵌入式硬件平台。
        这里的串口用的是pl2303 usb转串口。我把这个串口通过串口线接到pc上的com1.这样,测试的时候出现问题啦!!如下面的代码,连续往串口发送3次数据,第一次丢失,这个丢失有条件:在while循环中第一次没有任何问题,第一次执行close以后,接下来的for循环中,第一次write数据没有发出去。
当然这个问题也可以通过定义自己的通信协议来解决。但是如果大家有意能解决的话,不是很好吗,或者谁以前遇到过一样的问题,大家可以共享一下。反正目前我还没有解决掉,惭愧啊。
        while(1)
        {
                serial_fd = open(SERIAL_NAME, O_RDWR | O_NONBLOCK);
                if(serial_fd < 0){
                        perror("open failed:\n");
                        printf("open %s failed!\n", SERIAL_NAME);
                        return;
                }
        //        printf("open serial port ttyusb3 success!! serial_fd = %d\n", serial_fd);
                set_usb_uart_speed(serial_fd, USB_UART_SPEED);
                if(set_usb_uart_para(serial_fd,8,1,'N') < 0)  
                {
                        printf("Set Parity Error\n");
                        return;
                }
                sleep(3);
                memset(&recv_buf, 0, 100);
                memset(&send_buf, 0, 100);
                for(i = 0; i < 3; i += 1)
                {
                        memcpy(send_buf, "abcde", 5);
                        len = commu_write(serial_fd, send_buf, 5);
                        if(len != 5)
                                printf("send to serial_fd failed\n");
                        sleep(1);
                }
                printf("send data over,how many you receice???\n");
                sleep(3);
                close(serial_fd);
        }       
        commu_read是read的封装函数,
        数据发送到串口的时候,第一次pc上的com1口收不到数据。commu_write的返回值也确实是5,从应用层来看,数据读和写都没有错误。但是pc上的com1口确实没有收到数据。接下来的第2次和第3次发送都正常。
       在我第一阶段的测试当中,各种驱动编译进内核,有下面几个重要点:
       1   设备启动以后,第一次执行for循环没有问题,pc能接收3次发出来的数据。
       2   以后的for循环里,第一次pc没有接收到数据,第一次以后能接收到数据,说明硬件没有问题,我用示波器查看com口的引脚,第一次确实没有发出来,第一次以后确实发出来了。
       3   在for循环里面,第一次发送“abcde”,第二次内容改成“123456789”,pc的com1口直接显示“123456789”,说明驱动缓冲区中把“abcde”刷了,没有驻留。
       4   并且只要设备不重启这种状况就一直存在, 哪怕应用收到“ctrl + C”退出,再次执行这个应用,则每次for循环都丢失第一次发送的内容。      
      

         根据以上的结论。我把问题定位到驱动模块中。因为只要设备重启,并且不执行close的话,执行都是正常的。只要执行close,以后的就会丢失第一次write的是数据。所以先确定pl2303驱动是否收到应用送下来的数据
在pl2303驱动中的pl2303_write函数中:
            static int pl2303_write (struct usb_serial_port *port, int from_user,  const unsigned char *buf, int count)
           {
                  int result;
                  printk("LF:%s - port %d, %d bytes\n", __FUNCTION__, port->number, count);//add by lifeng on 2012-4-23

                  if (!count)
                          return count;

                  if (port->write_urb->status == -EINPROGRESS)
                         return 0;

                  printk("LF:count = %d, port->bulk_out_size = %d,from_user = %d\n", count, port->bulk_out_size, from_user);//add by lifeng on 2012-4-23
                  count = (count > port->bulk_out_size) ? port->bulk_out_size : count;
                  if (from_user)
                  {
                        if (copy_from_user (port->write_urb->transfer_buffer, buf, count))
                             return -EFAULT;
                  }
                  else
                 {
                           memcpy (port->write_urb->transfer_buffer, buf, count);
                 }
                  printk("LF: write buf :%s\n", port->write_urb->transfer_buffer);
        
                 usb_serial_debug_data(debug, &port->dev, __FUNCTION__, count, port->write_urb->transfer_buffer);

                 port->write_urb->transfer_buffer_length = count;
                 port->write_urb->dev = port->serial->dev;
                 result = usb_submit_urb (port->write_urb, GFP_ATOMIC);
                 if (result)
                           dev_err(&port->dev, "%s - failed submitting write urb, error %d\n", __FUNCTION__, result);
                else
                           result = count;

                printk("LF:result = %d\n", result);//add by lifeng on 2012-4-23
                return result;
         }
         打印write_urb->transfer_buffer和write_urb->transfer_buffer_length分别是“abcde”和5,也是正确的,usb_submit_urb函数返回值是0,也是正确的。也正常的调用了write_urb的写回调函数。
         说明pl2303驱动没有问题,只能往根上追。
         第二阶段测试: usb转串口,这里涉及到的驱动有,ohci-hcd.ko, usbserial.ko, pl2303.ko。现在把这三个都编译成模块的形式然后insmod。
         下面是对驱动部分操作的流程:
         1  等到出现上面所说的问题的时候,“ctrl + C”退出应用。然后rmmod pl2303和usbserial两个模块,然后再insmod这两个模块,再然后执行应用程序,第一次进入for循环第一次就丢失,和把驱动编译进内核,应用重新执行效果一样。所以问题应该和这两个模块没关系。可以排除是这两个模块的问题。
         2  等到出现上面所说的问题的时候,“ctrl + C”退出应用,然后rmmod pl2303, usbserial,ohci-hcd三个模块,然后再insmod上面3个模块,这种情况下,执行应用和驱动都编译进内核设备重启现象是一样的。for循环第一次正常执行,后面的都丢失第一次write的数据
        所以,可以下结论,问题出现在ohci-hcd.ko这个模块。

        进入内核,看了一下这个模块,我的个妈呀,本来对usb就不感冒,看了看这部分,文件都不过,也就2,3个内容分也不太多,但是理解那是相当难啊。
        接下来的工作就是这部分代码了,不知道谁有这方面经验啊!!!!!!
        同志们,赶紧来帮忙啊!!!!   

您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP