mirror of
https://github.com/espressif/esp-nimble.git
synced 2026-09-20 07:57:22 +00:00
nimble/ll: Fix recalculating rfclk start
ble_ll_xcvr_rfclk_timer_start() assumes that it should not reschedule rfclk if it's already scheduled before requested tick. This is correct since it may be called it different contexts, however when called from ble_ll_sched_rfclk_chk_restart() we expect that rfclk will be scheduled for a first item in scheduler and this may not work as expected. Consider following scenario (one of many): - connection is active - sync with periodic advertising is active - scaner is active - sync scan item is in scheduler - next connection event item is scheduled *after* above sync scan item At this point we have rfclk timer set to fire at sync scan item. And now interesting things will happen: - terminate sync which removes sync scan item from scheduler - disable scan If both of the above happen before scheduled connection event item, we have a problem. This is because when sync scan item was removed, we did not move rfclk timer to connection event item because rfclk code checked that it already has rfclk scheduled before requested time. This means rfclk will be enabled at the time of removed sync scan item, but it will not be rescheduled to connection event item since there is no scheduler item do do this. So far so good - we still have rfclk enabled. But then we have scan disable which disables rfclk since connection event item is apparently far enough in the future so this is allowed. As a result we do not have rfclk enabled for a connection event. To fix this we make sure that every time we reevaluate scheduler for rfclk change, we need to stop existing timer so it can be always started for a proper item.
This commit is contained in:
@@ -1608,6 +1608,15 @@ ble_ll_sched_rfclk_chk_restart(void)
|
||||
*/
|
||||
time_till_next = (int32_t)(next_time - os_cputime_get32());
|
||||
if (time_till_next > g_ble_ll_data.ll_xtal_ticks) {
|
||||
/*
|
||||
* XXX stop timer if already scheduled since it could be set for a
|
||||
* scheduler item which was removed prior to calling this func.
|
||||
* in such case we need to make sure we are set to proper item.
|
||||
*/
|
||||
if (g_ble_ll_data.ll_rfclk_is_sched) {
|
||||
g_ble_ll_data.ll_rfclk_is_sched = 0;
|
||||
os_cputime_timer_stop(&g_ble_ll_data.ll_rfclk_timer);
|
||||
}
|
||||
/* Restart the rfclk timer based on the next scheduled time */
|
||||
ble_ll_xcvr_rfclk_timer_start(next_time);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user