2.13. USB 设备

2.13.1. 简介

USB 通信串行总线(Universal Serial Bus)是一种外部总线标准,用于规范电脑和外部设备的连接和通讯,是应用在 PC 领域的接口技术。博流 BL70X 系列 MCU 中 USB 设备具有以下特性:

  • 支持 USB1.1 全速设备

  • 支持 8 个双向端点:EP0 可配置为控制/批量/中断/同步端点,EP1-EP7 可配置为批量/中断/同步端点

  • 每个端点均包含 TX、RX 两个方向的 FIFO,FIFO 深度 64 字节,并且支持 DMA

  • 支持内部 transceiver

  • 支持 suspend/resume

  • 支持 LPM

  • 支持多种 USB 中断配置

2.13.2. USB 设备结构体定义

typedef struct usb_dc_device {
    struct device parent;
    uint8_t id;
    usb_dc_ep_state_t in_ep[8];
    usb_dc_ep_state_t out_ep[8];
    void *tx_dma;
    void *rx_dma;
} usb_dc_device_t;
  • parent 继承父类属性

  • id USB id,0 表示 USB0

  • in_ep USB 输入端点的参数

  • out_ep USB 输出端点的参数

  • tx_dma 附加的发送 dma 句柄

  • rx_dma 附加的接收 dma 句柄

in_ep out_ep 的结构如下

typedef struct
{
    uint8_t ep_ena;
    uint32_t is_stalled;
    struct usb_dc_ep_cfg ep_cfg;
} usb_dc_ep_state_t;
  • ep_ena 继承父类属性

  • is_stalled 挂起状态,0表示非挂起状态,1表示挂起状态

  • ep_cfg 端点的属性

ep_cfg 的结构如下

struct usb_dc_ep_cfg {
    uint8_t ep_addr;
    uint16_t ep_mps;
    uint8_t ep_type;
};
  • ep_addr 端点的地址

  • ep_mps 端点最大 packet 长度

  • ep_type 端点传输类型

注解

以上参数无需用户配置

2.13.3. USB 设备接口

USB 设备接口遵循标准设备驱动管理层提供的接口。

2.13.3.1. usb_dc_register

usb_dc_register 用来注册一个 USB 从设备标准驱动接口,在注册之前需要打开对应 USB 设备的宏定义,例如定义宏 BSP_USING_USB 方可使用 USB 设备。注册完成以后才可以使用其他接口,如果没有定义宏,则无法使用 USB 设备。

int usb_dc_register(enum usb_index_type index, const char *name);
  • index 要注册的设备索引

  • name 为注册的设备命名

  • return 错误码,0表示成功,其他表示失败

2.13.3.2. device_open

device_open 用于打开一个 USB 设备,实际调用 usb_open

int device_open(struct device *dev, uint16_t oflag);
  • dev 设备句柄

  • oflag 设备的打开方式

  • return 错误码,0表示成功,其他表示失败

2.13.3.3. device_close

device_close 用于关闭一个 USB 设备,实际调用 usb_close

int device_close(struct device *dev);
  • dev 设备句柄

  • return 错误码,0表示成功,其他表示失败

2.13.3.4. device_control

device_control 用于对 USB 设备的进行控制和参数的修改,实际调用 usb_control

int device_control(struct device *dev, int cmd, void *args);
  • dev 设备句柄

  • cmd 设备控制命令

  • args 控制参数

  • return 错误码,0表示成功,其他表示失败

USB 设备除了标准的控制命令,还具有私有的控制命令。

table1

cmd

args

description

DEVICE_CTRL_SET_INT

uint32_t

开启 USB 中断

DEVICE_CTRL_USB_DC_SET_ACK

uint32_t

设置 USB 设备 ACK 状态

DEVICE_CTRL_USB_DC_ENUM_ON

NULL

打开 USB 设备枚举

DEVICE_CTRL_USB_DC_ENUM_OFF

NULL

关闭 USB 设备枚举

DEVICE_CTRL_USB_DC_GET_EP_TX_FIFO_CNT

uint32_t

设置 USB 设备发送 FIFO 的个数

DEVICE_CTRL_USB_DC_GET_EP_RX_FIFO_CNT

uint32_t

设置 USB 设备接收 FIFO 的个数

DEVICE_CTRL_ATTACH_TX_DMA

device*

设置 USB 设备发送 dma 句柄

DEVICE_CTRL_ATTACH_RX_DMA

device*

设置 USB 设备接收 dma 句柄

DEVICE_CTRL_USB_DC_SET_TX_DMA

uint32_t

开启 USB 设备通过 dma 发送

DEVICE_CTRL_USB_DC_SET_RX_DMA

uint32_t

开启 USB 设备通过 dma 接收

2.13.3.5. device_write

device_write 用于 USB 设备数据的发送,当前只支持同步传输 dma 发送,实际调用 usb_write

int device_write(struct device *dev, uint32_t pos, const void *buffer, uint32_t size);
  • dev 设备句柄

  • pos 无作用

  • buffer 要写入的 buffer 缓冲区

  • size 要写入的长度

  • return 错误码,0表示成功,其他表示失败

2.13.3.6. device_read

device_read 用于 USB 设备数据的接收,当前只支持同步传输 dma 接收。实际调用 usb_read

int device_read(struct device *dev, uint32_t pos, void *buffer, uint32_t size);
  • dev 设备句柄

  • pos 无作用

  • buffer 要读入的 buffer 缓冲区

  • size 要读入的长度

  • return 错误码,0表示成功,其他表示失败

2.13.3.7. device_set_callback

device_set_callback 用于注册一个 USB 设备中断回调函数。

int device_set_callback(struct device *dev, void (*callback)(struct device *dev, void *args, uint32_t size, uint32_t event));
  • dev 设备句柄

  • callback 要注册的中断回调函数

  • return 错误码,0表示成功,其他表示失败

    • dev 设备句柄

    • args 接收发送缓冲区,数据类型为 uint8_t*

    • size 传输长度

    • event 中断事件类型

event 类型如下

enum usb_dc_event_type {
    /** USB error reported by the controller */
    USB_DC_EVENT_ERROR,
    /** USB reset */
    USB_DC_EVENT_RESET,
    /** Start of Frame received */
    USB_DC_EVENT_SOF,
    /** USB connection established, hardware enumeration is completed */
    USB_DC_EVENT_CONNECTED,
    /** USB configuration done */
    USB_DC_EVENT_CONFIGURED,
    /** USB connection suspended by the HOST */
    USB_DC_EVENT_SUSPEND,
    /** USB connection lost */
    USB_DC_EVENT_DISCONNECTED,
    /** USB connection resumed by the HOST */
    USB_DC_EVENT_RESUME,

    /** setup packet received */
    USB_DC_EVENT_SETUP_NOTIFY,
    /** ep0 in packet received */
    USB_DC_EVENT_EP0_IN_NOTIFY,
    /** ep0 out packet received */
    USB_DC_EVENT_EP0_OUT_NOTIFY,
    /** ep in packet except ep0 received */
    USB_DC_EVENT_EP_IN_NOTIFY,
    /** ep out packet except ep0 received */
    USB_DC_EVENT_EP_OUT_NOTIFY,
    /** Initial USB connection status */
    USB_DC_EVENT_UNKNOWN
};

2.13.3.8. usb_dc_send_from_ringbuffer

usb_dc_send_from_ringbuffer 用于从 ringbuffer 中读取数据并通过某个端点将数据发送出去。

int usb_dc_send_from_ringbuffer(struct device *dev, Ring_Buffer_Type *rb, uint8_t ep);
  • dev 设备指针

  • rb rinbuffer 结构体指针

  • ep 端点地址

  • return 错误码,0表示成功,其他表示失败

2.13.3.9. usb_dc_receive_to_ringbuffer

usb_dc_receive_to_ringbuffer 用于从某个端点接收数据并保存到 ringbuffer 中。

int usb_dc_receive_to_ringbuffer(struct device *dev, Ring_Buffer_Type *rb, uint8_t ep);
  • dev 设备指针

  • rb rinbuffer 结构体指针

  • ep 端点地址

  • return 错误码,0表示成功,其他表示失败

重要

以下函数为 USB Device 协议栈需要实现的 porting 接口,用户无需在应用层调用。

2.13.3.10. usb_dc_set_address

usb_dc_set_address 用于 USB 设备地址的配置。

int usb_dc_set_address(const uint8_t addr);
  • addr USB 设备的地址

  • return 错误码,0表示成功,其他表示失败

2.13.3.11. usb_dc_ep_open

usb_dc_ep_open 用于 USB 设备端点的开启。

int usb_dc_ep_open(const struct usbd_endpoint_cfg *ep_cfg);
  • ep_cfg 端点的属性

  • return 错误码,0表示成功,其他表示失败

2.13.3.12. usb_dc_ep_close

usb_dc_ep_close 用于 USB 设备端点的关闭。

int usb_dc_ep_close(const uint8_t ep);
  • ep 端点地址

  • return 错误码,0表示成功,其他表示失败

2.13.3.13. usb_dc_ep_set_stall

usb_dc_ep_set_stall 用于 USB 设备挂起状态的设置,挂起状态下无法收发数据。

int usb_dc_ep_set_stall(const uint8_t ep);
  • ep 端点地址

  • return 错误码,0表示成功,其他表示失败

2.13.3.14. usb_dc_ep_clear_stall

usb_dc_ep_clear_stall 用于端点挂起状态的清除,非挂起状态可以进行收发数据。

int usb_dc_ep_clear_stall(const uint8_t ep);
  • ep 端点地址

  • return 错误码,0表示成功,其他表示失败

2.13.3.15. usb_dc_ep_is_stalled

usb_dc_ep_is_stalled 用于 USB 设备挂起状态的查询。

int usb_dc_ep_is_stalled(const uint8_t ep, uint8_t *stalled);
  • ep 端点id

  • stalled 保存挂起状态的地址, 0 表示非挂起状态, 1 表示挂起状态

  • return 错误码,0表示成功,其他表示失败

2.13.3.16. usb_dc_ep_write

usb_dc_ep_write 用于向某个端点发送数据。

int usb_dc_ep_write(const uint8_t ep, const uint8_t *data, uint32_t data_len, uint32_t *ret_bytes);
  • ep 端点地址

  • data 要发送的数据地址

  • data_len 要发送数据的长度

  • ret_bytes 实际成功发生的数据长度

  • return 错误码,0表示成功,其他表示失败

2.13.3.17. usb_dc_ep_read

usb_dc_ep_read 用于从某个端点接收数据。

int usb_dc_ep_read(const uint8_t ep, uint8_t *data, uint32_t max_data_len, uint32_t *read_bytes);
  • ep 端点地址

  • data 要接收数据的地址

  • data_len 要接收数据的长度,不能大于最大包长

  • ret_bytes 实际成功接收的数据长度

  • return 错误码,0表示成功,其他表示失败