Skip to content

Commit af5ddf0

Browse files
committed
Merge branch 'contrib/github_pr_14767_v5.4' into 'release/v5.4'
fix(gptimer): race on FSM state in gptimer_start() (GitHub PR) (v5.4) See merge request espressif/esp-idf!35134
2 parents fe3bb07 + fa3cdcc commit af5ddf0

File tree

3 files changed

+7
-5
lines changed

3 files changed

+7
-5
lines changed

components/esp_driver_gptimer/src/gptimer.c

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -336,13 +336,15 @@ esp_err_t gptimer_start(gptimer_handle_t timer)
336336
// which is possible to run along with this function, so we need to protect
337337
portENTER_CRITICAL_SAFE(&timer->spinlock);
338338
timer_ll_enable_alarm(timer->hal.dev, timer->timer_id, timer->flags.alarm_en);
339+
// Note here, if the alarm target is set very close to the current counter value
340+
// an alarm interrupt may be triggered very quickly after we start the timer
339341
timer_ll_enable_counter(timer->hal.dev, timer->timer_id, true);
342+
atomic_store(&timer->fsm, GPTIMER_FSM_RUN);
340343
portEXIT_CRITICAL_SAFE(&timer->spinlock);
341344
} else {
342-
ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_STATE, TAG, "timer is not enabled yet");
345+
ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_STATE, TAG, "timer is not ready for a new start");
343346
}
344347

345-
atomic_store(&timer->fsm, GPTIMER_FSM_RUN);
346348
return ESP_OK;
347349
}
348350

@@ -356,12 +358,12 @@ esp_err_t gptimer_stop(gptimer_handle_t timer)
356358
portENTER_CRITICAL_SAFE(&timer->spinlock);
357359
timer_ll_enable_counter(timer->hal.dev, timer->timer_id, false);
358360
timer_ll_enable_alarm(timer->hal.dev, timer->timer_id, false);
361+
atomic_store(&timer->fsm, GPTIMER_FSM_ENABLE);
359362
portEXIT_CRITICAL_SAFE(&timer->spinlock);
360363
} else {
361364
ESP_RETURN_ON_FALSE_ISR(false, ESP_ERR_INVALID_STATE, TAG, "timer is not running");
362365
}
363366

364-
atomic_store(&timer->fsm, GPTIMER_FSM_ENABLE);
365367
return ESP_OK;
366368
}
367369

docs/en/api-reference/peripherals/gptimer.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ Set up Alarm Action
8686

8787
For most of the use cases of GPTimer, you should set up the alarm action before starting the timer, except for the simple wall-clock scenario, where a free running timer is enough. To set up the alarm action, you should configure several members of :cpp:type:`gptimer_alarm_config_t` based on how you make use of the alarm event:
8888

89-
- :cpp:member:`gptimer_alarm_config_t::alarm_count` sets the target count value that triggers the alarm event. You should also take the counting direction into consideration when setting the alarm value. Specially, :cpp:member:`gptimer_alarm_config_t::alarm_count` and :cpp:member:`gptimer_alarm_config_t::reload_count` cannot be set to the same value when :cpp:member:`gptimer_alarm_config_t::auto_reload_on_alarm` is true, as keeping reload with a target alarm count is meaningless.
89+
- :cpp:member:`gptimer_alarm_config_t::alarm_count` sets the target count value that triggers the alarm event. You should also take the counting direction into consideration when setting the alarm value. Specially, :cpp:member:`gptimer_alarm_config_t::alarm_count` and :cpp:member:`gptimer_alarm_config_t::reload_count` cannot be set to the same value when :cpp:member:`gptimer_alarm_config_t::auto_reload_on_alarm` is true, as keeping reload with a target alarm count is meaningless. Please also note, because of the interrupt latency, it's not recommended to set the alarm period smaller than 5 us.
9090

9191
- :cpp:member:`gptimer_alarm_config_t::reload_count` sets the count value to be reloaded when the alarm event happens. This configuration only takes effect when :cpp:member:`gptimer_alarm_config_t::auto_reload_on_alarm` is set to true.
9292

docs/zh_CN/api-reference/peripherals/gptimer.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@
8686

8787
对于大多数通用定时器使用场景而言,应在启动定时器之前设置警报动作,但不包括简单的挂钟场景,该场景仅需自由运行的定时器。设置警报动作,需要根据如何使用警报事件来配置 :cpp:type:`gptimer_alarm_config_t` 的不同参数:
8888

89-
- :cpp:member:`gptimer_alarm_config_t::alarm_count` 设置触发警报事件的目标计数值。设置警报值时还需考虑计数方向。尤其是当 :cpp:member:`gptimer_alarm_config_t::auto_reload_on_alarm` 为 true 时,:cpp:member:`gptimer_alarm_config_t::alarm_count` 和 :cpp:member:`gptimer_alarm_config_t::reload_count` 不能设置为相同的值,因为警报值和重载值相同时没有意义。
89+
- :cpp:member:`gptimer_alarm_config_t::alarm_count` 设置触发警报事件的目标计数值。设置警报值时还需考虑计数方向。 :cpp:member:`gptimer_alarm_config_t::auto_reload_on_alarm` 为 ``true`` 时,:cpp:member:`gptimer_alarm_config_t::alarm_count` 和 :cpp:member:`gptimer_alarm_config_t::reload_count` 不能设置为相同的值,因为警报值和重载值相同时没有意义。请注意,由于中断延迟,不建议将警报周期设置为小于 5 微秒
9090

9191
- :cpp:member:`gptimer_alarm_config_t::reload_count` 代表警报事件发生时要重载的计数值。此配置仅在 :cpp:member:`gptimer_alarm_config_t::auto_reload_on_alarm` 设置为 true 时生效。
9292

0 commit comments

Comments
 (0)