usb转串口的疑惑
大家好,这几天做一个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个内容分也不太多,但是理解那是相当难啊。
接下来的工作就是这部分代码了,不知道谁有这方面经验啊!!!!!!
同志们,赶紧来帮忙啊!!!!
页:
[1]