From f9250ff60de7aa3efed6cf1fe9c60ac534e66e67 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Tue, 6 Mar 2018 14:41:56 +0100 Subject: [PATCH 1/5] nimble/ll: Allow to be late on RX when scanning X-Original-Commit: 178ff7a986ca139b1d776bad8050526f4dfaf18d --- nimble/controller/src/ble_ll_scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index b20cbfc99..51100cc1b 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -1001,7 +1001,7 @@ ble_ll_scan_start(struct ble_ll_scan_sm *scansm, struct ble_ll_sched_item *sch) rc = ble_phy_rx_set_start_time(os_cputime_get32() + g_ble_ll_sched_offset_ticks, 0); } - if (!rc) { + if (!rc || rc == BLE_PHY_ERR_RX_LATE) { /* Enable/disable whitelisting */ if (scanphy->scan_filt_policy & 1) { ble_ll_whitelist_enable(); From 176b8d8dce2ac5404a0349fd430765d2eae94b29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 7 Mar 2018 11:35:34 +0100 Subject: [PATCH 2/5] nimble/ll: Minor coding style fix X-Original-Commit: 09c3e68af9f41cb6aa5274c254648b721b6c7140 --- nimble/controller/src/ble_ll_scan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 51100cc1b..de3178f07 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -1379,7 +1379,7 @@ ble_ll_scan_event_proc(struct os_event *ev) case BLE_LL_STATE_ADV: case BLE_LL_STATE_CONNECTION: start_scan = 0; - break; + break; case BLE_LL_STATE_INITIATING: /* Must disable PHY since we will move to a new channel */ ble_phy_disable(); From ef48541d0988956d8746a7c6f510a1ef2b53b989 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Tue, 6 Mar 2018 14:43:14 +0100 Subject: [PATCH 3/5] nimble/ll: Improve extended scanner for both PHYs This patch simplify a bit scanner core and make sure to reuse all available bandwith when scanning for two PHYs is requested X-Original-Commit: 1efe9e5a084373104eda914caba8252b054ddb27 --- nimble/controller/src/ble_ll_scan.c | 129 ++++++++++++++-------------- 1 file changed, 66 insertions(+), 63 deletions(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index de3178f07..d62620cd1 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -1244,9 +1244,9 @@ ble_ll_scan_switch_phy(struct ble_ll_scan_sm *scansm) * * @param arg */ -static uint32_t +static bool ble_ll_scan_start_next_phy(struct ble_ll_scan_sm *scansm, - uint32_t next_event_time) + uint32_t *next_event_time) { struct ble_ll_scan_params *cur_phy; struct ble_ll_scan_params *next_phy; @@ -1256,35 +1256,33 @@ ble_ll_scan_start_next_phy(struct ble_ll_scan_sm *scansm, /* Lets check if we want to switch to other PHY */ if (scansm->cur_phy == scansm->next_phy || scansm->next_phy == PHY_NOT_CONFIGURED) { - return next_event_time; + return false; } cur_phy = &scansm->phy_data[scansm->cur_phy]; next_phy = &scansm->phy_data[scansm->next_phy]; - cur_phy->next_event_start = next_event_time; + /* Store next event for current phy */ + cur_phy->next_event_start = *next_event_time; - if ((int32_t)(next_phy->next_event_start - next_event_time)< 0) { - /* Other PHY already wanted to scan. Allow it */ - ble_ll_scan_switch_phy(scansm); - now = os_cputime_get32(); - if ((int32_t)(next_phy->next_event_start - now) <= 0) { - /* Start with new channel only if PHY was scanning already */ - if (next_phy->next_event_start != 0) { - next_phy->scan_chan = - ble_ll_scan_get_next_adv_prim_chan(next_phy->scan_chan); - } - next_phy->scan_win_start_time = now; - win = os_cputime_usecs_to_ticks(next_phy->scan_window * - BLE_HCI_SCAN_ITVL); + /* Other PHY already wanted to scan. Allow it */ + ble_ll_scan_switch_phy(scansm); - next_phy->next_event_start = now + win; - ble_ll_scan_start(scansm, NULL); - } - next_event_time = next_phy->next_event_start; + now = os_cputime_get32(); + + /* Start with new channel only if PHY was scanning already */ + if (next_phy->next_event_start != 0) { + next_phy->scan_chan = + ble_ll_scan_get_next_adv_prim_chan(next_phy->scan_chan); } + next_phy->scan_win_start_time = now; + win = os_cputime_usecs_to_ticks(next_phy->scan_window * + BLE_HCI_SCAN_ITVL); - return next_event_time; + next_phy->next_event_start = now + win; + + *next_event_time = next_phy->next_event_start; + return true; } static void @@ -1369,6 +1367,16 @@ ble_ll_scan_event_proc(struct os_event *ev) next_event_time = win_start + scan_itvl; } +#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) + if (inside_window == 0 && + ble_ll_scan_start_next_phy(scansm, &next_event_time)) { + /* Check if we should start next phy. If so let's say we are inside + * the window + */ + inside_window = 1; + } +#endif + /* * If we are not in the standby state it means that the scheduled * scanning event was overlapped in the schedule. In this case all we do @@ -1403,6 +1411,41 @@ ble_ll_scan_event_proc(struct os_event *ev) break; } + if (start_scan && inside_window) { +#ifdef BLE_XCVR_RFCLK + xtal_state = ble_ll_xcvr_rfclk_state(); + if (xtal_state != BLE_RFCLK_STATE_SETTLED) { + if (xtal_state == BLE_RFCLK_STATE_OFF) { + xtal_ticks = g_ble_ll_data.ll_xtal_ticks; + } else { + xtal_ticks = ble_ll_xcvr_rfclk_time_till_settled(); + } + + /* + * Only bother if we have enough time to receive anything + * here. The next event time will turn off the clock. + */ + if (win != 0) { + if ((win - dt) <= xtal_ticks) { + goto done; + } + } + + /* + * If clock off, start clock. Set next event time to now plus + * the clock setting time. + */ + if (xtal_state == BLE_RFCLK_STATE_OFF) { + ble_ll_xcvr_rfclk_start_now(now); + } + next_event_time = now + xtal_ticks; + goto done; + } +#endif + ble_ll_scan_start(scansm, NULL); + goto done; + } + #ifdef BLE_XCVR_RFCLK if (inside_window == 0) { /* @@ -1427,47 +1470,7 @@ ble_ll_scan_event_proc(struct os_event *ev) } #endif - if (start_scan && inside_window) { -#ifdef BLE_XCVR_RFCLK - xtal_state = ble_ll_xcvr_rfclk_state(); - if (xtal_state != BLE_RFCLK_STATE_SETTLED) { - if (xtal_state == BLE_RFCLK_STATE_OFF) { - xtal_ticks = g_ble_ll_data.ll_xtal_ticks; - } else { - xtal_ticks = ble_ll_xcvr_rfclk_time_till_settled(); - } - - /* - * Only bother if we have enough time to receive anything - * here. The next event time will turn off the clock. - */ - if (win != 0) { - if ((win - dt) <= xtal_ticks) { - goto rfclk_not_settled; - } - } - - /* - * If clock off, start clock. Set next event time to now plus - * the clock setting time. - */ - if (xtal_state == BLE_RFCLK_STATE_OFF) { - ble_ll_xcvr_rfclk_start_now(now); - } - next_event_time = now + xtal_ticks; - goto rfclk_not_settled; - } -#endif - ble_ll_scan_start(scansm, NULL); - } else { -#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV) - next_event_time = ble_ll_scan_start_next_phy(scansm, next_event_time); -#endif - } - -#ifdef BLE_XCVR_RFCLK -rfclk_not_settled: -#endif +done: OS_EXIT_CRITICAL(sr); os_cputime_timer_start(&scansm->scan_timer, next_event_time); } From 6054b773942b603d309b32d89b9b6dab6e2309d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Tue, 6 Mar 2018 14:45:41 +0100 Subject: [PATCH 4/5] nimble/ll: Support scan on two PHYs when continous scanning requested X-Original-Commit: 6258e862c56f2b99ef1682f1fc6c200ce36986ab --- nimble/controller/src/ble_ll_scan.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index d62620cd1..5f7fe5929 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2691,14 +2691,16 @@ ble_ll_set_ext_scan_params(uint8_t *cmd) } #endif - /* For now we don't accept request for continuous scan if 2 PHYs are - * requested. + /* If host requests continuous scan for 2 PHYs, we double scan interval + * and split it for two equal scan windows between 2 PHYs */ - if ((cmd[2] == - (BLE_HCI_LE_PHY_1M_PREF_MASK | BLE_HCI_LE_PHY_CODED_PREF_MASK)) && + if ((coded->configured && uncoded->configured) && ((uncoded->scan_itvl == uncoded->scan_window) || (coded->scan_itvl == coded-> scan_window))) { - return BLE_ERR_INV_HCI_CMD_PARMS; + + uncoded->scan_itvl *= 2; + coded-> scan_itvl = uncoded->scan_itvl; + coded->scan_window = uncoded->scan_window; } memcpy(g_ble_ll_scan_params, new_params, sizeof(new_params)); From 5eebc3b15e2d750c41550753572b82b37cd9a894 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Rymanowski?= Date: Wed, 7 Mar 2018 11:44:28 +0100 Subject: [PATCH 5/5] nimble/ll: Fix extended connect when using both PHYs for scanning When host is using extended connect, scan parameters is a recomendation for the controller. Nimble usually follow it but in case host requests both CODED and UNCODED PHY for primary scan PHY and choose parameters which saying "continous scan" on both PHYs, controller will split time between both PHYs. X-Original-Commit: fc457f1c0791bbc1493a01b9170b5d04d69e354a --- nimble/controller/src/ble_ll_scan.c | 35 ++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 11 deletions(-) diff --git a/nimble/controller/src/ble_ll_scan.c b/nimble/controller/src/ble_ll_scan.c index 5f7fe5929..76559ef85 100644 --- a/nimble/controller/src/ble_ll_scan.c +++ b/nimble/controller/src/ble_ll_scan.c @@ -2874,7 +2874,8 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, struct ble_ll_scan_sm **sm) { struct ble_ll_scan_sm *scansm; - struct ble_ll_scan_params *scanphy; + struct ble_ll_scan_params *uncoded; + struct ble_ll_scan_params *coded; struct hci_ext_conn_params *params; int rc; @@ -2886,23 +2887,23 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, if (hcc->init_phy_mask & BLE_PHY_MASK_1M) { params = &hcc->params[0]; - scanphy = &scansm->phy_data[PHY_UNCODED]; + uncoded = &scansm->phy_data[PHY_UNCODED]; - scanphy->scan_itvl = params->scan_itvl; - scanphy->scan_window = params->scan_window; - scanphy->scan_type = BLE_SCAN_TYPE_INITIATE; - scanphy->scan_filt_policy = hcc->filter_policy; + uncoded->scan_itvl = params->scan_itvl; + uncoded->scan_window = params->scan_window; + uncoded->scan_type = BLE_SCAN_TYPE_INITIATE; + uncoded->scan_filt_policy = hcc->filter_policy; scansm->cur_phy = PHY_UNCODED; } if (hcc->init_phy_mask & BLE_PHY_MASK_CODED) { params = &hcc->params[2]; - scanphy = &scansm->phy_data[PHY_CODED]; + coded = &scansm->phy_data[PHY_CODED]; - scanphy->scan_itvl = params->scan_itvl; - scanphy->scan_window = params->scan_window; - scanphy->scan_type = BLE_SCAN_TYPE_INITIATE; - scanphy->scan_filt_policy = hcc->filter_policy; + coded->scan_itvl = params->scan_itvl; + coded->scan_window = params->scan_window; + coded->scan_type = BLE_SCAN_TYPE_INITIATE; + coded->scan_filt_policy = hcc->filter_policy; if (scansm->cur_phy == PHY_NOT_CONFIGURED) { scansm->cur_phy = PHY_CODED; } else { @@ -2910,6 +2911,18 @@ ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc, } } + /* If host request for continuous scan if 2 PHYs are requested, we split + * time on two + */ + if ((scansm->next_phy != PHY_NOT_CONFIGURED) && + ((uncoded->scan_itvl == uncoded->scan_window) || + (coded->scan_itvl == coded-> scan_window))) { + + uncoded->scan_itvl *= 2; + coded-> scan_itvl = uncoded->scan_itvl; + coded->scan_window = uncoded->scan_window; + } + rc = ble_ll_scan_sm_start(scansm); if (sm == NULL) { return rc;