基于ARM7的usb的实现

 基于ATMELARM7处理器的USB协议实现

0 引言
  USB接口现在几乎成为每一个电子设备的必备接口。本文介绍如何在基于AT91SAM7SE的设备上实现USB协议,使之具有USB传输功能。AT91SAM7SE是ATMEL公司生产的基于ARM7内核的ARM处理器系列,包括AT91SAM7SE512、AT91SAM7SE256、AT91SAM7SE32三种型号,高性能32位RISC结构设计,分别具有512k字节、256k字节、32k字节的集成Flash存储器。论文参考,USB协议。具有丰富的外设资源,包括IO口、SPI、PWM、ADC等。由于该处理器具有UDP(USB DevicePort)接口,因此可以使用该处理器方便的构建USB设备。本文将重点介绍如何在该处理器上实现USB协议。
  1UDP控制器描述
  AT91SAM7SE处理器UDP接口兼容USB2.0,支持8个端口,每个端口的大小及传输类型如表1所示:
  表1 UDP端口描述
  

端点号 缓存大小 支持传输类型
0 64 控制/批量/中断
1 64 批量/同步/中断
2 64 批量/同步/中断
3 64 控制/批量/中断
4 512 批量/同步/中断
5 512 批量/同步/中断
6 64 批量/同步/中断
7 64 批量/同步/中断

UDP每个端口有两个FIFO缓存器,用于存储当前已接收或将发送的数据。FIFO缓存器可以使用其中的一个或两个。两个FIFO缓存同时使用时,一个FIFO可以通过处理器进行读写,另一个同时被UDP外设读写,提高了数据传输的效率。对于同步传输端点,必须使用双FIFO缓存。
  UDP端口对外提供两个USB引脚DP和DM,和USB连接器的连接可参考图1。
  
  图1 USB接口连接图
  2 软件设计
  2.1 软件结构
  为了能够合理的进行USB协议的实现,我们按照图2所示框架进行USB协议的分层设计:
  图2 USB协议实现框架
  硬件层用来实现底层USB控制器的操作。USB API相对于硬件独立,提供了标准的USB数据结构以及方法函数。USB类驱动提供最顶层的USB方法。应用程序层主要用来实现设备功能。下面具体分析实现图2结构所用的一些结构体和函数,对关键结构和函数给出部分代码:
  (1)硬件层,主要实现对USB控制器操作函数。函数针对具体的AT91SAM7SE芯片UDP端口设计,包括使能/禁止D+上拉电阻、使能/禁止UDP收发器、端点FIFO缓存读写、端点中断控制等。一个UDP控制器可用名为UdpController的结构来描述:
  typedef struct _UdpController
  {
  void *pInterface; //UDP控制器地址
  int dID; //UDP外设ID
  int dPmc; //UDP对应时钟管理ID
  } UdpController;
  (2)USB API层,该层提供了USB协议操作的一些方法: USB_Attach连接操作,USB设备通过检测+5V电源线来判断和主设备的连接与断开;USB_SetAddress地址设置,接收主机分配的唯一地址,使设备进入地址状态;USB_SetConfiguration配置操作,主机通过标准的USB请求命令获取设备的配置描述符,并对设备进行配置,使USB设备进入配置状态。
  在API层定义了一个传输结构,用来描述每个端点的每一次传输,定义如下:
  typedef struct _Transfer
  {
  Char *pData; //指向数据指针
  int buffered; //FIFO中的字节数
  int transferred; //已经发送(接收)的字节数
  int remaining; //剩余的字节数
  CallbackfCallback; //回调函数
  void *pArgument; //回调函数参数
  } Transfer;
  该层同时定义了对通信端点的描述,用结构体UsbEndPointsState描述:
  typedef struct _UsbEndpointState
  {
  int wMaxPacketSize; //端点最大包
  int dNumFIFO; //使用的FIFO索引
  intState; //端点状态
  Transfer transfer; //端点对应的传输
  }UsbEndpointState;
  在该层中,使用UsbEndpointState结构构成一个端点列表,该列表指针存储在USB类驱动层。
  (3)USB类驱动层。论文参考,USB协议。论文参考,USB协议。该层位于USB设计框架的最高层。定义了标准的USB请求结构,由设备描述符、配置描述符、接口描述符、端点描述符组成。这些结构体的实现可参考USB协议规范,在此不做描述。论文参考,USB协议。在该层定义一个总体的USB设备驱动类,其结构如下:
  typedef struct_UsbDeviceDriver;
  {
  UdpController*pUdpCtrl;//UDP控制器
  UsbEndpointState*pEndpts;//端点状态列表
  UsbStandardRequest *pStandardRequeat; 
  / /最新收到标准请求包
  Int DeviceState; //设备状态
  int nCurCfgNum; //对应配置
  }UsbDeviceDriver;
  在USB通信中,每一次读写操作的状态都包含在UsbDeviceDriver结构中,读写操作函数以该结构作为输入。
  2.2 读写流程
  对于一次读写操作,要确定使用的端口号,数据缓存指针,读写完毕的回调函数。读写函数简介如下:
  char USB_Read(
  UsbDeviceDriver *pUsbDriver, //USB类驱动
  unsigned char nEpIdx, //使用端点索引
  void*pData,//数据存储地址
  unsigned int dLength,//数据长度
  Callback fCallback, //完成时的回调函数
  void *pArgument); //回调函数参数
  在函数内部首先通过端点索引从pUsbDriver指向的类驱动中获得对应端点的描述结构体UsbEndpointState,把数据传输信息写到该结构体的Transfer中。最后调用硬件层中的UDP控制器函数,开启相应端口中断,等待主机数据的发送。对于写操作具有和读操作一样的函数输入参数,不同的是最后对硬件层的UDP控制器操作为写FIFO缓存。读操作流程如图3所示。在读写操作函数中,要初始化端点对应的Transfer结构数据。以传输100个字节数据为例,字节数据放入data[100]数组中。使用端口2进行传输。则端口2 的UsbEndpointState结构中对应的Transfer结构初始化如下:
  pTransfer->pData = data;
  pTransfer->remaining = 100;
  pTransfer->buffered = 0;
  pTransfer->transferred = 0;
  每完成一次端点包的传输pTransfer->remaining相应减少,pTransfer->transferred相应增加。pTransfer->buffered中的数据为在端点FIFO中还未读入或还未发送的字节数。
  
  图3 USB读写流程图
  读写流程完成后,整个USB协议层就可以进行读写了,此时可以在应用程序层上根据具体的应用编写自己的通信协议。
  2.3. USB验证
  要想使USB设备和主机进行通信,在主机端还要有USB设备的驱动程序,对于驱动程序的设计本文不做论述。将USB设备插入主机,若在主机管理器中能识别该USB设备,说明该USB设备能正常枚举。论文参考,USB协议。作者使用该处理器实现一个矢量网络分析仪中的电子校准件设备,插入主机后,设备管理器中显示如图4显示。
  
  图4 USB设备识别例图

你可能感兴趣的:(ARM)