原创 USB的“JoyStickMouse”例程分析01

2010-4-16 10:53 4943 8 9 分类: MCU/ 嵌入式

<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />

 

 


一、USB的“JoyStickMouse”例程结构分析


1、例程的结构


1)底层结构


包括5个文件:usb_core.cUSB总线数据处理的核心文件),usb_init.cusb_int.c(用于端点数据输入输入中断处理),usb_mem.c(用于缓冲区操作),usb_regs.c(用于寄存器操作)。它们都包含了头文件“usb_lib.h”。在这个头文件中,又有以下定义:


#include "usb_type.h"


#include "usb_regs.h"


#include "usb_def.h"


#include "usb_core.h"


#include "usb_init.h"


#include "usb_mem.h"


#include "usb_int.h"


usb_lib.h中又包含了七个头文件,其中usb_type.h中主要是用typedefstm32支持的数据类型取一些新的名称。usb_def.h中主要是定义一些相关的数据类型。


还有一个未包含在usb_lib.h中的头文件,usb_conf.h用于USB设备的配置


 


2)上层结构


上层结构总共5个文件:hw_config.c(用于USB硬件配置)、usb_pwr.c(用于USB连接、断开操作)、usb_istr.c(直接处理USB中断)、usb_prop.c(用于上层协议处理,比如HID协议,大容量存储设备协议)、usb_desc.c(具体设备的相关描述符定义和处理)。


 


可见,STUSB操作库结构十分清晰明了,我先不准备直接阅读源代码。而是先利用MDK的软件模拟器仿真执行,先了解一下设备初始化的流程。


 


2、设备初始化所做的工作


1Set_System(void)


这个是main函数中首先调用的函数,它位于hw_config.c文件中。它的主要功能是初始化时钟系统、使能相关的外围设备电源


配置了JoyStickMouse所用到的5个按键,并且配置了两个EXTI中断,一个是用于把USB从挂起模式唤醒,还有一个用途未知。


 


2USB_Interrupts_Config();


这个是main函数中调用的第二个函数,它也位于hw_config.c文件中。主要功能是配置USB所用到的中断


跟踪到代码中,主要设配置了USB低优先级中断和唤醒中断,又有一个EXTI中断功能未知。


 


3Set_USBClock()


这个是main函数中调用的第三个函数,它也位于hw_config.c文件中。它的功能是配置和使能USB时钟


 


4USB_Init(void)


这个是main函数中调用的第四个函数,它也位于usb_init.c文件中。它初始化了三个全局指针,指向DEVICE_INFOUSER_STANDARD_REQUESTSDEVICE_PROP结构体。


后面两个是函数指针结构体,里面都是USB请求实现、功能实现的函数指针。


void USB_Init(void)


{


  pInformation = &Device_Info;


  pInformation->ControlState = 2;


  pProperty = &Device_Property;


  pUser_Standard_Requests = &User_Standard_Requests;


  /* Initialize devices one by one */


  pProperty->Init();


}


这三个结构体都是与具体设备枚举和功能实现相关的,定义在usb_prop.cusb_desc.c文件中。


DEVICE_PROP Device_Property =


  {


    Joystick_init,


    Joystick_Reset,


    Joystick_Status_In,


    Joystick_Status_Out,


    Joystick_Data_Setup,


    Joystick_NoData_Setup,


    Joystick_Get_Interface_Setting,


    Joystick_GetDeviceDescriptor,


    Joystick_GetConfigDescriptor,


    Joystick_GetStringDescriptor,


    0,


    0x40 /*MAX PACKET SIZE*/


  };


USER_STANDARD_REQUESTS User_Standard_Requests =


  {


    Joystick_GetConfiguration,


    Joystick_SetConfiguration,


    Joystick_GetInterface,


    Joystick_SetInterface,


    Joystick_GetStatus,


    Joystick_ClearFeature,


    Joystick_SetEndPointFeature,


    Joystick_SetDeviceFeature,


    Joystick_SetDeviceAddress


  };


Usb_init()函数调用pProperty->Init()实质上就是Joystick_init)完成设备的初始化。


 


上层程序调用下次函数是常规性的操作。而下层函数(usb_init相对于usb_prop是输入底层操作文件)调用上层文件函数我们称之为回调。


回调函数的意义在于同一种操作模式、提供不同的回调函数则可以实现不同的功能。Windows中处理消息,好像也用到了这种模式。


回调函数的实现方法是函数指针数组。这是指针的高级应用。


 


这是函数的代码:


void Joystick_init(void)


{/* Update the serial number string descriptor with the data from the unique  ID*/


  Get_SerialNum();  //获取设备序列号,转变为unicode字符串


 


  pInformation->Current_Configuration = 0;


  /* Connect the device */


  PowerOn();  //连接USB设备,实质是能让主机检测到了。


  /* USB interrupts initialization */


  _SetISTR(0);               /* clear pending interrupts */


  wInterrupt_Mask = IMR_MSK;


  _SetCNTR(wInterrupt_Mask); /* set interrupts mask */


 


  bDeviceState = UNCONNECTED;


}


实质上代码执行到这里开发板已经可以响应主机发来的数据了。但我还是先把main()函数的代码看完吧。


 


5SysTick_Config();


这个函数调用主要是为程序中用到的精确延时作配置。


 


3、进入主循环


进入主循环的工作就两个:


Joystick_Send(JoyState())


JoyState()用来获取按键的状态。


Joystick_Send(JoyState())用来把按键状态发到主机。当然这里真正的发送工作并不是由该代码完成的。它的工作只是将数据写入IN端点缓冲区,主机的IN令牌包来的时候,SIE负责把它返回给主机。


 


主要代码如下:


  UserToPMABufferCopy(Mouse_Buffer, GetEPTxAddr(ENDP1), 4);  //从用户复制四个字节到端点1缓冲区,控制端点的输入缓冲区。


  SetEPTxValid(ENDP1); /* enable endpoint for transmission */


4、中断处理过程大致理解


1usb_istr()函数中的中断处理简单分析


有用的代码大概以下几段,首先是处理复位的代码,调用设备结构中的复位处理函数。


  wIstr = _GetISTR();


  if (wIstr & ISTR_RESET & wInterrupt_Mask)


  {


    _SetISTR((u16)CLR_RESET); //清复位中断


    Device_Property.Reset();


  }


 


处理唤醒的代码:


  if (wIstr & ISTR_WKUP & wInterrupt_Mask)


  {


    _SetISTR((u16)CLR_WKUP);


    Resume(RESUME_EXTERNAL);


  }


 


处理总线挂起的代码:


  if (wIstr & ISTR_SUSP & wInterrupt_Mask)


  {


    if (fSuspendEnabled) /* check if SUSPEND is possible */


    {


      Suspend();


    }


    else


    {


      /* if not possible then resume after xx ms */


      Resume(RESUME_LATER);


    }


    /* clear of the ISTR bit must be done after setting of CNTR_FSUSP */


    _SetISTR((u16)CLR_SUSP);


  }


处理端点传输完成的代码,这段是最重要的,它调用底层usb_int.c()文件中的CTR_LP()函数来处理端点数据传输完成中断。


  if (wIstr & ISTR_CTR & wInterrupt_Mask)


  {


    CTR_LP(); /* servicing of the endpoint correct transfer interrupt */


  }


 


 

文章评论1条评论)

登录后参与讨论

tengjingshu_112148725 2010-4-16 11:59

博主真是笔耕不辍,支持
相关推荐阅读
nthq2004 2010-05-08 20:04
USB自定义设备驱动02
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />  本来还想编写应用程序测试一下自定...
nthq2004 2010-05-07 21:35
USB自定义设备驱动01
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />  一、USB设备驱动入门1、学习目...
nthq2004 2010-05-04 21:01
智林开发板上实现自定义的USB HID设备
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />  一、自定义HID设备的相关概念1...
nthq2004 2010-05-01 21:58
U盘例程在智林开发板上的移植
 <?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> 一、移植前的准备工作1、有哪些操...
nthq2004 2010-04-30 19:19
U盘实现流程跟踪分析02
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />   二、追踪USB大容量设备的实现...
nthq2004 2010-04-27 21:51
U盘实现流程跟踪分析01
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />   一、追踪USB大容量设备的实现...
我要评论
1
8
关闭 站长推荐上一条 /2 下一条