微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > 基于Linux的USB主/从设备之间的三种通信方式

基于Linux的USB主/从设备之间的三种通信方式

时间:10-26 来源:互联网 点击:

入式应用将其USB主机当作一个远程存储设备。除此以外,采用这种方法之后,设备还可以具备存储转发(store-and-forward)的功能,因而能够在与USB主机的连接建立之前对来自嵌入式应用的数据流进行缓冲。

在基于StrongARM的Linux设备中,内核代码用于管理芯片所携带的USB设备控制器外设,通过调用函数sa1100_usb_open ()来初始化。在初始化之后,内核模块还会调用函数sa1100_usb_get_descriptor_ptr() 和sa1100_usb_set_string_descriptor()来设置在设备查询期间传送给USB主机的描述符,其中包含设备的数字厂商号和产品标识符,以及可以让主机用来识别设备的字符串,甚至还有一个序列号域,以便主机可以唯一地识别一个连接在USB接口上的设备,或者在同种型号的多个设备中进行区分。

设备查询过程是由USB设备控制器驱动的,并且一旦和USB主机连上之后会自动执行,所以内核模块必须在USB通信开始之前设置好每个设备的描述符。当准备工作就绪之后,USB设备模块就会调用函数sa1100_usb_start()来通知内核接收主机发来的USB连接请求。如果设备模块在连上USB 主机之前调用了函数sa1100_set_configured_callback(),那么接着内核模块就会在查询过程结束时调用回调函数。回调函数很适合用来在设备上发出警告或给出一些形象的暗示,说明连接已经建立。

如果不再需要进行USB通信,那么设备的内核模块就会先调用函数sa1100_usb_stop(),然后调用sa1100_usb_close(),来关闭SA1100上的USB控制器。

StrongARM 的 USB控制器支持bulk-in和bulk-out两种数据传送方式。当接收来自USB主机的数据包时,内核模块会调用sa1100_usb_recv (),将一个数据缓冲区的地址和一个回调函数送给它。然后内核中的USB设备控制代码会从主机取回一个bulk-out数据包,将其内容存入制定的缓冲区,接着调用回调函数。

下一步,回调函数从接收缓冲区中提取出数据,将其存放到其他地方,或者将缓冲区空间添加到一个队列中,然后分配一个新的缓冲区来接收下一个数据包。然后,如果还有数据需要接收,那么回调函数会重新调用sa1100_usb_recv(),准备接收另一个数据包。

向USB 主机发送数据的过程与此类似。内核模块收集了一帧数据之后,将数据的存放地址、数据长度和回调函数的地址送给sa1100_usb_send()函数。接着,在数据传送结束之后,内核模块会调用回调函数。

在www.embedded.com/code.htm (arch/arm/mach-sa1100/usb-char.c)可以找到一个叫做usb-char的模块,这是一个很好的设备端SA1110 Linux USB模块的例子。该模块将USB设备与USB 主机之间的连接变成一种高速串行链接。此外, usb-eth( arch/arm/mach-sa1100/usb-eth.c)模块也是个不错的例子,该模块将USB变成了一种虚拟的以太型网络。后面会深入探讨这两种模块。

2. USB主机端通信过程

有些很好的主机端USB驱动程序的例子是随主流Linux操作系统的发布而提供的,位于The Linux Kernel Archives (kernel.org)发布的原始内核源代码中。其中,Handspring Visor 模块(drivers/usb/serial/visor.c)是一个编写得更清晰,也更易理解的模块,它同时也是USB 主机端模块(drivers/usb/usb-skeleton.c)的模板。

利用USB实现高速串行通信

1. USB设备端通信过程

为了达到最实用的效果,我们可以将USB总线简单地看作一个高速串口,然后,在一些嵌入式设备和应用中,我们就可以用USB接口来模拟串口。 StrongARM处理器的Linux内核就提供了一个名为usb-char的USB设备驱动程序,它所完成的恰好就是用USB模拟串口的功能。

当需要与USB 主机通信时,Linux操作系统中的USB设备应用只是简单地打开一个与其usb-char设备节点的连接(连接类型为字符型,major number 为10, minor 为240),然后就开始读写数据。在与USB 主机的连接建立之前,read()和write()操作均返回一个错误信息。一旦连接建立好,并且设备查询完成之后,USB接口就开始象一个点对点的串口一样与主机进行通信。

这种进行USB数据传送的方法非常简单有效,因而usb-char设备模块发布之后一直很受欢迎。而且,该模块还为通过其他方法进行USB通信提供了一个参考。  

在usb -char中,真正的操作开始于usbc_open()函数,列表1给出了函数的一部分代码。笔者由于临时的兴趣,对该代码做了一点修改,取消了错误和超时句柄。在此向代码的原作者Brad Parker、Nicolas Pitre 和Ward Willats致歉。

twiddle_descriptors()函数用于设置设备的USB描述符。在描述符设置好之后,我们就可以开始进行设备查询,并从USB 主机接收一帧数据。k

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top