The task dispatch method for the esp_timer could stall even if it is
armed if ther ISR dispatch alarm triggers close to the task dispatch.
This MR fixes a bug where the esp_timer cleared the incorrect cached
array timer index and subsequently the timer task is never woken up.
Closes https://github.com/espressif/esp-idf/issues/18808
print_timer_info advanced the dump cursor by snprintf's return value. When a timer line was truncated, snprintf returned the full would-be length, which could move the cursor past the heap buffer and wrap the remaining size before the next write. Add a bounded append helper that clamps truncation to the end of the buffer while preserving the NUL terminator.
On real hardware, ESP_TIMER_ISR callbacks run in a hardware interrupt
that preempts any FreeRTOS task. On the Linux simulator, there are no
real ISRs — the alarm is detected by a native pthread but was only
forwarded to the FreeRTOS timer_task via xTaskNotifyGive(). This meant
ISR-dispatch callbacks could be starved by higher-priority FreeRTOS
tasks, breaking components like the task watchdog that rely on
ISR-dispatch timers to detect scheduling starvation.
Move ISR-dispatch timer processing into the alarm pthread itself,
mirroring the hardware ISR path. The FreeRTOS timer_task is only
notified when no ISR-dispatch timer consumed the alarm. This is safe
because the Linux FreeRTOS port already handles vPortEnterCritical()
calls from non-FreeRTOS threads (bumps nesting counter without
blocking on scheduled-task checks).
Previously it would return ESP_ERR_INVALID_STATE, which meant that if called from
user-code before the system tries to initialize the timer then esp-idf would
fail to boot.
This could happen if a user wanted to use esp-timer from a cpp constructor.
Closes https://github.com/espressif/esp-idf/issues/9679
CONFIG_ESP_TIMER_ISR_AFFINITY can be equal to -1, whereas
ESP_SYSTEM_INIT_FN takes an uint16_t argument. To avoid overflow,
move the choice of init mask into source code and set the value
explicitly.
Similar to how the secondary init functions were already registered
via ESP_SYSTEM_INIT_FN, do the same for the core init functions.
This MR doesn't actually move the init functions into respective
components yet. This has to be carefully done in follow-up MRs.
Inadequate locking in the esp_timer component allowed corruption
of the s_timers linked list:
1. timer_armed(timer) returns false
2. another task arms the timer and adds it to s_timers
3. the list is locked
4. the timer is inserted into s_timers again
The last step results in a loop in the s_timers list, which causes
an infinite loop when iterated. This change always locks the
list before checking if the timer is already armed avoiding
the data race.
Timers, periodic or not, can now be restarted thanks to esp_timer_restart function.
This is done atomically, which can be used to feed a periodic timer, or simply change the period.
ESP32-C2 has a single group timer, thus it will use it for the interrupt watchdog,
which is more critical than the task watchdog. The latter is implement in
software thanks to the `esp_timer`component.
- For ESP32 | SPIRAM_MALLOC_ALWAYSINTERNAL=0
- Forced `esp_timer_create` to allocate resource from the internal memory
- WiFi/BT coexistence will sometimes arm/disarm timers from an ISR
where flash may be disabled. This can lead to a cache-based
exception as the timer instance will be located in the PSRAM.
This commit updates the visibility of various header files and cleans up
some unnecessary inclusions. Also, this commit removes certain header
include paths which were maintained for backward compatibility.
esp_timer:
Control flow issues (DEADCODE)
Execution cannot reach this statement: "break;".
protocomm_httpd:
(UNUSED_VALUE)
Assigning value from "cookie_session_id" to "cur_cookie_session_id" here, but that stored value is overwritten before it can be used.
esp_flash_api:
Null pointer dereferences (REVERSE_INULL)
Null-checking "chip" suggests that it may be null, but it has already been dereferenced on all paths leading to the check.
Added the following new APIs to the esp_timer module:
- esp_timer_get_period(): Returns the period of a timer in microseconds.
- esp_timer_get_expiry_time(): Returns the timeout value of a one-shot timer in microseconds.
Signed-off-by: Sudeep Mohanty <sudeep.mohanty@espressif.com>