本篇主要介绍U盘模块,必须是有USB-HOST功能的芯片才可以进行U盘数据的读写,在硬件设计时已经提到了,本例用到的芯片属于STM32F105系列是带有OTG功能的,103系列的芯片只能作为从设备。
STM32F105 USB接口主要特点
- USB2.0协议,OTG1.3协议
- 可作为USB主机、USB设备、OTG设备(A类/B类)使用
- 可使用内部FS PHY做FS通信
从官方下载USB例程
我们需要做U盘数据的读写,USB做主机即HOST功能。如上图在官方例程的libraries目录中。其中的USB OTG是USB Device和USB Host的基础。在实际使用中,USB OTG是USB Device和USB Host的底层驱动。本例需要移植OTG+HOST。(现在可以不需要移植了,通过STM32CubeMX直接由图形界面简单配置下,生成初始化代码,并对外设做了进一步的抽象,让开发人员更只专注应用的开发。搞嵌入式还是要了解底层驱动,对吧?)
驱动移植
移植文件如下图
OTG和HOST驱动文件简要说明
文件 | 模块 | 说明 |
---|---|---|
usb_core.c/h | Common | 该文件包含硬件抽象层和USB通信操作 |
usb_hcd.c/h | Host | 该文件包含USB_HOST_Library访问核心时使用的Host接口层 |
usb_hcd_int.c/h | Host | 该文件包含Host模式所使用的中断子程序 |
usbh_core.c/h | Host core | 该文件包含处理所有USB通信和状态机的功能 |
usbh_stdreq.c/h | Host core | 该文件实现设备枚举的标准请求 |
usbh_ioreq.c/h | Host core | 该文件处理USB事务的生成 |
usbh_hcs.c/h | Host core | 该文件处理主机通道分配和触发进程 |
本例中需要实现U盘读写需要MSC驱动程序,MSC:(Mass storage class)大容量存储类驱动程序用于支持通用USB闪存驱动程序,使用BOT“Bulk-Only Transport”协议和透明SCSI命令集。
MSC驱动文件介绍
文件 | 说明 |
---|---|
usbh_msc_core.c /.h | MSC核心状态机实现 |
usbh_msc_bot.c /.h | BOT(Bulk-Only Transport)协议实现 |
usbh_msc_scsi.c /.h | SCSI命令的实现 |
usbh_msc_fatfs.c/.h | 用于与Fatfs文件系统进行文件访问操作接口的功能。*其就是Fatfs中diskio.c/.h的实现 |
用户文件介绍
文件 | 说明 |
---|---|
usb_bsp.c | 与芯片的接口实现文件 |
usbh_usr.c/h | 用户回调函数 |
通常所有的用户代码均在以上文件做修改即可,只有少数特殊处理会设计到驱动程序源码的修改。在配置好后,一般来说,所有修改均在usbh_usr.h/.c中。
配置文件介绍
文件 | 说明 |
---|---|
usb_conf.h | USB OTG底层驱动配置 |
usbh_usr.c/h | USB HOST底层驱动配置 |
- usb_conf.h
#ifndef USE_USB_OTG_FS
//#define USE_USB_OTG_FS
#endif /* USE_USB_OTG_FS */
#ifdef USE_USB_OTG_FS
#define USB_OTG_FS_CORE //使能内核的全速模式
#endif
#ifndef USE_USB_OTG_HS
//#define USE_USB_OTG_HS
#endif /* USE_USB_OTG_HS */
#ifndef USE_ULPI_PHY
//#define USE_ULPI_PHY
#endif /* USE_ULPI_PHY */
#ifndef USE_EMBEDDED_PHY
//#define USE_EMBEDDED_PHY
#endif /* USE_EMBEDDED_PHY */
#ifdef USE_USB_OTG_HS
#define USB_OTG_HS_CORE //使能内核的高速模式
#endif
/****************** USB OTG HS CONFIGURATION **********************************/
#ifdef USB_OTG_HS_CORE
#define RX_FIFO_HS_SIZE 512 //设置高速模式下接收的FIFO的大小
#define TXH_NP_HS_FIFOSIZ 256 //设置高速模式下,作为USB Host时,非周期性发送的FIFO的大小
#define TXH_P_HS_FIFOSIZ 256 //设置高速模式下,作为USB Host时,周期性发送的FIFO的大小
#ifdef USE_ULPI_PHY
#define USB_OTG_ULPI_PHY_ENABLED
#endif
#ifdef USE_EMBEDDED_PHY
#define USB_OTG_EMBEDDED_PHY_ENABLED
#endif
#define USB_OTG_HS_INTERNAL_DMA_ENABLED
#define USB_OTG_EXTERNAL_VBUS_ENABLED
// #define USB_OTG_INTERNAL_VBUS_ENABLED
#endif
/****************** USB OTG FS CONFIGURATION **********************************/
#ifdef USB_OTG_FS_CORE
#define RX_FIFO_FS_SIZE 128 //设置全速模式下接收的FIFO的大小
#define TXH_NP_FS_FIFOSIZ 96 //设置全速模式下,作为USB Host时,非周期性发送的FIFO的大小
#define TXH_P_FS_FIFOSIZ 96 //设置全速模式下,作为USB Host时,周期性发送的FIFO的大小
#endif
/****************** USB OTG MODE CONFIGURATION ********************************/
#define USE_HOST_MODE //HOST 模式
//#define USE_DEVICE_MODE
//#define USE_OTG_MODE
- usbh_config.h
#define USBH_MAX_NUM_ENDPOINTS 2 //支持端点的最大数量 1 bulk IN + 1 bulk Out
#define USBH_MAX_NUM_INTERFACES 2 //支持接口的最大数量
#ifdef USE_USB_OTG_FS
#define USBH_MSC_MPS_SIZE 0x40
#else
#define USBH_MSC_MPS_SIZE 0x200
#endif
USB处理状态机
下面介绍USB处理的俩个核心状态机。
- 核心状态机过程由USBH_Process函数实现。 应该从应用程序主循环周期性地调用该函数。
/**
* @brief USBH_Process
* USB Host core main state machine process
* @param None
* @retval None
*/
void USBH_Process(USB_OTG_CORE_HANDLE *pdev , USBH_HOST *phost)
{
volatile USBH_Status status = USBH_FAIL;
/* check for Host port events */
if ((HCD_IsDeviceConnected(pdev) == 0)&& (phost->gState != HOST_IDLE))
{
if(phost->gState != HOST_DEV_DISCONNECTED)
{
phost->gState = HOST_DEV_DISCONNECTED;
}
}
switch (phost->gState)
{
case HOST_IDLE ://在主机初始化之后,内核在这种状态下开始轮询USB设备连接。 当检测到设备断开连接事件时以及未发生错误时也会进入此状态。
if (HCD_IsDeviceConnected(pdev))
{
phost->gState = HOST_DEV_ATTACHED;
USB_OTG_BSP_mDelay(100);
}
break;
case HOST_DEV_ATTACHED ://当一个设备连接时,核心进入这个状态。 当一个设备被检测到时,状态机转到HOST_ENUMERATION状态。
phost->usr_cb->DeviceAttached