免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2521 | 回复: 2

[驱动] usb-serial write时候会丢第一个帧,疑惑中。。。 [复制链接]

论坛徽章:
0
发表于 2012-04-27 10:28 |显示全部楼层
大家好,这几天做一个linux-2.6.9环境下通信的小项目。硬件是R8610 x86结构,就是一个嵌入式硬件平台。
        本来感觉很简单,其实就是串口和网口的通信。从socket接受数据,然后传送给串口,或者从串口接受数据送给socket。只是这里的串口试用的是pl2303 usb转串口。整个代码的大体框架是select + read ,read到数据就write到另外的口。我是这样测试的,r8610有一个网口,一个pl2303usb转的串口,这两个口就是我们要通信的接口。我把这个串口通过串口线接到pc上的com1.这样,测试的时候出现问题啦,!!当然这个问题也可以通过定义自己的通信协议来解决。但是如果大家有意能解决的话,不是很好吗,或者谁以前遇到过一样的问题,大家可以共享一下。反正目前我还没有解决掉,惭愧啊。
        retval = select(max_fd, &fds, NULL, NULL,&tv_value);
        if(retval > 0)
        {
                if(FD_ISSET(real_socket_fd, &fds))//socket readable
                {
                        len = commu_read(real_socket_fd, recv_socket_buf, 100);
                        if(len > 0)//read success from socket
                        {
                                socket_err_count = 0;
                                recv_socket_buf[len] = '\0';
                                printf("got data from socket is %s\n", recv_socket_buf);
                                //tcdrain(serial_fd);
                                ret = commu_write(serial_fd, recv_socket_buf, len);//send the received data from socket to serial port
                                if(ret > 0)//send to serial success
                                {
                                        printf("write to serial success, num : %d\n", ret);
                                        serial_err_count = 0;
                                }
                    。。。。。。。
        }
        commu_read和commu_write是read和write的封装函数,
        但是从网络收到数据,然后发送到串口的时候,第一次pc上的com1口经常没有收不到数据。比如,从网络收到串“abcde”,通过看打印出的信息,commu_read确实从socket_fd上读到数据。长度是5,并且commu_write的返回值也确实是5,从应用层来看,数据读和写都没有错误。但是pc上的com1口确实没有收到数据。不管第一次收没收到数据,接下来的接受和发送都正常。
       上面说的第一次是这个意思:我的代码是服务器端,pc是客户端,“第一次发送数据”指客户端连接到服务器上以后第一次发送的数据,这里的数据不是一个字节。
       在我的测试当中,有下面几个重要点:
       1   第一次pc没有接收到数据,第一次以后能接收到数据,说明硬件没有问题,我怕用示波器查看com口的引脚,第一次确实没有发出来,第一次以后确实发出来了。
       2   我第一次发送“abcde”,没有成功,接下来继续发送,把内容改成“123456789”,pc的com1口直接显示“123456789”,说明驱动缓冲区中把“abcde”刷了,没有驻留。
       3   在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的写回调函数。

         那么貌似问题出在linux这个版本usbcore的写队列对第一个数据的处理上,对usbcore这一块目前还不是很了解,正在研究中。。。
         谁在这方面有过类似经验,可以提供一些帮助,可以尽快解决这问题,
         另外老板着急要货,目前已经通过定义通信协议把这个问题绕过,但是我还是想弄的明白点,又怕新任务安排下来,把这个问题忘了,所以在这里留下上面内容,

论坛徽章:
0
发表于 2012-04-27 10:30 |显示全部楼层
刚刚发表,顺便说明一下,头像是俺闺女

论坛徽章:
0
发表于 2012-05-07 09:46 |显示全部楼层
今天无意中,又测试出点进展:
open以后,如果不close,是不会发生write丢失数据问题。如果open以后,然后因为有很长时间没有数据传输,所以就close,接下来等到有需求的时候再open, 接下来的第一次write就会失败,而后继的传输都没有问题,貌似驱动的第一次初始化很正确,但是,应用close以后,再open就不能正常处理。
但是usb这里涉及的东西,有芯片pl2303驱动,ehci驱动, hub驱动, usb-core驱动,scsi驱动,实在不好定位,不知道谁有好点的经验啊
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP