fix(newlib): usleep returning early

This commit updates usleep() to always sleep for the required sleep
period or more. This fixes a bug where the usleep() could sleep for less
than the request sleep period.

Closes https://github.com/espressif/esp-idf/pull/15132
This commit is contained in:
Stephen Noonan
2025-01-03 16:47:19 -05:00
committed by Sudeep Mohanty
parent 4dbfed1b77
commit d5d7bb61e5

View File

@@ -207,10 +207,25 @@ int usleep(useconds_t us)
if (us < us_per_tick) {
esp_rom_delay_us((uint32_t) us);
} else {
/* since vTaskDelay(1) blocks for anywhere between 0 and portTICK_PERIOD_MS,
* round up to compensate.
*/
vTaskDelay((us + us_per_tick - 1) / us_per_tick);
/* vTaskDelay may return up to (n-1) tick periods due to the tick ISR
being asynchronous to the call. We must sleep at least the specified
time, or longer. Checking the monotonic clock allows making an
additional call to vTaskDelay when needed to ensure minimal time is
actually slept. Adding `us_per_tick - 1` prevents ever passing 0 to
vTaskDelay().
*/
uint64_t now_us = esp_time_impl_get_time();
uint64_t target_us = now_us + 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;
}
} while (now_us < target_us);
}
return 0;
}