From f5e1d1c2bf4cbb13501f68e425dfe207b2163d26 Mon Sep 17 00:00:00 2001 From: jincheng Date: Thu, 29 Jul 2021 16:56:24 +0800 Subject: [PATCH] fix timer collision in role switch Closes https://github.com/espressif/esp-idf/issues/7203 --- components/bt/common/osi/alarm.c | 13 ++++++++++++ components/bt/common/osi/include/osi/alarm.h | 5 +++++ .../bt/host/bluedroid/bta/dm/bta_dm_act.c | 5 ++++- .../host/bluedroid/bta/include/bta/bta_sys.h | 1 + .../bt/host/bluedroid/bta/sys/bta_sys_main.c | 21 +++++++++++++++++++ 5 files changed, 44 insertions(+), 1 deletion(-) diff --git a/components/bt/common/osi/alarm.c b/components/bt/common/osi/alarm.c index c8bfc83ab7..27de488fe2 100644 --- a/components/bt/common/osi/alarm.c +++ b/components/bt/common/osi/alarm.c @@ -318,3 +318,16 @@ uint32_t osi_time_get_os_boottime_ms(void) { return (uint32_t)(esp_timer_get_time() / 1000); } + +bool osi_alarm_is_active(osi_alarm_t *alarm) +{ + assert(alarm != NULL); + assert(alarm_mutex != NULL); + bool is_active = false; + + osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT); + is_active = alarm->deadline_us > 0; + osi_mutex_unlock(&alarm_mutex); + + return is_active; +} \ No newline at end of file diff --git a/components/bt/common/osi/include/osi/alarm.h b/components/bt/common/osi/include/osi/alarm.h index a1d3fa8961..a674380d8a 100644 --- a/components/bt/common/osi/include/osi/alarm.h +++ b/components/bt/common/osi/include/osi/alarm.h @@ -20,6 +20,7 @@ #define _ALARM_H_ #include +#include #include "esp_timer.h" typedef struct alarm_t osi_alarm_t; @@ -77,4 +78,8 @@ period_ms_t osi_alarm_get_remaining_ms(const osi_alarm_t *alarm); uint32_t osi_time_get_os_boottime_ms(void); +// This function returns whether the |alarm| which encapsulated +// a one-shot timer is active or not +bool osi_alarm_is_active(osi_alarm_t *alarm); + #endif /*_ALARM_H_*/ diff --git a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c index bae09bea6c..9f981b00ea 100644 --- a/components/bt/host/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/host/bluedroid/bta/dm/bta_dm_act.c @@ -3822,7 +3822,10 @@ static void bta_dm_adjust_roles(BOOLEAN delay_role_switch) } else { bta_dm_cb.switch_delay_timer[i].p_cback = (TIMER_CBACK *)&bta_dm_delay_role_switch_cback; - bta_sys_start_timer(&bta_dm_cb.switch_delay_timer[i], 0, 500); + /* Start the timer if not active */ + if (!bta_sys_timer_is_active(&bta_dm_cb.switch_delay_timer[i])) { + bta_sys_start_timer(&bta_dm_cb.switch_delay_timer[i], 0, 500); + } } } diff --git a/components/bt/host/bluedroid/bta/include/bta/bta_sys.h b/components/bt/host/bluedroid/bta/include/bta/bta_sys.h index a466028b95..87359b5a9f 100644 --- a/components/bt/host/bluedroid/bta/include/bta/bta_sys.h +++ b/components/bt/host/bluedroid/bta/include/bta/bta_sys.h @@ -225,6 +225,7 @@ extern void bta_sys_sendmsg(void *p_msg); extern void bta_sys_start_timer(TIMER_LIST_ENT *p_tle, UINT16 type, INT32 timeout_ms); extern void bta_sys_stop_timer(TIMER_LIST_ENT *p_tle); extern void bta_sys_free_timer(TIMER_LIST_ENT *p_tle); +extern BOOLEAN bta_sys_timer_is_active(TIMER_LIST_ENT *p_tle); extern void bta_sys_disable(tBTA_SYS_HW_MODULE module); extern UINT32 bta_sys_get_remaining_ticks(TIMER_LIST_ENT *p_target_tle); diff --git a/components/bt/host/bluedroid/bta/sys/bta_sys_main.c b/components/bt/host/bluedroid/bta/sys/bta_sys_main.c index c495e14f09..439c13261c 100644 --- a/components/bt/host/bluedroid/bta/sys/bta_sys_main.c +++ b/components/bt/host/bluedroid/bta/sys/bta_sys_main.c @@ -638,6 +638,27 @@ UINT32 bta_sys_get_remaining_ticks(TIMER_LIST_ENT *p_target_tle) } +/******************************************************************************* +** +** Function bta_sys_timer_is_active +** +** Description Get info of one-shot timer is active or not. +** +** Returns true if timer is exist and active, false otherwise. +** +*******************************************************************************/ +BOOLEAN bta_sys_timer_is_active(TIMER_LIST_ENT *p_tle) +{ + assert(p_tle != NULL); + + osi_alarm_t *alarm = hash_map_get(bta_alarm_hash_map, p_tle); + if (alarm != NULL && osi_alarm_is_active(alarm)) { + return TRUE; + } + + return FALSE; +} + /******************************************************************************* ** ** Function bta_sys_stop_timer