forked from espressif/esp-idf
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:
committed by
Sudeep Mohanty
parent
4dbfed1b77
commit
d5d7bb61e5
@@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user