Bluetooth: controller: split: Remove use of k_cpu_idle

Remove use of k_cpu_idle in controller, and refactor the
implementation used to start, wait and stop clocks needed
by the controller.

Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
Vinayak Kariappa Chettimada 2020-03-17 19:30:46 +05:30 committed by Carles Cufí
commit 915c510a0a
15 changed files with 188 additions and 113 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -26,6 +26,7 @@
#include "lll.h"
#include "lll_vendor.h"
#include "lll_clock.h"
#include "lll_internal.h"
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
@ -47,10 +48,6 @@ static struct {
} curr;
} event;
static struct {
struct device *clk;
} lll;
/* Entropy device */
static struct device *dev_entropy;
@ -128,7 +125,6 @@ static void swi_ull_low_nrf5_isr(void *arg)
int lll_init(void)
{
struct device *clk;
int err;
/* Get reference to entropy device */
@ -140,17 +136,12 @@ int lll_init(void)
/* Initialise LLL internals */
event.curr.abort_cb = NULL;
/* Initialize LF CLK */
clk = device_get_binding(DT_INST_0_NORDIC_NRF_CLOCK_LABEL);
if (!clk) {
return -ENODEV;
/* Initialize Clocks */
err = lll_clock_init();
if (err) {
return err;
}
clock_control_on(clk, CLOCK_CONTROL_NRF_SUBSYS_LF);
/* Initialize HF CLK */
lll.clk = clk;
err = init_reset();
if (err) {
return err;
@ -313,51 +304,6 @@ bool lll_is_done(void *param)
return !event.curr.abort_cb;
}
int lll_clk_on(void)
{
int err;
/* turn on radio clock in non-blocking mode. */
err = clock_control_on(lll.clk, CLOCK_CONTROL_NRF_SUBSYS_HF);
if (!err || err == -EINPROGRESS) {
DEBUG_RADIO_XTAL(1);
}
return err;
}
int lll_clk_on_wait(void)
{
int err;
/* turn on radio clock in blocking mode. */
err = clock_control_on(lll.clk, CLOCK_CONTROL_NRF_SUBSYS_HF);
while (clock_control_get_status(lll.clk, CLOCK_CONTROL_NRF_SUBSYS_HF) !=
CLOCK_CONTROL_STATUS_ON) {
k_cpu_idle();
}
DEBUG_RADIO_XTAL(1);
return err;
}
int lll_clk_off(void)
{
int err;
/* turn off radio clock in non-blocking mode. */
err = clock_control_off(lll.clk, CLOCK_CONTROL_NRF_SUBSYS_HF);
if (!err) {
DEBUG_RADIO_XTAL(0);
} else if (err == -EBUSY) {
DEBUG_RADIO_XTAL(1);
}
return err;
}
u32_t lll_evt_offset_get(struct evt_hdr *evt)
{
if (0) {

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -26,6 +26,7 @@
#include "lll.h"
#include "lll_vendor.h"
#include "lll_clock.h"
#include "lll_adv.h"
#include "lll_conn.h"
#include "lll_chan.h"
@ -105,7 +106,7 @@ void lll_adv_prepare(void *param)
struct lll_prepare_param *p = param;
int err;
err = lll_clk_on();
err = lll_hfclock_on();
LL_ASSERT(!err || err == -EINPROGRESS);
err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, p);
@ -134,7 +135,7 @@ static int prepare_cb(struct lll_prepare_param *prepare_param)
if (lll_is_stop(lll)) {
int err;
err = lll_clk_off();
err = lll_hfclock_off();
LL_ASSERT(!err || err == -EBUSY);
lll_done(NULL);
@ -270,7 +271,7 @@ static int is_abort_cb(void *next, int prio, void *curr,
*resume_prio = 0; /* TODO: */
/* Retain HF clk */
err = lll_clk_on();
err = lll_hfclock_on();
LL_ASSERT(!err || err == -EINPROGRESS);
return -EAGAIN;
@ -308,7 +309,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
/* NOTE: Else clean the top half preparations of the aborted event
* currently in preparation pipeline.
*/
err = lll_clk_off();
err = lll_hfclock_off();
LL_ASSERT(!err || err == -EBUSY);
lll_done(param);
@ -580,7 +581,7 @@ static void isr_cleanup(void *param)
radio_tmr_stop();
err = lll_clk_off();
err = lll_hfclock_off();
LL_ASSERT(!err || err == -EBUSY);
lll_done(NULL);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -15,25 +15,110 @@
#include "common/log.h"
#include "hal/debug.h"
void lll_clock_wait(void)
/* Clock setup timeouts are unlikely, below values are experimental */
#define LFCLOCK_TIMEOUT_MS 500
#define HFCLOCK_TIMEOUT_MS 2
static void clock_ready(struct device *dev, clock_control_subsys_t subsys,
void *user_data);
static struct device *dev;
int lll_clock_init(void)
{
int err;
dev = device_get_binding(DT_INST_0_NORDIC_NRF_CLOCK_LABEL);
if (!dev) {
return -ENODEV;
}
err = clock_control_on(dev, CLOCK_CONTROL_NRF_SUBSYS_LF);
return err;
}
int lll_clock_wait(void)
{
static bool done;
if (done) {
return;
return 0;
}
done = true;
struct device *clock =
device_get_binding(DT_INST_0_NORDIC_NRF_CLOCK_LABEL);
struct k_sem sem_clock_wait;
struct clock_control_async_data async_data = {
.cb = clock_ready,
.user_data = &sem_clock_wait,
};
int err;
LL_ASSERT(clock);
k_sem_init(&sem_clock_wait, 0, 1);
clock_control_on(clock, CLOCK_CONTROL_NRF_SUBSYS_LF);
while (clock_control_get_status(clock, CLOCK_CONTROL_NRF_SUBSYS_LF) !=
CLOCK_CONTROL_STATUS_ON) {
DEBUG_CPU_SLEEP(1);
k_cpu_idle();
DEBUG_CPU_SLEEP(0);
err = clock_control_async_on(dev, CLOCK_CONTROL_NRF_SUBSYS_LF,
&async_data);
if (err) {
return err;
}
err = k_sem_take(&sem_clock_wait, K_MSEC(LFCLOCK_TIMEOUT_MS));
return err;
}
int lll_hfclock_on(void)
{
int err;
/* turn on radio clock in non-blocking mode. */
err = clock_control_on(dev, CLOCK_CONTROL_NRF_SUBSYS_HF);
if (!err || err == -EINPROGRESS) {
DEBUG_RADIO_XTAL(1);
}
return err;
}
int lll_hfclock_on_wait(void)
{
struct k_sem sem_clock_wait;
struct clock_control_async_data async_data = {
.cb = clock_ready,
.user_data = &sem_clock_wait,
};
int err;
k_sem_init(&sem_clock_wait, 0, 1);
err = clock_control_async_on(dev, CLOCK_CONTROL_NRF_SUBSYS_HF,
&async_data);
LL_ASSERT(!err);
err = k_sem_take(&sem_clock_wait, K_MSEC(HFCLOCK_TIMEOUT_MS));
DEBUG_RADIO_XTAL(1);
return err;
}
int lll_hfclock_off(void)
{
int err;
/* turn off radio clock in non-blocking mode. */
err = clock_control_off(dev, CLOCK_CONTROL_NRF_SUBSYS_HF);
if (!err) {
DEBUG_RADIO_XTAL(0);
} else if (err == -EBUSY) {
DEBUG_RADIO_XTAL(1);
}
return err;
}
static void clock_ready(struct device *dev, clock_control_subsys_t subsys,
void *user_data)
{
k_sem_give(user_data);
}

View file

@ -1,7 +1,11 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
void lll_clock_wait(void);
int lll_clock_init(void);
int lll_clock_wait(void);
int lll_hfclock_on(void);
int lll_hfclock_on_wait(void);
int lll_hfclock_off(void);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -22,6 +22,7 @@
#include "pdu.h"
#include "lll.h"
#include "lll_clock.h"
#include "lll_conn.h"
#include "lll_internal.h"
@ -125,7 +126,7 @@ void lll_conn_abort_cb(struct lll_prepare_param *prepare_param, void *param)
/* NOTE: Else clean the top half preparations of the aborted event
* currently in preparation pipeline.
*/
err = lll_clk_off();
err = lll_hfclock_off();
LL_ASSERT(!err || err == -EBUSY);
lll_done(param);
@ -638,7 +639,7 @@ static void isr_cleanup(void *param)
radio_tmr_stop();
err = lll_clk_off();
err = lll_hfclock_off();
LL_ASSERT(!err || err == -EBUSY);
lll_done(NULL);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -7,9 +7,6 @@
int lll_prepare_done(void *param);
int lll_done(void *param);
bool lll_is_done(void *param);
int lll_clk_on(void);
int lll_clk_on_wait(void);
int lll_clk_off(void);
u32_t lll_evt_offset_get(struct evt_hdr *evt);
u32_t lll_preempt_calc(struct evt_hdr *evt, u8_t ticker_id,
u32_t ticks_at_event);

View file

@ -20,6 +20,7 @@
#include "lll.h"
#include "lll_vendor.h"
#include "lll_clock.h"
#include "lll_conn.h"
#include "lll_master.h"
#include "lll_chan.h"
@ -65,7 +66,7 @@ void lll_master_prepare(void *param)
struct lll_prepare_param *p = param;
int err;
err = lll_clk_on();
err = lll_hfclock_on();
LL_ASSERT(!err || err == -EINPROGRESS);
err = lll_prepare(lll_conn_is_abort_cb, lll_conn_abort_cb, prepare_cb,

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -25,6 +25,7 @@
#include "lll.h"
#include "lll_vendor.h"
#include "lll_clock.h"
#include "lll_scan.h"
#include "lll_conn.h"
#include "lll_chan.h"
@ -104,7 +105,7 @@ void lll_scan_prepare(void *param)
struct lll_prepare_param *p = param;
int err;
err = lll_clk_on();
err = lll_hfclock_on();
LL_ASSERT(!err || err == -EINPROGRESS);
err = lll_prepare(is_abort_cb, abort_cb, prepare_cb, 0, p);
@ -134,7 +135,7 @@ static int prepare_cb(struct lll_prepare_param *prepare_param)
if (lll_is_stop(lll)) {
int err;
err = lll_clk_off();
err = lll_hfclock_off();
LL_ASSERT(!err || err == -EBUSY);
lll_done(NULL);
@ -288,8 +289,8 @@ static int is_abort_cb(void *next, int prio, void *curr,
*resume_cb = resume_prepare_cb;
*resume_prio = 0; /* TODO: */
/* Retain HF clk */
err = lll_clk_on();
/* Retain HF clock */
err = lll_hfclock_on();
LL_ASSERT(!err || err == -EINPROGRESS);
return -EAGAIN;
@ -331,7 +332,7 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
/* NOTE: Else clean the top half preparations of the aborted event
* currently in preparation pipeline.
*/
err = lll_clk_off();
err = lll_hfclock_off();
LL_ASSERT(!err || err == -EBUSY);
lll_done(param);
@ -642,7 +643,7 @@ static void isr_cleanup(void *param)
radio_tmr_stop();
err = lll_clk_off();
err = lll_hfclock_off();
LL_ASSERT(!err || err == -EBUSY);
lll_done(NULL);

View file

@ -20,6 +20,7 @@
#include "lll.h"
#include "lll_vendor.h"
#include "lll_clock.h"
#include "lll_conn.h"
#include "lll_slave.h"
#include "lll_chan.h"
@ -65,7 +66,7 @@ void lll_slave_prepare(void *param)
struct lll_prepare_param *p = param;
int err;
err = lll_clk_on();
err = lll_hfclock_on();
LL_ASSERT(!err || err == -EINPROGRESS);
err = lll_prepare(lll_conn_is_abort_cb, lll_conn_abort_cb, prepare_cb,

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017-2019 Nordic Semiconductor ASA
* Copyright (c) 2017-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -20,6 +20,7 @@
#include "util/memq.h"
#include "lll.h"
#include "lll_clock.h"
#include "lll_internal.h"
#include "ll_test.h"
@ -172,7 +173,7 @@ static u32_t init(u8_t chan, u8_t phy, void (*isr)(void *))
cntr_start();
/* Setup resources required by Radio */
err = lll_clk_on_wait();
err = lll_hfclock_on_wait();
/* Reset Radio h/w */
radio_reset();
@ -334,7 +335,7 @@ u32_t ll_test_end(u16_t *num_rx)
radio_tmr_stop();
/* Release resources acquired for Radio */
err = lll_clk_off();
err = lll_hfclock_off();
LL_ASSERT(!err || err == -EBUSY);
/* Stop coarse timer */

View file

@ -38,6 +38,7 @@ endif()
if(CONFIG_BT_LL_SW_SPLIT)
zephyr_library_sources(
ll_sw/nordic/lll/lll.c
ll_sw/nordic/lll/lll_clock.c
)
if(CONFIG_BT_BROADCASTER)
zephyr_library_sources(
@ -51,7 +52,6 @@ if(CONFIG_BT_LL_SW_SPLIT)
endif()
if(CONFIG_BT_CONN)
zephyr_library_sources(
ll_sw/nordic/lll/lll_clock.c
ll_sw/nordic/lll/lll_conn.c
)
zephyr_library_sources_ifdef(

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -13,7 +13,7 @@
#include "common/log.h"
#include "hal/debug.h"
void lll_clock_wait(void)
int lll_clock_wait(void)
{
return 0;
}

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
void lll_clock_wait(void);
int lll_clock_wait(void);

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2016-2019 Nordic Semiconductor ASA
* Copyright (c) 2016-2020 Nordic Semiconductor ASA
* Copyright (c) 2016 Vinayak Kariappa Chettimada
*
* SPDX-License-Identifier: Apache-2.0
@ -66,7 +66,7 @@ static void ticker_stop_cb(u32_t ticks_at_expire, u32_t remainder, u16_t lazy,
void *param);
static void ticker_op_stop_cb(u32_t status, void *params);
static void disabled_cb(void *param);
static inline void conn_release(struct ll_adv_set *adv);
static void conn_release(struct ll_adv_set *adv);
#endif /* CONFIG_BT_PERIPHERAL */
static inline u8_t disable(u16_t handle);
@ -549,6 +549,7 @@ u8_t ll_adv_enable(u8_t enable)
struct ll_conn *conn;
struct lll_conn *conn_lll;
void *link;
int err;
if (lll->conn) {
return BT_HCI_ERR_CMD_DISALLOWED;
@ -704,7 +705,12 @@ u8_t ll_adv_enable(u8_t enable)
lll_hdr_init(&conn->lll, conn);
/* wait for stable clocks */
lll_clock_wait();
err = lll_clock_wait();
if (err) {
conn_release(adv);
return BT_HCI_ERR_HW_FAILURE;
}
}
#endif /* CONFIG_BT_PERIPHERAL */
@ -1218,7 +1224,7 @@ static void disabled_cb(void *param)
ll_rx_sched();
}
static inline void conn_release(struct ll_adv_set *adv)
static void conn_release(struct ll_adv_set *adv)
{
struct lll_conn *lll = adv->lll.conn;
memq_link_t *link;

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018-2019 Nordic Semiconductor ASA
* Copyright (c) 2018-2020 Nordic Semiconductor ASA
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -51,7 +51,8 @@
static void ticker_op_stop_scan_cb(u32_t status, void *params);
static void ticker_op_cb(u32_t status, void *params);
static void access_addr_get(u8_t access_addr[]);
static inline void access_addr_get(u8_t access_addr[]);
static inline void conn_release(struct ll_scan_set *scan);
u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
u8_t filter_policy, u8_t peer_addr_type,
@ -66,6 +67,7 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
memq_link_t *link;
u8_t access_addr[4];
u8_t hop;
int err;
scan = ull_scan_is_disabled_get(0);
if (!scan) {
@ -271,7 +273,12 @@ u8_t ll_create_connection(u16_t scan_interval, u16_t scan_window,
scan->own_addr_type = own_addr_type;
/* wait for stable clocks */
lll_clock_wait();
err = lll_clock_wait();
if (err) {
conn_release(scan);
return BT_HCI_ERR_HW_FAILURE;
}
return ull_scan_enable(scan);
}
@ -699,7 +706,7 @@ static void ticker_op_cb(u32_t status, void *params)
* - It shall have no more than eleven transitions in the least significant 16
* bits.
*/
static void access_addr_get(u8_t access_addr[])
static inline void access_addr_get(u8_t access_addr[])
{
#if defined(CONFIG_BT_CTLR_PHY_CODED)
u8_t transitions_lsb16;
@ -850,3 +857,27 @@ again:
sys_put_le32(aa, access_addr);
}
static inline void conn_release(struct ll_scan_set *scan)
{
struct lll_conn *lll = scan->lll.conn;
struct node_rx_pdu *cc;
struct ll_conn *conn;
memq_link_t *link;
LL_ASSERT(!lll->link_tx_free);
link = memq_deinit(&lll->memq_tx.head, &lll->memq_tx.tail);
LL_ASSERT(link);
lll->link_tx_free = link;
conn = (void *)HDR_LLL2EVT(lll);
cc = (void *)&conn->llcp_terminate.node_rx;
link = cc->hdr.link;
LL_ASSERT(link);
ll_rx_link_release(link);
ll_conn_release(conn);
scan->lll.conn = NULL;
}