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
3439static 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 */
62108TEST_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