Skip to content

Commit 769b231

Browse files
committed
Merge branch 'docs/add_tinyusb_docs' into 'master'
docs(tinyusb): add tinyusb guide docs See merge request ae_group/esp-iot-solution!1045
2 parents a367be5 + ef9c0ee commit 769b231

File tree

8 files changed

+889
-1
lines changed

8 files changed

+889
-1
lines changed

docs/en/usb/usb_overview/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ USB Host & Device
1616
USB Device Solution <usb_device_solutions>
1717
USB Self Power Device <usb_device_self_power>
1818
USB Device Set Const COM <usb_device_const_COM>
19+
TinyUSB Guide <tinyusb_guide>
20+
Native TinyUSB Development Guide <tinyusb_development_guide>
Lines changed: 233 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,233 @@
1+
2+
Developing with Native tinyusb
3+
--------------------------------
4+
5+
:link_to_translation:`zh_CN:[中文]`
6+
7+
This guide contains the following content:
8+
9+
.. contents:: Table of Contents
10+
:local:
11+
:depth: 2
12+
13+
This section will introduce how to use tinyusb components for development.
14+
15+
Project Directory
16+
~~~~~~~~~~~~~~~~~~~
17+
18+
First, create the following directory structure:
19+
20+
.. code:: C
21+
22+
project_name
23+
|
24+
|-- main
25+
| |-- CMakeLists.txt
26+
| |-- idf_component.yml
27+
| |-- main.c
28+
|
29+
|-- tusb
30+
|-- tusb_config.h
31+
|-- usb_descriptors.c
32+
|-- usb_descriptors.h
33+
34+
Add component dependencies in the main component of the project, referencing :ref:`espressif/tinyusb <espressif/tinyusb>`.
35+
36+
The tusb folder primarily contains files to be provided to tinyusb. We place them in a separate folder to ensure simplicity in dependency relationships. Then, add the following statements in the ``main/CMakeLists.txt`` file (after idf_component_register):
37+
38+
.. code:: C
39+
40+
# espressif__tinyusb should match the current tinyusb dependency name
41+
idf_component_get_property(tusb_lib espressif__tinyusb COMPONENT_LIB)
42+
43+
target_include_directories(${tusb_lib} PUBLIC "${COMPONENT_DIR}/tusb")
44+
target_sources(${tusb_lib} PUBLIC "${COMPONENT_DIR}/tusb/usb_descriptors.c")
45+
46+
.. note::
47+
Regarding reverse dependency issues, since the project needs to depend on tinyusb and provide header files to tinyusb, it inevitably leads to reverse dependency problems. Currently, this can be resolved by directly compiling all key files of tinyusb into the main component.
48+
49+
tusb_config.h File
50+
~~~~~~~~~~~~~~~~~~~
51+
52+
Most of tinyusb's functionalities are controlled through macros, so we need to declare the required functionalities in the ``tusb_config.h`` file. Here are some key macros:
53+
54+
**System Settings Macros**:
55+
56+
- **CFG_TUSB_RHPORT0_MODE**: Defines the connection method and speed to the USB Phy. The following method indicates a USB device with USB full speed.
57+
58+
.. code:: C
59+
60+
#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_FULL_SPEED)
61+
62+
- **ESP_PLATFORM**: This macro needs to be enabled when using the esp-idf platform for compilation.
63+
64+
- **CFG_TUSB_OS**: Defines the operating system for tinyusb. If using FreeRTOS, this macro needs to be enabled. It can also be disabled if not using an OS.
65+
66+
.. code:: C
67+
68+
#define CFG_TUSB_OS OPT_OS_FREERTOS
69+
70+
- **CFG_TUSB_OS_INC_PATH**: In ESP-IDF, it requires adding the "freertos/" prefix in the include path.
71+
72+
.. code:: C
73+
74+
#define CFG_TUSB_OS_INC_PATH freertos/
75+
76+
- **CFG_TUSB_DEBUG**: Enables the LOG print level of tinyusb. There are three levels in total.
77+
78+
.. code:: C
79+
80+
#define CFG_TUSB_DEBUG 0
81+
82+
- **CFG_TUD_ENABLED**: Set to 1 to enable tinyusb device functionality.
83+
84+
- **CFG_TUSB_MEM_SECTION**: This macro can be enabled to allocate tinyusb memory to a specific memory section.
85+
86+
- **CFG_TUSB_MEM_ALIGN**: Defines the memory alignment method.
87+
88+
.. code:: C
89+
90+
#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
91+
92+
**USB Device Macros**:
93+
94+
- **CFG_TUD_ENDPOINT0_SIZE**: Defines the maximum packet size for endpoint 0.
95+
96+
**USB Class Macros**:
97+
98+
Here, using the UVC Class as an example, each USB Class has its own macros:
99+
100+
- **CFG_TUD_VIDEO**: Configures the number of video control interfaces.
101+
102+
- **CFG_TUD_VIDEO_STREAMING**: Configures the number of video streaming interfaces.
103+
104+
Refer to the following file examples:
105+
106+
- :example_file:`../components/usb/usb_device_uac/tusb/tusb_config.h`
107+
- :example_file:`../components/usb/usb_device_uvc/tusb/tusb_config.h`
108+
- :example_file:`/usb/device/usb_hid_device/hid_device/tusb_config.h`
109+
110+
usb_descriptors.h File (Optional)
111+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
112+
113+
This file is mainly used to place custom USB descriptors. Tinyusb provides many descriptor templates, but if they do not meet your needs, you need to define your own set of USB descriptors. Note that it is best to use the predefined descriptors in tinyusb, as it makes descriptor assembly and length calculation more convenient.
114+
115+
Refer to the following file examples:
116+
117+
- :example_file:`../components/usb/usb_device_uac/tusb/usb_descriptors.h`
118+
- :example_file:`../components/usb/usb_device_uvc/tusb/usb_descriptors.h`
119+
- :example_file:`/usb/device/usb_hid_device/hid_device/usb_descriptors.h`
120+
121+
usb_descriptors.c File
122+
~~~~~~~~~~~~~~~~~~~~~~~
123+
124+
This file primarily implements several weak functions for obtaining descriptors, such as getting the device descriptor, configuration descriptor, and string descriptor.
125+
126+
.. code:: C
127+
128+
uint8_t const *tud_descriptor_device_cb(void);
129+
130+
uint8_t const *tud_descriptor_configuration_cb(uint8_t index);
131+
132+
uint16_t const *tud_descriptor_string_cb(uint8_t index, uint16_t langid);
133+
134+
Points to Note:
135+
136+
- The length of the configuration descriptor must equal the actual length.
137+
- The endpoint numbers used in the configuration descriptor's endpoint descriptors must not overlap.
138+
139+
Refer to the following file examples:
140+
141+
- :example_file:`../components/usb/usb_device_uvc/tusb/usb_descriptors.c`
142+
- :example_file:`../components/usb/usb_device_uac/tusb/usb_descriptors.c`
143+
- :example_file:`/usb/device/usb_hid_device/hid_device/usb_descriptors.c`
144+
145+
Initializing USB Phy
146+
~~~~~~~~~~~~~~~~~~~~
147+
148+
To initialize the internal USB Phy:
149+
150+
.. code:: C
151+
152+
static void usb_phy_init(void)
153+
{
154+
// Configure USB PHY
155+
usb_phy_config_t phy_conf = {
156+
.controller = USB_PHY_CTRL_OTG,
157+
.otg_mode = USB_OTG_MODE_DEVICE,
158+
.target = USB_PHY_TARGET_INT,
159+
};
160+
usb_new_phy(&phy_conf, &s_uvc_device.phy_hdl);
161+
}
162+
163+
If using an external USB Phy, refer to :ref:`external_phy`.
164+
165+
Initializing the TinyUSB Stack
166+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
167+
168+
Use the following code:
169+
170+
.. code:: C
171+
172+
static void tusb_device_task(void *arg)
173+
{
174+
while (1) {
175+
tud_task();
176+
}
177+
}
178+
179+
int main(void) {
180+
usb_phy_init();
181+
bool usb_init = tusb_init();
182+
if (!usb_init) {
183+
ESP_LOGE(TAG, "USB Device Stack Init Fail");
184+
return ESP_FAIL;
185+
}
186+
xTaskCreatePinnedToCore(tusb_device_task, "TinyUSB", 4096, NULL, 5, NULL, 0);
187+
}
188+
189+
Device-Level Weak Functions
190+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
191+
192+
These functions allow you to handle events such as device insertion, removal, suspension, and resumption.
193+
194+
.. code:: C
195+
196+
// Invoked when the device is mounted
197+
void tud_mount_cb(void)
198+
{
199+
}
200+
201+
// Invoked when the device is unmounted
202+
void tud_umount_cb(void)
203+
{
204+
}
205+
206+
// Invoked when the device is suspended
207+
void tud_suspend_cb(bool remote_wakeup_en)
208+
{
209+
}
210+
211+
// Invoked when the USB bus is resumed
212+
void tud_resume_cb(void)
213+
{
214+
}
215+
216+
Implementing USB Class-Specific Callback Functions.
217+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
218+
219+
USB classes provide some weak functions to complete basic functions. Taking the UVC driver as an example, the source file is `video_device <https://github.com/hathach/tinyusb/blob/master/src/class/video/video_device.h>`.
220+
221+
By observing the API, it can be seen that the UVC Class provides two functions and one callback function:
222+
223+
.. code:: C
224+
225+
bool tud_video_n_streaming(uint_fast8_t ctl_idx, uint_fast8_t stm_idx);
226+
227+
bool tud_video_n_frame_xfer(uint_fast8_t ctl_idx, uint_fast8_t stm_idx, void *buffer, size_t bufsize);
228+
229+
TU_ATTR_WEAK void tud_video_frame_xfer_complete_cb(uint_fast8_t ctl_idx, uint_fast8_t stm_idx);
230+
231+
The ``tud_video_n_frame_xfer`` function is used to transfer a frame of image, and the ``tud_video_frame_xfer_complete_cb`` callback is used to check if the transfer is complete.
232+
233+
Additionally, different USB classes have special macro definitions to define software FIFO sizes or enable certain features. For example, the macro ``CFG_TUD_VIDEO_STREAMING_EP_BUFSIZE`` in the UVC Class is used to define the buffer size of the video streaming interface endpoint.

0 commit comments

Comments
 (0)