本帖最后由 susutata 于 2023-7-20 11:39 编辑
#申请原创#
@21小跑堂
初识APM32 USB Device Library
## 01 简介
在官方所提供的APM32 USB SDK中,发现配套的library中有APM32F0、F10x、F4xx及L0xx,想来已经适配了APM32目前所有支持USB设备的系列型号。
设备库中包括有USB底层寄存器配置文件、USB设备标准库驱动、USB内核文件、USB Class文件。其中:
- usbd_core:包含USB FS、HS的控制、中断、批量和同步传输操作。
- usbd_class:包含USB CDC类、HID类、MSC类及供应商特殊类(winusb 1.0)的支持。
## 02 架构
APM32 USB Device Library的架构主要分为五层,其中应用层位域架构的顶端。第二层包括core和class两部分驱动。
## 03 文件目录结构
### 目录结构
USB设备库文件包含在APM32_USB_Library目录下的Device文件夹中。其目录结构如下图所示:
### 文件结构
整个USB设备库的文件包括底层共用的驱动、延时单元、中间件core和class文件,还有用户配置文件等。
#### 共用的驱动
- apm32xxx.h
- apm32xxx_usb.c/h
- apm32xxx_usb_device.c/h
#### 延时单元
- bsp_delay.c/h
#### 中间件
- core文件
- class文件
#### 用户配置文件
- usbd_board.c/h:USB设备配置文件
- usbd_device_user.c/h:USB用户初始化文件
- usbd_descriptor.c/h:描述符配置文件
- usb_interface.c/h:数据接口配置文件
## 04 内核和Class
### USB设备Configuration
USB设备库中提供三个基础的配置文件:
- usbd_board.c/h:包含USB设备的配置和回调函数。
- usbd_descriptor.c/h:包含USB设备的基本描述符。
- usbd_device_user.c/h:用于初始化USB设备。
### USB设备Core
USB设备Core中提供4个主要的文件:
#### usbd_core.c/h
包含USB核心状态机的控制,及不同事件的处理及回调函数。
API | 描述 | USBD_Init() | 初始化设备及状态机,并链接设备结构体到Class的处理单元 | USBD_DeInit() | 解除USB设备初始化 | USBD_SetupStage() | 处理setup阶段的请求 | USBD_DataOutStage() | 处理out阶段的数据 | USBD_DataInStage() | 处理in阶段的数据 | USBD_SetSpeed() | 设置USB设备的速度 | USBD_Resume() | 在挂起前恢复设备状态到之前的状态 | USBD_Suspend() | 设置设备状态为挂起 | USBD_Reset() | 重新初始化设备 | USBD_HandleSOF() | 处理SOF事件 | USBD_Connect() | 处理设备连接事件 | USBD_Disconnect() | 处理设备断开连接事件 |
#### usbd_dataXfer.c/h包含在EP0上的数据收发等函数。
API | 描述 | USBD_CtrlSendData() | 在EP0上发送数据 | USBD_CtrlSendNextData() | 在EP0上发送剩余数据 | USBD_CtrlReceiveData() | 从EP0上接收数据 | USBD_CtrlSendStatus() | 在EP0上发送零长度数据包 | USBD_CtrlReceiveStatus() | 从EP0上接收零长度数据包 | USBH_SetupReqParse() | 解析setup请求 |
#### usbd_stdReq.c/h
包含各个标准请求的处理函数。
API | 描述 | USBD_REQ_GetStatus() | 处理"Get Status"请求 | USBD_REQ_ClearFeature() | 处理"Clear Feature"请求 | USBD_REQ_SetFeature() | 处理"Set Feature"请求 | USBD_REQ_SetAddress() | 处理"Set Address"请求 | USBD_REQ_GetDesc() | 处理"Get Descriptor"请求 | USBD_REQ_GetCfg() | 处理"Get Configuration"请求 | USBD_REQ_SetCfg() | 处理"Set Configuration"请求 | USBD_REQ_CtrlError() | 处理控制传输出现的错误情况 |
#### usbd_config.h
该文件包含了USB Device中常用的变量及结构体的定义。
### USB设备Class
#### CDC
CDC Class用于虚拟COM口和调制解调器等设备。主要的API如下表所示。
API | 描述 | USBD_CDC_ClassInitHandler() | 初始化CDC类的结构体和端点 | USBD_CDC_ClassDeInitHandler() | 解除CDC类初始化 | USBD_CDC_SOFHandler() | 处理SOF事件 | USBD_CDC_SetupHandler() | 处理CDC类的setup请求 | USBD_CDC_RxEP0Handler() | 处理EP0上的接收就绪事件 | USBD_CDC_DataInHandler() | 处理CDC类从IN端点发送到Host的数据 | USBD_CDC_DataOutHandler() | 处理CDC类从OUT端点接收到的Host数据 | USBD_CDC_TxPacket() | 发送包 | USBD_CDC_RxPacket() | 接收包 | USBD_CDC_ReadInterval() | 读取轮询间隔 | USBD_CDC_ConfigTxBuffer() | 配置发送buffer | USBD_CDC_ConfigRxBuffer() | 配置接收buffer | USBD_CDC_RegisterItf() | 注册CDC类接口处理函数 |
#### HID
HID Class用于实现人机接口,如鼠标、键盘。但要注意,该Class默认只实现了DATA IN的传输,没有DATA OUT的传输处理。主要的API如下表所示。
API | 描述 | USBD_HID_ClassInitHandler() | 初始化HID类的结构体和端点 | USBD_HID_ClassDeInitHandler() | 解除HID类的初始化 | USBD_HID_SOFHandler() | 处理SOF事件 | USBD_HID_SetupHandler() | 处理HID类的setup请求 | USBD_HID_DataInHandler() | 处理HID类从IN端点发送到主机的数据 | USBD_HID_ReadInterval() | 读取轮询间隔 | USBD_HID_TxReport() | 发送报告描述符给主机 |
#### MSC
MSC Class用于U盘等大容量存储设备。主要的API如下表所示。
API | 描述 | USBD_MSC_ClassInitHandler() | 初始化MSC类的结构体和端点 | USBD_MSC_ClassDeInitHandler() | 解除MSC类的初始化 | USBD_MSC_SOFHandler() | 处理SOF事件 | USBD_MSC_SetupHandler() | 处理MSC类的setup请求 | USBD_MSC_DataInHandler() | 处理MSC类从IN端点发送到Host的数据 | USBD_MSC_DataOutHandler() | 处理MSC类从OUT端点接收到的主机数据 | USBD_MSC_RegisterMemory() | 注册MSC类接口处理函数 |
#### WinUSB
WinUSB Class是供应商特殊class,基于 MS OS 1.0版本实现。主要的API如下表所示。
API | 描述 | USBD_WINUSB_ClassInitHandler() | 初始化WINUSB类的结构体和端点 | USBD_WINUSB_ClassDeInitHandler() | 解除WINUSB类的初始化 | USBD_WINUSB_SOFHandler() | 处理SOF事件 | USBD_WINUSB_SetupHandler() | 处理WINUSB类的setup请求 | USBD_WINUSB_DataInHandler() | 处理WINUSB类从IN端点发送到Host的数据 | USBD_WINUSB_DataOutHandler() | 处理WINUSB类从OUT端点接收到的Host数据 | USBD_WINUSB_TxPacket() | 发送包 | USBD_WINUSB_RxPacket() | 接收包 | USBD_WINUSB_ReadInterval() | 读取轮询间隔 | USBD_WINUSB_ConfigTxBuffer() | 配置发送buffer | USBD_WINUSB_ConfigRxBuffer() | 配置接收buffer | USBD_WINUSB_RegisterItf() | 注册WINUSB类接口处理函数 |
## 05 应用方法
基础应用方法比较简单,配置设备库的一些参数、描述符和接口处理,然后初始化就行。比较容易忘记的地方是底层和class里的端点配置。
### 配置USB设备库
#### 库配置项
#define USBD_SUP_CLASS_MAX_NUM 1
#define USBD_SUP_INTERFACE_MAX_NUM 1
#define USBD_SUP_CONFIGURATION_MAX_NUM 1
#define USBD_SUP_STR_DESC_MAX_NUM 512
#define USBD_SUP_MSC_MEDIA_PACKET 512
/* Only support LPM USB device */
#define USBD_SUP_LPM 0
#define USBD_SUP_SELF_PWR 1
#define USBD_DEBUG_LEVEL 1U
#### Class配置项
#define USBD_MSC_OUT_EP_ADDR 0x01
#define USBD_MSC_IN_EP_ADDR 0x81
#define USBD_MSC_FS_MP_SIZE 0x40
#define USBD_MSC_HS_MP_SIZE 0x200
### 配置USB底层
在USBD_HardwareInit()中配置端点缓冲,时钟、IO、延时时基等。
//OTG类MCU
/* Configure RX FIFO */
USB_OTG_ConfigRxFifoSize(usbdh->usbGlobal, USBD_FS_RX_FIFO_SIZE);
/* Configure TX FIFO */
USBD_OTG_ConfigDeviceTxFifo(usbdh, 0, USBD_FS_TX_FIFO_0_SIZE);
USBD_OTG_ConfigDeviceTxFifo(usbdh, 1, USBD_FS_TX_FIFO_1_SIZE);
//USBD类MCU
USBD_ConfigPMA(&usbDeviceHandler, USBD_MSC_EP_OUT_ADDR, USBD_EP_BUFFER_SINGLE, USBD_MSC_EP_OUT_SIZE);
USBD_ConfigPMA(&usbDeviceHandler, USBD_MSC_EP_IN_ADDR, USBD_EP_BUFFER_SINGLE, USBD_MSC_EP_IN_SIZE);
### 配置中断服务函数
USB中断请求函数需放在相应的中断服务函数中。
### 配置USB描述符
USB设备常用的描述符配置都在usbd_descriptor.c文件中,包括:
- 设备描述符
- 配置描述符
- 配置字符串描述符
- 接口字符串描述符
- 语言ID字符串描述符
- 制造商字符串描述符
- 产品字符串描述符
- 序列号字符串描述符
- 其他速度描述符
- 设备修饰描述符
- BOS描述符
### 配置USB数据接口
CDC、MSC等class有数据需要在class中处理,则还需要在USB设备初始化时注册接口处理函数到USB内核中。
/* USB MSC register storage handler */
USBD_MSC_RegisterMemory(&gUsbDeviceFS, &USBD_MEMORY_INTERFACE_FS);
### 初始化USB设备
官方默认的USB设备初始化函数USB_DeviceInit()在usb_device_user.c文件中,包含以下功能:
- 内核速度选择
- 描述符注册
- Class接口注册
- Class处理函数注册
- USB设备用户回调函数注册
void USB_DeviceInit(void)
{
/* USB MSC register storage handler */
USBD_MSC_RegisterMemory(&gUsbDeviceFS, &USBD_MEMORY_INTERFACE_FS);
/* USB device and class init */
USBD_Init(&gUsbDeviceFS, USBD_SPEED_FS, &USBD_DESC_FS, &USBD_MSC_CLASS, USB_DevUserHandler);
}
完成USB设备初始化后就可以按Class的特征进行控制、数据收发等操作。
|