Skip to content

Commit c0e3d66

Browse files
committed
refactor(esp_tinyusb): runtime_config test applicaton, multitask access test
- Fixed concurrent access to the nb_of_success var from several tasks - Changed the logic of getting notification from the worker thread to sem_done - Added the test case for uninstall the tinyusb driver via several tasks - Added README.md
1 parent 63a4825 commit c0e3d66

File tree

2 files changed

+156
-20
lines changed

2 files changed

+156
-20
lines changed
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
| Supported Targets | ESP32-H4 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
2+
| ----------------- | -------- | -------- | -------- | -------- |
3+
4+
# Espressif's Additions to TinyUSB - Runtime Configuration Test Application
5+
6+
This directory contains Unity tests that validate Espressif-specific integration of TinyUSB.
7+
8+
The tests focus on:
9+
10+
- TinyUSB configuration helpers (default macros, per-port config).
11+
- USB Device descriptors (FS/HS, string descriptors, edge cases).
12+
- USB peripheral / PHY configuration for full-speed and high-speed.
13+
- TinyUSB task configuration (CPU pinning, invalid parameters).
14+
- Multitask access to the TinyUSB driver (concurrent installs).
15+
16+
The test prints a numbered menu, for example:
17+
18+
```
19+
(1) "Config: Default macros arguments" [runtime_config][default]
20+
(2) "Config: Full-speed (High-speed)" [runtime_config][full_speed]
21+
...
22+
```
23+
24+
You can run all tests by running `pytest` or select individual ones by name and number.
25+
26+
## Tags
27+
28+
Each test is tagged with categories and modes:
29+
30+
### Categories
31+
32+
- [runtime_config] – Tests focusing on `tinyusb_config_t` and runtime configuration.
33+
- [periph] – Tests that directly exercise the USB peripheral (USB OTG 1.1 or USB OTG 2.0).
34+
- [task] – Tests related to the dedicated TinyUSB task configuration.
35+
36+
### Speed / Mode
37+
38+
- [default] – Generic, target-agnostic.
39+
- [full_speed] – Tests specific to USB OTG 1.1 / Full-speed port.
40+
- [high_speed] – Tests specific to USB OTG 2.0 / High-speed port.
41+
42+
These tags can be used by test runners / CI to select or filter tests.

device/esp_tinyusb/test_apps/runtime_config/main/test_multitask_access.c

Lines changed: 114 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -29,28 +29,74 @@
2929

3030
#define MULTIPLE_THREADS_TASKS_NUM 5
3131

32-
static int nb_of_success = 0;
32+
static SemaphoreHandle_t sem_done = NULL;
33+
TaskHandle_t test_task_handles[MULTIPLE_THREADS_TASKS_NUM];
34+
35+
// Unlocked spinlock, ready to use
36+
static portMUX_TYPE _spinlock = portMUX_INITIALIZER_UNLOCKED;
37+
static volatile int nb_of_success = 0;
3338

3439
static void test_task_install(void *arg)
3540
{
36-
TaskHandle_t parent_task_handle = (TaskHandle_t)arg;
37-
41+
(void) arg;
3842
// Install TinyUSB driver
3943
tinyusb_config_t tusb_cfg = TINYUSB_DEFAULT_CONFIG(test_device_event_handler);
4044
tusb_cfg.phy.skip_setup = true; // Skip phy setup to allow multiple tasks to install the driver
4145

46+
// Wait to be started by main thread
47+
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
48+
4249
if (tinyusb_driver_install(&tusb_cfg) == ESP_OK) {
4350
test_device_wait();
4451
TEST_ASSERT_EQUAL(ESP_OK, tinyusb_driver_uninstall());
52+
taskENTER_CRITICAL(&_spinlock);
53+
nb_of_success++;
54+
taskEXIT_CRITICAL(&_spinlock);
55+
}
56+
57+
// Notify the parent task that the task completed the job
58+
xSemaphoreGive(sem_done);
59+
// Delete task
60+
vTaskDelete(NULL);
61+
}
62+
63+
64+
static void test_task_uninstall(void *arg)
65+
{
66+
// Wait to be started by main thread
67+
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
68+
69+
if (tinyusb_driver_uninstall() == ESP_OK) {
70+
taskENTER_CRITICAL(&_spinlock);
4571
nb_of_success++;
72+
taskEXIT_CRITICAL(&_spinlock);
4673
}
4774

4875
// Notify the parent task that the task completed the job
49-
xTaskNotifyGive(parent_task_handle);
76+
xSemaphoreGive(sem_done);
5077
// Delete task
5178
vTaskDelete(NULL);
5279
}
5380

81+
// USB PHY
82+
83+
static usb_phy_handle_t test_init_phy(void)
84+
{
85+
usb_phy_handle_t phy_hdl = NULL;
86+
usb_phy_config_t phy_conf = {
87+
.controller = USB_PHY_CTRL_OTG,
88+
.target = USB_PHY_TARGET_INT,
89+
.otg_mode = USB_OTG_MODE_DEVICE,
90+
};
91+
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_new_phy(&phy_conf, &phy_hdl), "Unable to install USB PHY ");
92+
return phy_hdl;
93+
}
94+
95+
static void test_deinit_phy(usb_phy_handle_t phy_hdl)
96+
{
97+
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_del_phy(phy_hdl), "Unable to delete USB PHY ");
98+
}
99+
54100
// ============================= Tests =========================================
55101

56102
/**
@@ -61,34 +107,82 @@ static void test_task_install(void *arg)
61107
*/
62108
TEST_CASE("Multitask: Install", "[runtime_config][full_speed][high_speed]")
63109
{
64-
usb_phy_handle_t phy_hdl = NULL;
65-
// Install the PHY externally
66-
usb_phy_config_t phy_conf = {
67-
.controller = USB_PHY_CTRL_OTG,
68-
.target = USB_PHY_TARGET_INT,
69-
.otg_mode = USB_OTG_MODE_DEVICE,
70-
};
71-
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_new_phy(&phy_conf, &phy_hdl), "Unable to install USB PHY ");
110+
usb_phy_handle_t phy_hdl = test_init_phy();
111+
112+
// Create counting semaphore to wait for all tasks to complete
113+
sem_done = xSemaphoreCreateCounting(MULTIPLE_THREADS_TASKS_NUM, 0);;
114+
TEST_ASSERT_NOT_NULL(sem_done);
72115

116+
// No task are running yet
73117
nb_of_success = 0;
118+
74119
// Create tasks that will start the driver
75120
for (int i = 0; i < MULTIPLE_THREADS_TASKS_NUM; i++) {
76-
TEST_ASSERT_EQUAL(pdTRUE, xTaskCreate(test_task_install,
121+
TEST_ASSERT_EQUAL(pdPASS, xTaskCreate(test_task_install,
77122
"InstallTask",
78123
4096,
79-
(void *) xTaskGetCurrentTaskHandle(),
124+
NULL,
80125
4 + i,
81-
NULL));
126+
&test_task_handles[i]));
127+
}
128+
129+
// Start all tasks
130+
for (int i = 0; i < MULTIPLE_THREADS_TASKS_NUM; i++) {
131+
xTaskNotifyGive(test_task_handles[i]);
132+
}
133+
134+
// Wait for all tasks to complete
135+
for (int i = 0; i < MULTIPLE_THREADS_TASKS_NUM; i++) {
136+
TEST_ASSERT_EQUAL_MESSAGE(pdTRUE, xSemaphoreTake(sem_done, pdMS_TO_TICKS(5000)), "Not all tasks completed in time");
82137
}
83138

84-
// Wait until all tasks are finished
85-
vTaskDelay(pdMS_TO_TICKS(5000));
86-
// Check if all tasks finished, we should get all notification from the tasks
87-
TEST_ASSERT_EQUAL_MESSAGE(MULTIPLE_THREADS_TASKS_NUM, ulTaskNotifyTake(pdTRUE, pdMS_TO_TICKS(5000)), "Not all tasks finished");
88139
// There should be only one task that was able to install the driver
89140
TEST_ASSERT_EQUAL_MESSAGE(1, nb_of_success, "Only one task should be able to install the driver");
90141
// Clean-up
91-
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, usb_del_phy(phy_hdl), "Unable to delete PHY");
142+
test_deinit_phy(phy_hdl);
143+
vSemaphoreDelete(sem_done);
92144
}
93145

146+
TEST_CASE("Multitask: Uninstall", "[runtime_config][full_speed][high_speed]")
147+
{
148+
usb_phy_handle_t phy_hdl = test_init_phy();
149+
// Create counting semaphore to wait for all tasks to complete
150+
sem_done = xSemaphoreCreateCounting(MULTIPLE_THREADS_TASKS_NUM, 0);
151+
TEST_ASSERT_NOT_NULL(sem_done);
152+
153+
// No task are running yet
154+
nb_of_success = 0;
155+
156+
// Install the driver once
157+
tinyusb_config_t tusb_cfg = TINYUSB_DEFAULT_CONFIG(test_device_event_handler);
158+
tusb_cfg.phy.skip_setup = true; // Skip phy setup to allow multiple tasks
159+
TEST_ASSERT_EQUAL_MESSAGE(ESP_OK, tinyusb_driver_install(&tusb_cfg), "Unable to install TinyUSB driver ");
160+
// Create tasks that will uninstall the driver
161+
for (int i = 0; i < MULTIPLE_THREADS_TASKS_NUM; i++) {
162+
TEST_ASSERT_EQUAL(pdPASS, xTaskCreate(test_task_uninstall,
163+
"UninstallTask",
164+
4096,
165+
NULL,
166+
4 + i,
167+
&test_task_handles[i]));
168+
}
169+
170+
// Start all tasks
171+
for (int i = 0; i < MULTIPLE_THREADS_TASKS_NUM; i++) {
172+
xTaskNotifyGive(test_task_handles[i]);
173+
}
174+
// Wait for all tasks to complete
175+
for (int i = 0; i < MULTIPLE_THREADS_TASKS_NUM; i++) {
176+
TEST_ASSERT_EQUAL_MESSAGE(pdTRUE, xSemaphoreTake(sem_done, pdMS_TO_TICKS(5000)), "Not all tasks completed in time");
177+
}
178+
179+
// There should be only one task that was able to uninstall the driver
180+
TEST_ASSERT_EQUAL_MESSAGE(1, nb_of_success, "Only one task should be able to uninstall the driver");
181+
182+
// Clean-up
183+
test_deinit_phy(phy_hdl);
184+
vSemaphoreDelete(sem_done);
185+
}
186+
187+
94188
#endif // SOC_USB_OTG_SUPPORTED

0 commit comments

Comments
 (0)