STM32下USB的使用

一、介绍

  • 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)收发器

image

  • ST 提供了一个完整的 USB OTG 驱动库(包括主机和设备),全部是以 HAL 库的形式提供,相关参考例程在 en.stm32cubef4_v1-26-0_v1.26.0.zip 可以找到

时钟

image

  • STM32F407通过AHB总线访问(AHB频率必须大14.2Mhz),USB OTG 的内核时钟必须是 48Mhz来自时钟树里面的 PLL48CK(和 SDIO 共用)。

三、 demo移植

  • USB OTG 库
    image
  • USB OTG 例程
    image
  • USB OTG 库的使用和例程说明,参考 ST 官方提供的:UM1734(从机)和 UM1720(主机)两个文档,详细介绍USB OTG库的各个组成部分以及所提供的例程使用方法

demo移植步骤

  • 相关代码
    image

  • 步骤如下:

    • 拷贝官方 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 文件夹下
      image

    • 在Keil工程的基础上新建分组添加相关代码到工程中
      image

  • 代码修改

  • 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 相关源码解释,参考: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);
}
USBD_HandleTypeDef USBD_Device; /* USB Device 处理结构体 */
。
。
。
USBD_Init(&USBD_Device, &FS_Desc, DEVICE_FS); /* 初始化 USB */
 USBD_RegisterClass(&USBD_Device, &USBD_MSC); /* 添加类 */
/* 为 MSC 类添加回调函数 */
USBD_MSC_RegisterStorage(&USBD_Device, &USBD_Storage_Interface_fops_FS);
USBD_Start(&USBD_Device); /* 开启 USB */


  • HAL_PCD_IRQHandler 函数处理各种 USB 中断请求。
posted @ 2023-07-06 20:14  登云上人间  阅读(2445)  评论(0编辑  收藏  举报