11/*
2- * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
2+ * SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
33 *
44 * SPDX-License-Identifier: Apache-2.0
55 */
@@ -34,6 +34,9 @@ static volatile uint32_t count;
3434// Lock variable to create a blocked task scenario
3535static volatile SemaphoreHandle_t task_mutex ;
3636
37+ // Semaphore to synchronize yield test tasks
38+ static SemaphoreHandle_t yield_sync_sem ;
39+
3740// This helper macro is used to store the task id atomically
3841#define STORE_TASK_ID (task_id ) ({ \
3942 portENTER_CRITICAL(&idx_lock); \
@@ -56,10 +59,11 @@ static void yield_task1(void *arg)
5659 /* Store task_id in the sequence array */
5760 STORE_TASK_ID (task_id );
5861
59- /* Notify the yield_task2 to run */
60- task_sequence_ready = true;
62+ /* Give semaphore to unblock yield_task2, making it READY (not just setting a flag).
63+ * This ensures task2 is in the ready queue when we yield. */
64+ xSemaphoreGive (yield_sync_sem );
6165
62- /* Yield */
66+ /* Yield - now task2 is guaranteed to be READY and should run next */
6367 taskYIELD ();
6468
6569 /* Increment task count to notify unity task */
@@ -73,10 +77,9 @@ static void yield_task2(void *arg)
7377{
7478 uint32_t task_id = (uint32_t )arg ;
7579
76- /* Wait for the other task to run for the test to begin */
77- while (!task_sequence_ready ) {
78- vTaskDelay (10 );
79- };
80+ /* Block on semaphore - this ensures task1 runs first and we don't poll.
81+ * When task1 gives the semaphore, we transition directly to READY state. */
82+ xSemaphoreTake (yield_sync_sem , portMAX_DELAY );
8083
8184 /* Store task_id in the sequence array */
8285 STORE_TASK_ID (task_id );
@@ -108,9 +111,16 @@ TEST_CASE("Task yield must run the next ready task of the same priority", "[free
108111 /* Reset task sequence flag */
109112 task_sequence_ready = false;
110113
111- /* Create test tasks */
112- xTaskCreatePinnedToCore (yield_task1 , "yield_task1" , 2048 , (void * )1 , UNITY_FREERTOS_PRIORITY - 1 , NULL , UNITY_FREERTOS_CPU );
114+ /* Create semaphore for synchronization - start empty so task2 blocks */
115+ yield_sync_sem = xSemaphoreCreateBinary ();
116+ TEST_ASSERT_NOT_NULL (yield_sync_sem );
117+
118+ /* Create test tasks - order matters!
119+ * Task2 is created first and will immediately block on the semaphore.
120+ * Task1 is created second and will run first since task2 is blocked. */
113121 xTaskCreatePinnedToCore (yield_task2 , "yield_task2" , 2048 , (void * )2 , UNITY_FREERTOS_PRIORITY - 1 , NULL , UNITY_FREERTOS_CPU );
122+ vTaskDelay (1 ); /* Ensure task2 has blocked on semaphore before creating task1 */
123+ xTaskCreatePinnedToCore (yield_task1 , "yield_task1" , 2048 , (void * )1 , UNITY_FREERTOS_PRIORITY - 1 , NULL , UNITY_FREERTOS_CPU );
114124
115125 /* Wait for the tasks to finish up */
116126 while (count != 2 ) {
@@ -122,6 +132,9 @@ TEST_CASE("Task yield must run the next ready task of the same priority", "[free
122132 /* Verify that the yield is successful and the next ready task is run */
123133 TEST_ASSERT_EQUAL (1 , task_yield_sequence [idx ++ ]);
124134 TEST_ASSERT_EQUAL (2 , task_yield_sequence [idx ++ ]);
135+
136+ /* Clean up semaphore */
137+ vSemaphoreDelete (yield_sync_sem );
125138}
126139
127140/*
0 commit comments