From 1e616eeb84eb2aa796608b8cc4dc3d248170597c Mon Sep 17 00:00:00 2001 From: Sudeep Mohanty Date: Mon, 28 Apr 2025 16:42:40 +0200 Subject: [PATCH] fix(newlib): Fixed an issue where usleep() could consume more CPU cycles The following changes are made in this commit: 1. This commit updates the implementation of usleep() to now always yield CPU time if undergoing a multi-tick sleep. This reduces the accuracy of usleep() but in turn allows the scheduler to schedule different tasks. 2. The commit also updates the MCPWM unit test which fails due to the change in the behavior of usleep(). Closes: https://github.com/espressif/esp-idf/pull/15132 --- .../legacy_mcpwm_driver/main/test_legacy_mcpwm.c | 2 +- components/newlib/src/time.c | 13 +++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/components/driver/test_apps/legacy_mcpwm_driver/main/test_legacy_mcpwm.c b/components/driver/test_apps/legacy_mcpwm_driver/main/test_legacy_mcpwm.c index 1526620f7c..c9270b2459 100644 --- a/components/driver/test_apps/legacy_mcpwm_driver/main/test_legacy_mcpwm.c +++ b/components/driver/test_apps/legacy_mcpwm_driver/main/test_legacy_mcpwm.c @@ -172,7 +172,7 @@ static uint32_t pcnt_get_pulse_number(pcnt_unit_handle_t pwm_pcnt_unit, int capt int count_value = 0; TEST_ESP_OK(pcnt_unit_clear_count(pwm_pcnt_unit)); TEST_ESP_OK(pcnt_unit_start(pwm_pcnt_unit)); - usleep(capture_window_ms * 1000); + vTaskDelay(pdMS_TO_TICKS(capture_window_ms)); TEST_ESP_OK(pcnt_unit_stop(pwm_pcnt_unit)); TEST_ESP_OK(pcnt_unit_get_count(pwm_pcnt_unit, &count_value)); printf("count value: %d\r\n", count_value); diff --git a/components/newlib/src/time.c b/components/newlib/src/time.c index 3dfbc99115..1f609422fb 100644 --- a/components/newlib/src/time.c +++ b/components/newlib/src/time.c @@ -219,12 +219,13 @@ int usleep(useconds_t us) do { vTaskDelay((((target_us - now_us) + us_per_tick - 1) / us_per_tick)); now_us = esp_time_impl_get_time(); - /* If the time left until the target is less than 1 tick, then we use ROM delay to fill the gap */ - uint64_t time_left = target_us - now_us; - if (time_left != 0 && time_left < us_per_tick) { - esp_rom_delay_us(time_left); - break; - } + /* It is possible that the time left until the target time is less + * than a tick period. However, we let usleep() to sleep for an + * entire tick period. This, could result in usleep() sleeping for + * a longer time than the requested time but that does not violate + * the spec of usleep(). Additionally, it allows FreeRTOS to schedule + * other tasks while the current task is sleeping. + */ } while (now_us < target_us); } return 0;