一、介绍
-
USB,即通用串行总线(Universal Serial Bus),包括 USB 协议和 USB 硬件两个方面,支持热插拔功能
-
USB2.0 使用四根线:VCC(5V)、GND、D+(3.3V)和 D-(3.3V) (注:五线模式多了一个DI 脚用于支持 OTG 模式,
OTG 为 USB 主机+USB 设备双重角色
) -
在 USB 主机上,D-和 D+都接 15K 的电阻到地,在没有设备接入的时候,D+、D-均是低电平。在 USB 设备中,如果是高速设备,则在D+上接一个1.5K的电阻到 3.3V,如果是低速设备,则在 D-上接一2023-07-06 18:05:27 星期四个1.5K 的电阻到 3.3V。当设备接入主机时,主机就可以判断是否有设备接入,并能判断设备是高速设备还是低速设备。
-
USB 规范四种速度模式:低速(Low-Speed)、全速(Full-Speed)、高速(Hi-Speed)和超高(SuperSpeedUSB)。
USB 系统组成
-
USB 系统主要包括三个部分:控制器(Host Controller)、集线器 (Hub) 和 USB 设备
。 -
控制器(Host Controller), USB主机有一个或多个控制器,负责
执行由控制器驱动程序发出的命令
。 -
控制器驱动程序(Host Controller Driver)在控制器与 USB 设备之间建立通信信道。
-
集线器(Hub)连接到 USB 主机的根集线器,用于拓展主机可访问的 USB 设备的数量。
-
USB 设备(USB Device)是受主机控制的设备。常用的如 U 盘,USB 鼠标这类
USB 通讯
USB 系统通过“管道”进行通讯,有“控制管道”和“数据管道”两种,“控制管道”是双向的,“数据管道”则是单向的
USB主机
-
检测和断开总是由主机发起
-
USB 主机与设备进行连接时交换信息的过程叫
“USB 枚举”
-
枚举过程
:主机需要分配设备地址、读取描述符(作为提供有关设备信息的数据结构),并分配和加载设备驱动程序(主机操作) -
从机提供相应的描述符使主机知悉如何操作此设备(从机操作)
-
枚举过程需要数秒时间,枚举过程完成后才可以进行数据传输。
-
数据传输规定的三种类型:
IN/读取/上行数据传输、OUT/写入/下行数据传输、控制数据传输。
- IN = 读取 = 上行
- OUT = 写入 = 下行
端点
-
USB 通过设备 端点 寻址,在主机和设备间实现信息交流
-
控制端点或端点 0: 枚举发生前专用于
与设备进行通信的端点
。有端点 0 IN 和端点 0 OUT 两个不同的端点,每一个 USB 设备都需要支持端点 0。端点 0 不需要使用独立的描述符。 -
特定设备所支持的端点数量将由各自的设计要求决定。简单的设计(如鼠标)可能仅要一个 IN 端点。复杂的设计可能需要多个数据端点。
-
USB 规定数据 4 种传输方式:控制传输(Control Transfer)、中断传输(Interrupt Transfer)、批量传输或叫块传输(Bulk Transfer)、实时传输或叫同步传输(Isochronous Transfer ),都是通过管道进行传输。
二、STM32F407下USB介绍
-
STM32F407 系列芯片有 2 个 USB OTG,高速 USB(USB OTG HS);全速 USB(USB OTG FS),高速 USB(HS)需要外扩高速 PHY 芯片实现
-
STM32F407 的 USB OTG FS 主要特性:通用特性、主机模式特性和从机模式特性
-
STM32F407 的 USB OTG FS 是双角色设备 (DRD) 控制器,同时支持从机功能和主机功能,或为“仅主机”模式或“仅从机” 模式
-
主机模式下,支持全速(FS,12 Mb/s)和低速(LS,1.5 Mb/s)收发器。从机模式下,仅支持全速(FS,12 Mb/s)收发器
- ST 提供了一个完整的 USB OTG 驱动库(包括主机和设备),全部是以 HAL 库的形式提供,相关参考例程在 en.stm32cubef4_v1-26-0_v1.26.0.zip 可以找到
时钟
- STM32F407通过
AHB总线访问
(AHB频率必须大14.2Mhz),USB OTG 的内核时钟必须是 48Mhz
,来自时钟树里面的 PLL48CK
(和 SDIO 共用)。
三、 demo移植
- USB OTG 库
- USB OTG 例程
- USB OTG 库的使用和例程说明,参考 ST 官方提供的:UM1734(从机)和 UM1720(主机)两个文档,详细介绍USB OTG库的各个组成部分以及所提供的例程使用方法
demo移植步骤
-
相关代码
-
步骤如下:
-
拷贝官方 USB 驱动库相关代码到自建的工程文件夹下。STM32Cube_FW_F4_V1.26.0→Middlewares→ST 文件夹下的:
STM32_USB_Device_Library、STM32_USB_HOST_Library
两个文件夹及源码拷贝到该文夹下面 -
新建 USB_APP 文件夹用于存放 MSC 实现相关代码。STM32Cube_FW_F4_V1.26.0→Projects→STM324xG_EVAL→Applications→USB_Device→MSC_Standalone→Src 下的部分代码:
usbd_conf.c、usbd_storage.c 和 usbd_desc.c
等 3 个.c 文件 -
继续:STM32Cube_FW_F4_V1.26.0 → Projects → STM324xG_EVAL → Applications → USB_Device→MSC_Standalone→Inc 下面的:
usbd_conf.h、usbd_storage.h 和 usbd_desc.h
等三个文件到 USB_APP 文件夹下
-
在Keil工程的基础上新建分组添加相关代码到工程中
-
-
代码修改
-
Keil配置修改
- 使用 USB OTG FS,必须在 MDK 编译器的全局宏定义里面,添加宏定义:
USE_USB_FS
- 通过修改 usbd_conf.h 里面的 MSC_MEDIA_PACKET 定义值大小,可以一定程度提高USB 读写速度(越大越快)。通过修改:STORAGE_LUN_NBR 宏定义的值为 2,可以支持 3 个磁盘
- 官方例程在 2 个或以上磁盘支持的时候,存在 bug,需要修改 usbd_msc.h 里面USBD_MSC_BOT_HandleTypeDef 结构体的 scsi_blk_nbr 参数,将其改为数组形式:uint32_t scsi_blk_nbr[STORAGE_LUN_NBR];数组大小由 STORAGE_LUN_NBR 指定,修改该参数后,相应的有一些函数要做修改,参考本例程源码。
- 修改 usbd_msc_bot.c 里面修改 MSC_BOT_CBW_Decode 函数,将 hmsc->cbw.bLUN > 1 改为:hmsc->cbw.bLUN > STORAGE_LUN_NBR,以支持多个磁盘
- 使用 USB OTG FS,必须在 MDK 编译器的全局宏定义里面,添加宏定义:
-
USB 相关源码解释,参考:UM1734(STM32Cube USB device library).pdf
usb核心代码刨析
1. USB 驱动代码
1.1 usbd_conf.c
-
usbd_conf.c 提供 USB 设备库的回调及 MSP 初始化函数,当 USB 状态机处理完不同事务的时候,会调用此回调函数,通过回调函数,可以知道 USB当前状态。根据这些状态,用户应用程序可以执行不同操作
-
usbd_conf.c 3 个重点函数:
HAL_PCD_MspInit 和 OTG_FS_IRQHandler、USBD_LL_Init函数
-
HAL_PCD_MspInit 函数,使能 USB 时钟,初始化 IO 口,设置中断等。该函数在HAL_PCD_Init 函数里面被调用。
-
OTG_FS_IRQHandler 函数,是 USB 的中断服务函数,通过调用 HAL_PCD_IRQHandler 函数,实现对 USB 各种事务的处理。
-
USBD_LL_Init 函数,初始化 USB 底层设置,因为定义的是:USE_USB_FS,因此会设置 USB OTG 使用 USB_OTG_FS,完成各种设置,比如,使用内部 PHY,使用全速模式,不使能 VBUS 检测等。该函数在 USBD_Init 函数里面被调用
1.2 usbd_desc.c
- 提供 USB 设备类的描述符,决定 USB 设备的类型、端点、接口、字符串、制造商等重要信息
- 一般不修改
- usbd 即 device 类,usbh 即 host 类。只有 usb 字样的那就是 device 和 host 可以共用的,通过文件名区分该文件是用在 device 还是 host
1.3 usbd_storage.c
- 提供磁盘操作函数,包括支持的磁盘个数,以及每个磁盘的初始化和读写等函数。
- STORAGE_Init_FS函数: 初始化存储设备。根据输入参数(lun),执行不同存储设备的初始化
- STORAGE_Read_FS 函数: 从存储设备读取数据,根据存储设备(lun)的不同,调用不同的读取函数,完成数据读取。
- STORAGE_Write_FS 函数: 往存储设备写入数据,根据存储设备(lun)的不同,调用不同的写入函数,完成数据写入
2. main.c 代码
- USBD_HandleTypeDef 是用于处理 USB 设备类通信处理的结构体类型,包含了 USB 设备类通信的各种变量、结构体参数、传输状态和端点信息等
- USB 初始化
1, 调用 USBD_Init 函数,初始化 USB 从机内核;
2, 调用 USBD_RegisterClass 函数,链接 MSC 设备类驱动程序到设备内核;
3, 调用 USBD_MSC_RegisterStorage 函数,为 MSC 设备类驱动添加回调函数;
4, 调用 USBD_Start 函数,启动 USB 通信;
经过以上四步处理,USB 启动,所有 USB 事务,都是通过 USB 中断触发,并由 USB驱动库自动处理。USB 中断服务函数在 usbd_conf.c 里
/**
* @brief USB OTG 中断服务函数
* @note 处理所有 USB 中断
* @param 无
* @retval 无
*/
void OTG_FS_IRQHandler(void)
{
HAL_PCD_IRQHandler(&g_pcd_usb_otg_fs);
}
- HAL_PCD_IRQHandler 函数处理各种 USB 中断请求。