tm32 usb host mass storage 主机驱动例程分析:(原创)
在usbh_core.c中有一个函数USBH_Process(),这个函数很重要,main()函数每循环一次,它就执行一次,
它处理所有USB内核状态的变化,
typedef enum {
HOST_IDLE =0,
HOST_DEV_ATTACHED,
HOST_DEV_DISCONNECTED,
HOST_DETECT_DEVICE_SPEED,
HOST_ENUMERATION,
HOST_CLASS_REQUEST,
HOST_CLASS,
HOST_CTRL_XFER,
HOST_USR_INPUT,
HOST_SUSPENDED,
HOST_ERROR_STATE
}HOST_State;
根据这个当前状态(phost->gState)处于以上哪个状态的不同,做出不同的处理过程。其中最重要的要属这两个状态:HOST_ENUMERATION,,HOST_CLASS。
HOST_ENUMERATION状态,不言而喻,这就是大名鼎鼎的枚举状态,经过空闲,连接状态后面就要对设备进行枚举了,枚举过程其实也是对状态机的处理过程,用
的是这个USBH_HandleEnum(pdev , phost)函数,也在在usbh_core.c中,因为枚举过程也是USB过程的核心过程。枚举过程根据时间先后顺序依次经过
typedef enum {
ENUM_IDLE = 0,
ENUM_GET_FULL_DEV_DESC,
ENUM_SET_ADDR,
ENUM_GET_CFG_DESC,
ENUM_GET_FULL_CFG_DESC,
ENUM_GET_MFC_STRING_DESC,
ENUM_GET_PRODUCT_STRING_DESC,
ENUM_GET_SERIALNUM_STRING_DESC,
ENUM_SET_CONFIGURATION,
ENUM_DEV_CONFIGURED
} ENUM_State;
以上几个过程,如果都得到正确的处理,且返回值也为OK的话,枚举过程结束,此时已经获得了USB设备的基本信息。比如:设备描述符,配置描述符等等。下一
步就该加载设备驱动了,根据枚举过程获得到的设备类型和ID号,比如大容量存储设备,HID,VIDIO等,选择不同的设备驱动加载,并初始化。这一步是在USBH_Process()处
理函数在的HOST_USR_INPUT状态下执行的。正确执行后进入下一个状态HOST_CLASS_REQUEST,
在这个HOST_CLASS_REQUEST状态,主要是初始化设备驱动类的状态机(host class state machine),为一步做准备。
下面就到了另一个重要的处理函数,status = phost->class_cb->Machine(pdev, phost);其实这个函数最终会调用USBH_MSC_Handle(),这个函数在
usbh_msc_core.c中,usbh_msc_core.c顾名思义,这就是USB主机端mass storage类的驱动程序,核心文件,
USBH_MSC_Handle()函数根据当前所处的状态,作出相应的处理。
typedef enum
{
USBH_MSC_BOT_INIT_STATE = 0,
USBH_MSC_BOT_RESET,
USBH_MSC_GET_MAX_LUN,
USBH_MSC_TEST_UNIT_READY,
USBH_MSC_READ_CAPACITY10,
USBH_MSC_MODE_SENSE6,
USBH_MSC_REQUEST_SENSE,
USBH_MSC_BOT_USB_TRANSFERS,
USBH_MSC_DEFAULT_APPLI_STATE,
USBH_MSC_CTRL_ERROR_STATE,
USBH_MSC_UNRECOVERED_STATE
}
MSCState;
USBH_MSC_DEFAULT_APPLI_STATE, 这个状态就是我们编写的应用程序将要执行的状态。最为不爽的是,连STM提供的上层应用程序也是按状态机的方式编写的。
USBH_USR_MSC_Application(),就是STM提供的应用程序,在usbh_usr.c中,分为4个状态:
#define USH_USR_FS_INIT 0
#define USH_USR_FS_READLIST 1
#define USH_USR_FS_WRITEFILE 2
#define USH_USR_FS_DRAW 3
如果我要编写我自己的应用程序的话,应该就是修改这个函数吧,
|