diff --git a/rt-thread-version/rt-thread-standard/_sidebar.md b/rt-thread-version/rt-thread-standard/_sidebar.md index 6f8962bace74f39e7c4e3f932d361ee68a5dcfa7..8c2a67b09ec10c32df33cedb7d87529e19805fd7 100644 --- a/rt-thread-version/rt-thread-standard/_sidebar.md +++ b/rt-thread-version/rt-thread-standard/_sidebar.md @@ -105,6 +105,9 @@ - [MicroPython C 模块扩展](/rt-thread-version/rt-thread-standard/packages-manual/micropython-docs/external_c_modules.md) - PikaScript 用户手册 - [PikaScript](/rt-thread-version/rt-thread-standard/packages-manual/pikascript-docs/introduction.md) + - TinyUSB 用户手册 + - [介绍](/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/introduction.md) + - [USB 设备](/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/device.md) - [更多软件包...](/rt-thread-version/rt-thread-standard/packages-manual/more.md) - 应用开发 - 开发环境搭建 diff --git a/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/device.md b/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/device.md new file mode 100644 index 0000000000000000000000000000000000000000..8981b7316351e13ed54fd110862c6199d54ee63b --- /dev/null +++ b/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/device.md @@ -0,0 +1,237 @@ +# USB 设备 + +USB 设备的配置项说明如下,用于配置设备描述符,配置描述符与字符串描述符。 + +| 配置项名称 | 说明 | +| ----------------- | ------------------------------------------------------------ | +| Device Vendor ID | 供应商 ID(VID,由 USB-IF 分配) | +| Device Product ID | 产品 ID(PID,由制造商分配) | +| Manufacturer name | 制造商描述 | +| Device name | 设备描述 | +| Endpoint 0 size | 端点 0 最大数据包大小(数据包的大小可以为 8 Bytes、16 Bytes、32 个 Bytes 和 64 Bytes) | +| Maximum current | 设备所需的最大电流 | + +# CDC + +**通信设备类 (CDC)** 实现了虚拟串口 (Virtual COM Port) 的功能,用户可以使用 CDC 设备模拟串口,与主机进行通信。 + +## 示例代码 + +```c +#include +#include +#include + +void cdc_example(void) +{ + uint8_t buffer[32]; + char ch; + + /* 判断端口是否打开 (DTR=1) */ + if (tud_cdc_connected()) + { + rt_memset(buffer, 0, 32); + + /* 发送字符串 */ + tud_cdc_write_str("please enter something: "); + /* 刷新发送缓冲区 */ + tud_cdc_write_flush(); + /* 清空读取缓冲区 */ + tud_cdc_read_flush(); + + for (int i = 0; i < 32; i++) + { + /* 判断当前是否有数据可读取 */ + while (!tud_cdc_available()) { rt_thread_mdelay(10); } + /* 读取一个字符 */ + ch = tud_cdc_read_char(); + *(buffer + i) = ch; + /* 字符回显 */ + tud_cdc_write_char(ch); + tud_cdc_write_flush(); + /* 按下回车结束输入 */ + if (ch == '\r') { break; } + } + tud_cdc_write_str("\r\nwhat you enter: "); + tud_cdc_write((const char *) buffer, 32); + tud_cdc_write_str("\r\n"); + tud_cdc_write_flush(); + } + else + { + rt_kprintf("please open port and make sure DTR=1\n"); + } +} +MSH_CMD_EXPORT(cdc_example, TinyUSB cdc example) +``` + +## 配置项说明 + +| 配置项名称 | 说明 | +| ---------------------------- | ------------------------------------------------- | +| Description of CDC | CDC 设备描述 | +| Notification endpoint number | 通知端点编号(Interrupt 类型,IN 端点) | +| Endpoint number | 数据传输端点编号(Bulk 类型,IN、OUT 共两个端点) | +| Rx buffer size | 接收缓冲区大小 | +| Tx buffer size | 发送缓冲区大小 | + +# MSC + +**大容量存储类 (MSC)** 主要用于访问设备的内部存储,常见的大容量存储设备有: + +- 外部硬盘 +- 外部 CD/DVD +- U 盘 +- 固态硬盘 +- 读卡器 + +对于 MSC,软件包已将相关函数与设备驱动框架对接,用户通常仅需编写少量代码,并指定用于大容量存储的块设备名称即可。 + +> [!NOTE] +> 注意:当块设备被挂载期间,由于 USB 主机与内核没有进行同步,需注意用户代码不能对块设备进行任何操作,否则会造成 **竞争**。在设备被挂载之前,应调用 `rt_device_close()` 关闭设备。并在设备卸载后重新打开块设备。如需要在设备挂载期间仍能访问块设备,应使用 MTP 协议(TinyUSB 暂不支持)。 + +## 配置项说明 + +| 配置项名称 | 说明 | +| ---------------------------------------- | ------------------------------------------------------------ | +| Description of MSC | MSC 设备描述 | +| SCSI VID | SCSI 供应商 ID | +| SCSI PID | SCSI 产品 ID | +| SCSI Product revision | SCSI 产品版本 | +| Endpoint number | 端点编号(Bulk 类型,IN、OUT 共两个端点) | +| Endpoint buffer size | 端点缓冲区大小,必须大于块设备扇区大小,通常 SPI Nor Flash 为 4 KBytes,SD 卡为 512 Bytes | +| The name of the block device used by MSC | 用于大容量存储设备的块设备名称 | + +# HID + +**人机接口设备(HID)** 通常用于允许人类与 PC 交互的设备。使用这些设备,主机能够对人类的输入(如鼠标的移动或按键)作出反应。这种反应必须迅速发生,以便用户不会注意到他的行动和预期的反馈之间的明显延迟。TinyUSB 预定义的 HID 设备如下: + +- 鼠标 +- 键盘 +- 游戏手柄 +- 用户控制设备 + +此外,还可自定义报文描述符用于特定应用程序。 + +## 示例代码 + +```c +#include +#include +#include + +#include +#include +#include + +#define CIRCLE_RADIUS 300 + +/* 字符键值转换表 */ +static const uint8_t conv_table[128][2] = { HID_ASCII_TO_KEYCODE }; +static struct rt_semaphore hid_sem; + +/* 报文发送完毕回调函数 */ +void tud_hid_report_complete_cb(uint8_t instance, uint8_t const* report, uint8_t len) +{ + (void) instance; + (void) report; + (void) len; + /* 使用信号量进行同步,确保报文不会因发送过快导致还未发送的报文被覆盖 */ + rt_sem_release(&hid_sem); +} + +static void hid_press_key(uint8_t modifier, uint8_t keycode) +{ + uint8_t keycode_array[6] = {0}; + + keycode_array[0] = keycode; + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, modifier, keycode_array); + rt_sem_take(&hid_sem, 100); + keycode_array[0] = 0; + tud_hid_keyboard_report(REPORT_ID_KEYBOARD, 0, keycode_array); + rt_sem_take(&hid_sem, 100); +} + +static void hid_type_str_fmt(const char *fmt, ...) +{ + uint8_t keycode; + uint8_t modifier; + uint32_t length; + va_list args; + char buffer[64]; + char chr; + + va_start(args, fmt); + rt_vsnprintf(buffer, 64, fmt, args); + + length = rt_strlen(buffer); + for (int i = 0; i < length; i++) + { + chr = buffer[i]; + if (conv_table[chr][0]) + { + modifier = KEYBOARD_MODIFIER_LEFTSHIFT; + } + else + { + modifier = 0; + } + keycode = conv_table[chr][1]; + hid_press_key(modifier, keycode); + } +} + +void hid_example(void) +{ + float last_x_pos = CIRCLE_RADIUS, x_pos; + float last_y_pos = 0, y_pos; + + /* 初始化信号量 */ + rt_sem_init(&hid_sem, "hid", 0, RT_IPC_FLAG_PRIO); + + if (tud_connected()) + { + /* 用鼠标画个圆 */ + for (int i = 0; i < 360; i++) + { + x_pos = cosf((float)i / 57.3F) * CIRCLE_RADIUS; + y_pos = sinf((float)i / 57.3F) * CIRCLE_RADIUS; + + tud_hid_mouse_report(REPORT_ID_MOUSE, 0, + (int8_t)(x_pos - last_x_pos), (int8_t)(y_pos - last_y_pos), 0, 0); + rt_sem_take(&hid_sem, 100); + + last_x_pos = x_pos; + last_y_pos = y_pos; + } + rt_thread_mdelay(500); + + /* 打开记事本并输入一些文字 */ + hid_press_key(KEYBOARD_MODIFIER_LEFTGUI, HID_KEY_R); + rt_thread_mdelay(500); + hid_type_str_fmt("notepad\n\n"); + rt_thread_mdelay(2000); + hid_type_str_fmt("This is RT-Thread TinyUSB demo.\n"); + } + else + { + rt_kprintf("please connect USB port\n"); + } + + rt_sem_detach(&hid_sem); +} +MSH_CMD_EXPORT(hid_example, TinyUSB hid example) +``` + +## 配置项说明 + +| 配置项名称 | 说明 | +| --------------------- | ----------------------------------- | +| Description of HID | HID 设备描述 | +| Endpoint number | 端点编号(Interrupt 类型,IN 端点) | +| Polling interval (ms) | 轮询间隔,单位为 **毫秒 (ms)** | +| Keyboard report | 使能键盘报文类型 | +| Mouse report | 使能鼠标报文类型 | +| Gamepad report | 使能游戏手柄报文类型 | +| Endpoint buffer size | 端点缓冲区大小 | + diff --git a/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/figures/env.png b/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/figures/env.png new file mode 100644 index 0000000000000000000000000000000000000000..8feb68cbabf1dc841f1db46b79b211927e6f233c Binary files /dev/null and b/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/figures/env.png differ diff --git a/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/figures/rt-thread-studio.png b/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/figures/rt-thread-studio.png new file mode 100644 index 0000000000000000000000000000000000000000..1bc9683f580e522d52bf063c67bcf57c940ec930 Binary files /dev/null and b/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/figures/rt-thread-studio.png differ diff --git a/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/introduction.md b/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/introduction.md new file mode 100644 index 0000000000000000000000000000000000000000..dab7effd720183eb8543b72f13ddf619c6c706d4 --- /dev/null +++ b/rt-thread-version/rt-thread-standard/packages-manual/tinyusb-docs/introduction.md @@ -0,0 +1,45 @@ +# TinyUSB 介绍 + +[TinyUSB](https://docs.tinyusb.org/en/latest/) 是一个开源的用于嵌入式系统的跨平台 USB Host/Device 协议栈,为了内存安全而设计,没有动态分配,同时也是线程安全的,所有中断事件都被推迟,然后在非 ISR 任务函数中处理,支持多种 MCU。目前 TinyUSB 的源代码托管在 [GitHub](https://github.com/hathach/tinyusb) 上。 + +在社区成员的努力下,通过对 TinyUSB 上游仓库进行 [移植](https://github.com/RT-Thread-packages/tinyusb),目前已成为 RT-Thread 软件包。 + +# 支持情况 + +目前软件包仅支持 USB Device 协议栈。 + +[支持的 MCU 与设备类](https://github.com/RT-Thread-packages/tinyusb/blob/master/rt-thread/README_ZH.md#21mcu) + +# 开始使用 + +1. ENV + + 软件包在 ENV 包管理器中的路径为: + + ![env](figures/env.png) + + > [!NOTE] + > 在 Keil MDK 中使用时,请选择 **ARM Clang** 编译器,或手动在编译选项中选中 **GNU Extensions**。 + +2. RT-Thread Studio + + 在 RT-Thread Studio 中,搜索 `TinyUSB` 即可将软件包添加至工程。 + + ![rt-thread-studio](figures/rt-thread-studio.png) + +# 配置项说明 + +| 配置项名称 | 说明 | +| ------------------------- | ------------------------------------------------------------ | +| TinyUSB thread stack size | TinyUSB 线程栈大小 | +| TinyUSB thread priority | TinyUSB 线程优先级 | +| Memory section name | 指定 USB 内存对应的 section。在部分 MCU 上,DMA 只能访问特定的 SRAM 区域,可使用此配置项指定链接的区域。 | +| Memory align size | USB 内存对齐大小 | +| Port number | USB 接口数量 | +| Port speed | USB 速度,可选择 **全速 (12 Mpbs)** 或 **高速 (480 Mbps)** | +| Using USB device | 使能 USB 设备栈 | +| TinyUSB debug level | 调试日志输出等级 | + +# 问题反馈 + +Issue: [RT-Thread-packages/tinyusb](https://github.com/RT-Thread-packages/tinyusb/issues)