summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsakumisu <[email protected]>2021-12-04 14:41:09 +0800
committersakumisu <[email protected]>2021-12-04 15:02:02 +0800
commit1ac20b5fdefe91cd1eb01697244747f31dce7a5c (patch)
treed5ce58ac9c3e03a065c383fd509af10e48743edd
parentaac9ca00f8115b1ab59f012033a5898580f2d359 (diff)
add rt-thread userguide
-rw-r--r--README.md355
-rw-r--r--SConscript73
-rw-r--r--docs/img/rtt_cdc_demo.pngbin0 -> 9403 bytes
-rw-r--r--docs/img/stm32cubemx.pngbin0 -> 37705 bytes
-rw-r--r--docs/img/stm32cubemx_clk.pngbin0 -> 16418 bytes
-rw-r--r--docs/rt-thread.md72
-rw-r--r--docs/rt-thread_zh.md71
-rw-r--r--docs/usb_host.md1
8 files changed, 264 insertions, 308 deletions
diff --git a/README.md b/README.md
index b42407fd..cb76dacb 100644
--- a/README.md
+++ b/README.md
@@ -16,9 +16,49 @@ USB Stack 是一个小而美的、可移植性高的、用于嵌入式 MCU 的 U
- TMC: <https://www.usb.org/document-library/test-measurement-class-specification>
- DFU: <https://www.st.com/resource/zh/application_note/cd00264379-usb-dfu-protocol-used-in-the-stm32-bootloader-stmicroelectronics.pdf>
+## USB Stack 目录结构
+
+```
+.
+├── class
+│ ├── audio
+│ ├── cdc
+│ ├── dfu
+│ ├── hid
+│ ├── hub
+│ ├── midi
+│ ├── msc
+│ ├── tmc
+│ └── video
+├── common
+├── core
+├── demo
+│ ├── bouffalolab
+│ └── stm32
+├── docs
+├── packet capture
+└── port
+ ├── bouffalolab
+ │ └── bl702
+ ├── ch32
+ ├── mm32
+ ├── stm32
+ └── template
+```
+
+| 目录名 | 描述 |
+|:-------------:|:------------------------------:|
+|class | usb class 类主从驱动 |
+|common | usb spec 定义和一些常用函数 |
+|core | usb 主从核心实现 |
+|demo | 示例 |
+|docs | 文档 |
+|packet capture | 抓包文件(需要使用力科软件打开)|
+|port | usb 主从需要实现的 porting接口 |
+
## USB Device 协议栈简介
-USB Device 协议栈对标准设备请求、CLASS 请求、VENDOR 请求以及 custom 特殊请求规范了一套统一的函数框架,采用面向对象和链表的方式,能够使得用户快速上手复合设备,不用管底层的逻辑。同时,规范了一套标准的 dcd porting 接口,用于适配不通的 USB IP,达到面向 ip 编程。
+USB Device 协议栈对标准设备请求、CLASS 请求、VENDOR 请求以及 custom 特殊请求规范了一套统一的函数框架,采用面向对象和链表的方式,能够使得用户快速上手复合设备,不用管底层的逻辑。同时,规范了一套标准的 dcd porting 接口,用于适配不同的 USB IP,达到面向 ip 编程。
USB Device 协议栈的代码实现过程参考 <https://www.bilibili.com/video/BV1Ef4y1t73d> 。
@@ -54,316 +94,15 @@ USB Device 协议栈资源占用说明:
waiting....
-## USB Device Controller Porting 接口
-
-USB Device controller porting 接口在 `usb_stack/common/usb_dc.h` 文件中声明,用户根据自己的 MCU 实现以下接口:
-
-- `usbd_set_address`
-- `usbd_ep_open`
-- `usbd_ep_close`
-- `usbd_ep_set_stall`
-- `usbd_ep_clear_stall`
-- `usbd_ep_is_stalled`
-- `usbd_ep_write`
-- `usbd_ep_read`
-
-## USB Device Controller 其他接口
-
-用户需要实现 usb device controller 相关寄存器初始化的函数(可以命名为 `usb_dc_init` ),以及在 USB 中断函数中根据不同的中断标志调用 `usbd_event_notify_handler`。
-
-## USB Device 应用层接口
-
-### USB Device 通用接口
-
-#### **usbd_desc_register**
-
-`usbd_desc_register` 用来注册 USB 描述符,描述符种类包括:设备描述符、配置描述符、接口描述符、字符串描述符、设备限定描述符。
-
-```
- void usbd_desc_register(const uint8_t *desc);
-```
-
-- **desc** 描述符的句柄
-
-
-#### **usbd_msosv1_desc_register**
-
-`usbd_msosv1_desc_register` 用来注册一个 WINUSB 描述符,格式按照 `struct usb_msosv1_descriptor`。
-
-```
- void usbd_msosv1_desc_register(struct usb_msosv1_descriptor *desc);
-```
-
-- **desc** 描述符句柄
-
-
-#### **usbd_class_add_interface**
-
-`usbd_class_add_interface` 用来给 USB 设备类增加接口,并将接口信息挂载在类的链表上。
-
-```
- void usbd_class_add_interface(usbd_class_t *class, usbd_interface_t *intf);
-```
-
-- **class** USB 设备类的句柄
-- **intf** USB 设备接口的句柄
-
-`usbd_class_t` 定义如下
-
-```
-
- typedef struct usbd_class {
- usb_slist_t list;
- const char *name;
- usb_slist_t intf_list;
- } usbd_class_t;
-
-```
-
-- **list** 类的链表节点
-- **name** 类的名称
-- **intf_list** 接口的链表节点
-
-`usbd_interface_t` 定义如下
-
-```
- typedef struct usbd_interface {
- usb_slist_t list;
- /** Handler for USB Class specific commands */
- usbd_request_handler class_handler;
- /** Handler for USB Vendor specific commands */
- usbd_request_handler vendor_handler;
- /** Handler for USB custom specific commands */
- usbd_request_handler custom_handler;
- /** Handler for USB event notify commands */
- usbd_notify_handler notify_handler;
- uint8_t intf_num;
- usb_slist_t ep_list;
- } usbd_interface_t;
-
-```
-
-- **list** 接口的链表节点
-- **class_handler** class setup 请求回调函数
-- **vendor_handler** vendor setup 请求回调函数
-- **custom_handler** custom setup 请求回调函数
-- **notify_handler** 中断标志、协议栈相关状态回调函数
-- **intf_num** 当前接口偏移
-- **ep_list** 端点的链表节点
-
-#### **usbd_interface_add_endpoint**
-
-`usbd_interface_add_endpoint` 用来给 USB 接口增加端点,并将端点信息挂载在接口的链表上。
-
-```
- void usbd_interface_add_endpoint(usbd_interface_t *intf, usbd_endpoint_t *ep);
-```
-
-- **intf** USB 设备接口的句柄
-- **ep** USB 设备端点的句柄
-
-`usbd_endpoint_t` 定义如下
-
-```
- typedef struct usbd_endpoint {
- usb_slist_t list;
- uint8_t ep_addr;
- usbd_endpoint_callback ep_cb;
- } usbd_endpoint_t;
-```
-
-- **list** 端点的链表节点
-- **ep_addr** 端点地址
-- **ep_cb** 端点中断回调函数
-
-#### **usb_device_is_configured**
-
-`usb_device_is_configured` 用来检查 USB 设备是否被配置(枚举)。
-
-```
- bool usb_device_is_configured(void);
-```
-
-- **return** 配置状态, 0 表示未配置, 1 表示配置成功
-
-
-### USB Device CDC 类接口
-
-#### **usbd_cdc_add_acm_interface**
-
-`usbd_cdc_add_acm_interface` 用来给 USB CDC ACM 类添加接口,并重写该接口相关的函数。重写的函数包括 `cdc_acm_class_request_handler` 和 ``cdc_notify_handler`,
-其中 `cdc_acm_class_request_handler` 用于处理 USB CDC ACM Setup 中断请求, `cdc_notify_handler` 用于实现 USB CDC 其他中断回调函数。
-
-```
- void usbd_cdc_add_acm_interface(usbd_class_t *class, usbd_interface_t *intf);
-```
-
-- **class** 类的句柄
-- **intf** 接口句柄
-
-#### **usbd_cdc_acm_set_line_coding**
-
-`usbd_cdc_acm_set_line_coding` 用来对串口进行配置。该接口由用户实现,默认为空。
-
-```
- void usbd_cdc_acm_set_line_coding(uint32_t baudrate, uint8_t databits, uint8_t parity, uint8_t stopbits);
-```
-
-- **baudrate** 波特率
-- **databits** 数据位
-- **parity** 校验位
-- **stopbits** 停止位
-
-
-#### **usbd_cdc_acm_set_dtr**
-
-`usbd_cdc_acm_set_line_coding` 用来控制串口 DTR。该接口由用户实现,默认为空。
-
-```
- void usbd_cdc_acm_set_dtr(bool dtr);
-```
-
-- **dtr** dtr 为1表示拉低电平,为0表示拉高电平
-
-
-#### **usbd_cdc_acm_set_rts**
-
-`usbd_cdc_acm_set_line_coding` 用来控制串口 RTS。该接口由用户实现,默认为空。
-
-```
- void usbd_cdc_acm_set_rts(bool rts);
-```
-
-- **rts** rts 为1表示拉低电平,为0表示拉高电平
-
-### USB Device MSC 类接口
-
-#### **usbd_msc_class_init**
-
-`usbd_msc_class_init` 用于初始化 USB MSC 类,注册 USB CDC ACM 设备并为其添加接口,且为接口添加 BLUK OUT 、BULK IN 端点及其回调函数。
-
-```
- void usbd_msc_class_init(uint8_t out_ep, uint8_t in_ep);
-```
-
-- **out_ep** 输出端点的地址
-- **in_ep** 输入端点的地址
-
-#### **usbd_msc_get_cap**
-
-`usbd_msc_get_cap` 用来获取存储器的信息。该接口由用户实现,默认为空。
-
-```
- void usbd_msc_get_cap(uint8_t lun, uint32_t *block_num, uint16_t *block_size);
-```
-
-- **lun** 存储逻辑单元,暂时无用
-- **block_num** 存储扇区个数的指针
-- **block_size** 存储扇区大小的指针
-
-#### **usbd_msc_sector_read**
-
-`usbd_msc_sector_read` 用来对存储器某个扇区开始进行数据读取。该接口由用户实现,默认为空。
-
-```
- int usbd_msc_sector_read(uint32_t sector, uint8_t *buffer, uint32_t length);
-```
-
-- **sector** 扇区偏移
-- **buffer** 存储读取的数据的指针
-- **length** 读取长度
-
-
-#### **usbd_msc_sector_write**
-
-`usbd_msc_sector_write` 用来对存储器某个扇区开始写入数据。该接口由用户实现,默认为空。
+## USB Device API
-```
- int usbd_msc_sector_write(uint32_t sector, uint8_t *buffer, uint32_t length);
-```
-
-- **sector** 扇区偏移
-- **buffer** 写入数据指针
-- **length** 写入长度
-
-
-### USB Device HID 类接口
-
-#### **usbd_hid_add_interface**
-
-`usbd_hid_add_interface` 用来给 USB HID 类添加接口,并重写该接口相关的函数。重写的函数包括 `hid_class_request_handler` 、 `hid_custom_request_handler`
-和 `hid_notify_handler`,其中 `hid_class_request_handler` 用来处理 USB HID 类的 Setup 中断请求, `hid_custom_request_handler` 用来处理 USB HID 获取描述符请求,
-`hid_notify_handler` 用来处理 USB HID 类的其他中断回调函数。
-
-```
- void usbd_hid_add_interface(usbd_class_t *class, usbd_interface_t *intf);
-```
+更详细的设备协议栈 API 请参考: [USB Device API](docs/usb_device.md)
-- **class** 类的句柄
-- **intf** 接口句柄
+## USB Host API
-#### **usbd_hid_report_descriptor_register**
-
-`usbd_hid_report_descriptor_register` 用来对存储器某个扇区开始写入数据。该接口由用户实现,默认为空。
-
-```
- void usbd_hid_report_descriptor_register(uint8_t intf_num, const uint8_t *desc, uint32_t desc_len);
-```
-
-- **intf_num** 当前 hid 报告描述符所在接口偏移
-- **desc** 报告描述符
-- **desc_len** 报告描述符长度
-
-#### **usbd_hid_set_request_callback**
-
-`usbd_hid_set_request_callback` 用来对存储器某个扇区开始写入数据。该接口由用户实现,默认为空。
-
-```
- void usbd_hid_set_request_callback( uint8_t intf_num,
- uint8_t (*get_report_callback)(uint8_t report_id, uint8_t report_type),
- void (*set_report_callback)(uint8_t report_id, uint8_t report_type, uint8_t *report, uint8_t report_len),
- uint8_t (*get_idle_callback)(uint8_t report_id),
- void (*set_idle_callback)(uint8_t report_id, uint8_t duration),
- void (*set_protocol_callback)(uint8_t protocol),
- uint8_t (*get_protocol_callback)(void));
-
-```
-
-- **intf_num** 当前 hid 报告描述符所在接口偏移
-- **get_report_callback** get report命令处理回调函数
-- **set_report_callback** set report命令处理回调函数
-- **get_idle_callback** get idle命令处理回调函数
-- **set_idle_callback** set idle命令处理回调函数
-- **set_protocol_callback** set protocol命令处理回调函数
-- **get_protocol_callback** get protocol命令处理回调函数
-
-
-### USB Device Audio 类接口
-
-#### **usbd_audio_add_interface**
-
-`usbd_audio_add_interface` 用来给 USB Audio 类添加接口,并重写该接口相关的函数。重写的函数包括 `audio_class_request_handler` 和 `audio_notify_handler`。
-
-```
- void usbd_audio_add_interface(usbd_class_t *class, usbd_interface_t *intf);
-```
-
-- **class** 类的句柄
-- **intf** 接口句柄
-
-
-### USB Device Video 类接口
-
-#### **usbd_video_add_interface**
-
-`usbd_video_add_interface` 用来给 USB Video 类添加接口,并重写该接口相关的函数。重写的函数包括 `video_class_request_handler` 和 `video_notify_handler`。
-
-```
- void usbd_video_add_interface(usbd_class_t *class, usbd_interface_t *intf);
-```
+更详细的主机协议栈 API 请参考: [USB Host API](docs/usb_host.md)
-- **class** 类的句柄
-- **intf** 接口句柄
+## RT-Thread 软件包使用
+如何在 RT-Thread OS 中使用软件包,请参考:[USB Stack 在 RT-Thread package 中的使用](docs/rt-thread_zh.md)
-### USB Device DFU 类接口
diff --git a/SConscript b/SConscript
new file mode 100644
index 00000000..0857de49
--- /dev/null
+++ b/SConscript
@@ -0,0 +1,73 @@
+from building import *
+
+cwd = GetCurrentDir()
+path = [cwd + '/common']
+path += [cwd + '/core']
+src = Glob('core/usbd_core.c')
+CPPDEFINES = []
+if GetDepend(['PKG_USB_STACK_USING_HS']):
+ CPPDEFINES+=['CONFIG_USB_HS']
+
+# USB DEVICE
+if GetDepend(['PKG_USB_STACK_USING_DEVICE']):
+ if GetDepend(['PKG_USB_STACK_USING_CDC']):
+ path += [cwd + '/class/cdc']
+ src += Glob('class/cdc/usbd_cdc.c')
+ if GetDepend(['PKG_USB_STACK_USING_HID']):
+ path += [cwd + '/class/hid']
+ src += Glob('class/cdc/usbd_hid.c')
+ if GetDepend(['PKG_USB_STACK_USING_DFU']):
+ path += [cwd + '/class/dfu']
+ src += Glob('class/cdc/usbd_dfu.c')
+ if GetDepend(['PKG_USB_STACK_USING_HUB']):
+ path += [cwd + '/class/hub']
+ src += Glob('class/cdc/usbd_hub.c')
+ if GetDepend(['PKG_USB_STACK_USING_AUDIO']):
+ path += [cwd + '/class/audio']
+ src += Glob('class/cdc/usbd_audio.c')
+ if GetDepend(['PKG_USB_STACK_USING_VIDEO']):
+ path += [cwd + '/class/video']
+ src += Glob('class/cdc/usbd_video.c')
+ if GetDepend(['PKG_USB_STACK_USING_MSC']):
+ path += [cwd + '/class/msc']
+ src += Glob('class/cdc/usbd_msc.c')
+ if GetDepend(['SOC_FAMILY_STM32']):
+ if GetDepend(['SOC_SERIES_STM32F0']):
+ src += Glob('port/stm32/usb_dc_nohal.c')
+ src += Glob('../../../../libraries/STM32F0xx_HAL/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd.c')
+ src += Glob('../../../../libraries/STM32F0xx_HAL/STM32F0xx_HAL_Driver/Src/stm32f0xx_hal_pcd_ex.c')
+ src += Glob('../../../../libraries/STM32F0xx_HAL/STM32F0xx_HAL_Driver/Src/stm32f0xx_ll_usb.c')
+ CPPDEFINES += ['STM32F0']
+ elif GetDepend(['SOC_SERIES_STM32F1']):
+ src += Glob('port/stm32/usb_dc_nohal.c')
+ src += Glob('../../../../libraries/STM32F1xx_HAL/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd.c')
+ src += Glob('../../../../libraries/STM32F1xx_HAL/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pcd_ex.c')
+ src += Glob('../../../../libraries/STM32F1xx_HAL/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_usb.c')
+ CPPDEFINES += ['STM32F1']
+ elif GetDepend(['SOC_SERIES_STM32F3']):
+ src += Glob('port/stm32/usb_dc_nohal.c')
+ src += Glob('../../../../libraries/STM32F3xx_HAL/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_pcd.c')
+ src += Glob('../../../../libraries/STM32F3xx_HAL/STM32F3xx_HAL_Driver/Src/stm32f3xx_hal_pcd_ex.c')
+ src += Glob('../../../../libraries/STM32F3xx_HAL/STM32F3xx_HAL_Driver/Src/stm32f3xx_ll_usb.c')
+ CPPDEFINES += ['STM32F3']
+ elif GetDepend(['SOC_SERIES_STM32F4']):
+ src += Glob('port/stm32/usb_dc_hal.c')
+ src += Glob('../../../../libraries/STM32F4xx_HAL/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd.c')
+ src += Glob('../../../../libraries/STM32F4xx_HAL/STM32F4xx_HAL_Driver/Src/stm32f4xx_hal_pcd_ex.c')
+ src += Glob('../../../../libraries/STM32F4xx_HAL/STM32F4xx_HAL_Driver/Src/stm32f4xx_ll_usb.c')
+ CPPDEFINES += ['STM32F4']
+ elif GetDepend(['SOC_SERIES_STM32H7']):
+ src += Glob('port/stm32/usb_dc_hal.c')
+ src += Glob('../../../../libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd.c')
+ src += Glob('../../../../libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_hal_pcd_ex.c')
+ src += Glob('../../../../libraries/STM32H7xx_HAL/STM32H7xx_HAL_Driver/Src/stm32h7xx_ll_usb.c')
+ CPPDEFINES += ['STM32H7']
+
+# USB HOST
+if GetDepend(['USB_STACK_USING_HOST']):
+ pass;
+
+group = DefineGroup('usb_stack', src, depend = ['PKG_USING_USB_STACK'], CPPPATH = path, CPPDEFINES = CPPDEFINES)
+
+Return('group')
+
diff --git a/docs/img/rtt_cdc_demo.png b/docs/img/rtt_cdc_demo.png
new file mode 100644
index 00000000..861669e1
--- /dev/null
+++ b/docs/img/rtt_cdc_demo.png
Binary files differ
diff --git a/docs/img/stm32cubemx.png b/docs/img/stm32cubemx.png
new file mode 100644
index 00000000..a6ca5078
--- /dev/null
+++ b/docs/img/stm32cubemx.png
Binary files differ
diff --git a/docs/img/stm32cubemx_clk.png b/docs/img/stm32cubemx_clk.png
new file mode 100644
index 00000000..41a7aae8
--- /dev/null
+++ b/docs/img/stm32cubemx_clk.png
Binary files differ
diff --git a/docs/rt-thread.md b/docs/rt-thread.md
new file mode 100644
index 00000000..ce00a0d0
--- /dev/null
+++ b/docs/rt-thread.md
@@ -0,0 +1,72 @@
+# RT-Thread package Userguide with usb stack
+
+[中文版](rt-thread_zh.md)
+
+To use usb stack package, you need to select it in the RT-Thread package manager. The specific path is as follows:
+
+```
+-> RT-Thread online packages
+ -> system packages
+ --- USB Stack: tiny and portable USB stack for embedded system with USB IP
+
+ USB STACK Options ---->
+ [ ] Enable usb high speed mode
+ [*] Enable usb device mode
+ [*] Enable usb cdc acm device
+ [ ] Enable usb hid device
+ [ ] Enable usb dfu device
+ [ ] Enable usb msc device
+ [ ] Enable usb hub device
+ [ ] Enable usb audio device
+ [ ] Enable usb video device
+
+ Version (latest) --->
+```
+
+## How to use
+
+### In STM32
+
+Please note that stm32 series have two usb ip. For usb ip, like stm32f0、stm32f1、stm32f3, for usb otg ip(as we know it is from **DesignWare**),like stm32f4、stm32f7 and so on.
+Currently,if you usb usb device on mcu with usb ip, recommend you to use dcd porting named **usb_dc_nohal.c**,otherwise use **usb_dc_hal.c**.In the future,**usb_dc_hal.c** will be droped.
+
+#### Use USB Device
+
+- Firstly,you should have a bsp project,and then go to `board\CubeMX_Config` directory, open file that suffix name with `.ioc` in **STM32CubeMX**.
+- Enable **USB** or **USB_OTG_FS** or **USB_OTG_HS** in **Connectivity** List,enable USB IRQ in **NVIC Setting**.
+
+![STM32CubeMX USB setting](img/stm32cubemx.png)
+
+- Enable USB Clock for 48Mhz in **Clock configuration**.
+
+![STM32CubeMX USB clock](img/stm32cubemx_clk.png)
+
+- Generate code.
+- Copy **SystemClock_Config** into **board.c**.
+- Copy **MX_USB_OTG_FS_PCD_Init** or **MX_USB_OTG_HS_PCD_Init** into **main.c** if you use **usb_dc_hal.c**.Also, USB Irq from **it.c** needs the same.
+- Implement **printf** or modify with **rt_kprintf** in **usb_utils.h**, usb stack needs.
+- Now we can call some functions provided by **usb_stack**.Your should register descriptors、interfaces and endpoint callback firstly, and then call `usb_dc_init`. Example is as follows:
+
+```
+int main(void)
+{
+ extern void cdc_init(void);
+ cdc_init();
+ extern void usb_dc_init(void);
+ usb_dc_init();
+ while (1)
+ {
+ rt_thread_mdelay(500);
+ }
+}
+```
+
+- How to register class you can go to [stm32 class examples](https://github.com/sakumisu/usb_stack/tree/master/demo/stm32/stm32f103c8t6/example) for a reference.
+
+#### CDC Demo Demonstration
+
+![CDC Demo](img/rtt_cdc_demo.png)
+
+#### Video manual
+
+If you have problem from steps above, you can see this video:[Use USB Stack in RT-Thread package manager](https://www.bilibili.com/video/BV1Ef4y1t73d?p=26)。 \ No newline at end of file
diff --git a/docs/rt-thread_zh.md b/docs/rt-thread_zh.md
new file mode 100644
index 00000000..2b5005b8
--- /dev/null
+++ b/docs/rt-thread_zh.md
@@ -0,0 +1,71 @@
+# USB Stack 在 RT-Thread package 中的使用
+
+[English Version](rt-thread.md)
+
+使用 USB Stack package 需要在 RT-Thread 的包管理器中选择它,具体路径如下:
+
+```
+-> RT-Thread online packages
+ -> system packages
+ --- USB Stack: tiny and portable USB stack for embedded system with USB IP
+
+ USB STACK Options ---->
+ [ ] Enable usb high speed mode
+ [*] Enable usb device mode
+ [*] Enable usb cdc acm device
+ [ ] Enable usb hid device
+ [ ] Enable usb dfu device
+ [ ] Enable usb msc device
+ [ ] Enable usb hub device
+ [ ] Enable usb audio device
+ [ ] Enable usb video device
+
+ Version (latest) --->
+```
+
+## 使用 USB Stack
+
+### 在 STM32 平台
+
+STM32 系列单片机有两种 USB IP,分别是 USB IP 和 USB OTG IP。其中 USB IP,例如 STM32F0、STM32F1、STM32F3等等,USB OTG IP(我们都知道用的是 **DesignWare** 公司的)的有 STM32F4、STM32F7、STM32H7等等。当前如果你需要使用 USB Device 功能,porting 接口提供了两种,一种是不带 hal 层的 **usb_dc_nohal.c**,一种是带 hal 层的 **usb_dc_hal.c**,如果你使用的是 USB IP系列,推荐用前者,否则用后者,需要注意的是后者在后面会删除,不使用 hal 版本。
+
+#### 使用 USB Device 功能
+
+- 首先,你需要有一个 bsp 工程,之后进入到 `board\CubeMX_Config` 目录下,使用 **STM32CubeMX** 打开后缀名为 `.ioc` 的文件。
+- 进入 **Connectivity** 选项,选择 **USB** 或者 **USB_OTG_FS** 或者 **USB_OTG_HS**,并使能 device 功能,在 **NVIC Setting** 中开启 USB 中断。
+
+![STM32CubeMX USB setting](img/stm32cubemx.png)
+
+- 在 **Clock configuration** 栏配置 USB 时钟为 48Mhz.
+
+![STM32CubeMX USB clock](img/stm32cubemx_clk.png)
+
+- 点击 **Generate code**。
+- 复制 **SystemClock_Config** 函数内容到 **board.c** 中。
+- 如果你使用的是 hal 版本,需要复制 **MX_USB_OTG_FS_PCD_Init** 或者 **MX_USB_OTG_HS_PCD_Init** 到你的应用程序中,比如 **main.c**,并且还需要从 **it.c** 中复制中断函数。
+- 实现 **printf** 函数或者将 **usb_utils.h** 中的 **printf** 改成 **rt_kprintf**,并添加 `#include <rtthread.h>`
+- 现在我们可以调用 USB Stack 中的函数来注册描述符、接口、端点中断,并调用 `usb_dc_init`,示例如下:
+
+```
+int main(void)
+{
+ extern void cdc_init(void);
+ cdc_init();
+ extern void usb_dc_init(void);
+ usb_dc_init();
+ while (1)
+ {
+ rt_thread_mdelay(500);
+ }
+}
+```
+
+- 关于如何注册 class 类可以参考 [stm32 class examples](https://github.com/sakumisu/usb_stack/tree/master/demo/stm32/stm32f103c8t6/example)。
+
+#### CDC demo 演示
+
+![CDC Demo](img/rtt_cdc_demo.png)
+
+#### 视频教程
+
+如果对上述步骤还有问题,可以参考 [协议栈在 RT-Thread 包管理器中的使用](https://www.bilibili.com/video/BV1Ef4y1t73d?p=26)。 \ No newline at end of file
diff --git a/docs/usb_host.md b/docs/usb_host.md
new file mode 100644
index 00000000..2d245c7f
--- /dev/null
+++ b/docs/usb_host.md
@@ -0,0 +1 @@
+# USB STACK API For host \ No newline at end of file