Bluetooth: controller: split: Implement Aux Sets
Implement use of configurable Auxiliary advertising sets. Signed-off-by: Vinayak Kariappa Chettimada <vich@nordicsemi.no>
This commit is contained in:
parent
b92abf8e6a
commit
4d79d43db1
16 changed files with 929 additions and 175 deletions
|
@ -455,10 +455,20 @@ config BT_CTLR_ADV_EXT
|
|||
config BT_CTLR_ADV_SET
|
||||
int "LE Advertising Extensions Sets"
|
||||
depends on BT_CTLR_ADV_EXT
|
||||
default 1
|
||||
range 1 64
|
||||
help
|
||||
Maximum supported advertising sets.
|
||||
|
||||
config BT_CTLR_ADV_AUX_SET
|
||||
int "LE Advertising Extensions Auxiliary Sets"
|
||||
depends on BT_CTLR_ADV_EXT
|
||||
range 1 BT_CTLR_ADV_SET if BT_CTLR_ADV_PERIODIC
|
||||
range 0 BT_CTLR_ADV_SET
|
||||
default 1 if BT_CTLR_ADV_PERIODIC
|
||||
default 0
|
||||
help
|
||||
Maximum supported advertising auxiliary channel sets.
|
||||
|
||||
config BT_CTLR_ADV_PERIODIC
|
||||
bool "LE Periodic Advertising"
|
||||
depends on BT_CTLR_ADV_EXT
|
||||
|
@ -470,7 +480,7 @@ config BT_CTLR_ADV_PERIODIC
|
|||
config BT_CTLR_ADV_SYNC_SET
|
||||
int "LE Periodic Advertising Sets"
|
||||
depends on BT_CTLR_ADV_PERIODIC
|
||||
default 1
|
||||
range 1 BT_CTLR_ADV_AUX_SET
|
||||
help
|
||||
Maximum supported periodic advertising sets.
|
||||
|
||||
|
|
|
@ -39,11 +39,11 @@ enum {
|
|||
TICKER_ID_ADV_BASE,
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) || defined(CONFIG_BT_HCI_MESH_EXT)
|
||||
TICKER_ID_ADV_LAST = ((TICKER_ID_ADV_BASE) + (BT_CTLR_ADV_MAX) - 1),
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
#if (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
|
||||
TICKER_ID_ADV_AUX_BASE,
|
||||
TICKER_ID_ADV_AUX_LAST = ((TICKER_ID_ADV_AUX_BASE) +
|
||||
(CONFIG_BT_CTLR_ADV_SET) - 1),
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
(CONFIG_BT_CTLR_ADV_AUX_SET) - 1),
|
||||
#endif /* CONFIG_BT_CTLR_ADV_AUX_SET > 0 */
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
|
||||
#endif /* CONFIG_BT_BROADCASTER */
|
||||
|
||||
|
|
|
@ -779,7 +779,7 @@ uint32_t radio_tmr_start_now(uint8_t trx)
|
|||
now = EVENT_TIMER->CC[1];
|
||||
} while (now > start);
|
||||
|
||||
return start;
|
||||
return start + 1;
|
||||
}
|
||||
|
||||
uint32_t radio_tmr_start_get(void)
|
||||
|
|
|
@ -55,10 +55,6 @@ static void isr_done(void *param);
|
|||
static void isr_abort(void *param);
|
||||
static struct pdu_adv *chan_prepare(struct lll_adv *lll);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
static void aux_ptr_populate(struct pdu_adv *pdu, uint32_t start_us);
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
|
||||
static inline int isr_rx_pdu(struct lll_adv *lll,
|
||||
uint8_t devmatch_ok, uint8_t devmatch_id,
|
||||
uint8_t irkmatch_ok, uint8_t irkmatch_id,
|
||||
|
@ -214,14 +210,6 @@ static int prepare_cb(struct lll_prepare_param *prepare_param)
|
|||
/* capture end of Tx-ed PDU, used to calculate HCTO. */
|
||||
radio_tmr_end_capture();
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
if (pdu->type == PDU_ADV_TYPE_EXT_IND) {
|
||||
aux_ptr_populate(pdu, start_us);
|
||||
}
|
||||
#else /* !CONFIG_BT_CTLR_ADV_EXT */
|
||||
ARG_UNUSED(pdu);
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
|
||||
radio_gpio_pa_setup();
|
||||
radio_gpio_pa_lna_enable(start_us + radio_tx_ready_delay_get(0, 0) -
|
||||
|
@ -488,8 +476,9 @@ static void isr_done(void *param)
|
|||
start_us = radio_tmr_start_now(1);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
if (pdu->type == PDU_ADV_TYPE_EXT_IND) {
|
||||
aux_ptr_populate(pdu, start_us);
|
||||
if (lll->aux) {
|
||||
lll_adv_aux_offset_fill(lll->aux->ticks_offset,
|
||||
start_us + 1, pdu);
|
||||
}
|
||||
#else /* !CONFIG_BT_CTLR_ADV_EXT */
|
||||
ARG_UNUSED(pdu);
|
||||
|
@ -512,7 +501,7 @@ static void isr_done(void *param)
|
|||
|
||||
return;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) && defined(CONFIG_BT_CTLR_ADV_EXT_PBACK)
|
||||
} else {
|
||||
struct pdu_adv_com_ext_adv *p;
|
||||
struct ext_adv_hdr *h;
|
||||
|
@ -525,7 +514,7 @@ static void isr_done(void *param)
|
|||
if ((pdu->type == PDU_ADV_TYPE_EXT_IND) && h->aux_ptr) {
|
||||
radio_filter_disable();
|
||||
|
||||
lll_adv_aux_prepare(lll);
|
||||
lll_adv_aux_pback_prepare(lll);
|
||||
|
||||
return;
|
||||
}
|
||||
|
@ -627,39 +616,6 @@ static struct pdu_adv *chan_prepare(struct lll_adv *lll)
|
|||
return pdu;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
static void aux_ptr_populate(struct pdu_adv *pdu, uint32_t start_us)
|
||||
{
|
||||
struct pdu_adv_com_ext_adv *p;
|
||||
struct ext_adv_aux_ptr *aux;
|
||||
struct ext_adv_hdr *h;
|
||||
uint8_t *ptr;
|
||||
|
||||
p = (void *)&pdu->adv_ext_ind;
|
||||
h = (void *)p->ext_hdr_adi_adv_data;
|
||||
|
||||
if (!h->aux_ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ptr = (uint8_t *)h + sizeof(*h);
|
||||
|
||||
if (h->adv_addr) {
|
||||
ptr += BDADDR_SIZE;
|
||||
}
|
||||
|
||||
if (h->adi) {
|
||||
ptr += sizeof(struct ext_adv_adi);
|
||||
}
|
||||
|
||||
aux = (void *)ptr;
|
||||
aux->offs = (1000 - start_us) / 30;
|
||||
if (aux->offs_units) {
|
||||
aux->offs /= 10;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
|
||||
static inline int isr_rx_pdu(struct lll_adv *lll,
|
||||
uint8_t devmatch_ok, uint8_t devmatch_id,
|
||||
uint8_t irkmatch_ok, uint8_t irkmatch_id,
|
||||
|
|
|
@ -13,6 +13,19 @@ struct lll_adv_pdu {
|
|||
uint8_t pdu[DOUBLE_BUFFER_SIZE][PDU_AC_SIZE_MAX];
|
||||
};
|
||||
|
||||
struct lll_adv_aux {
|
||||
struct lll_hdr hdr;
|
||||
struct lll_adv *adv;
|
||||
|
||||
uint32_t ticks_offset;
|
||||
|
||||
struct lll_adv_pdu data;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
|
||||
int8_t tx_pwr_lvl;
|
||||
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
|
||||
};
|
||||
|
||||
struct lll_adv_sync {
|
||||
struct lll_hdr hdr;
|
||||
struct lll_adv *adv;
|
||||
|
@ -28,7 +41,13 @@ struct lll_adv_sync {
|
|||
uint8_t data_chan_count:6;
|
||||
uint16_t data_chan_id;
|
||||
|
||||
uint32_t ticks_offset;
|
||||
|
||||
struct lll_adv_pdu data;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
|
||||
int8_t tx_pwr_lvl;
|
||||
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
|
||||
};
|
||||
|
||||
struct lll_adv {
|
||||
|
@ -61,7 +80,7 @@ struct lll_adv {
|
|||
struct lll_adv_pdu scan_rsp;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
struct lll_adv_pdu aux_data;
|
||||
struct lll_adv_aux *aux;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
struct lll_adv_sync *sync;
|
||||
|
@ -134,20 +153,21 @@ static inline struct pdu_adv *lll_adv_scan_rsp_peek(struct lll_adv *lll)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
static inline struct pdu_adv *lll_adv_aux_data_alloc(struct lll_adv *lll,
|
||||
static inline struct pdu_adv *lll_adv_aux_data_alloc(struct lll_adv_aux *lll,
|
||||
uint8_t *idx)
|
||||
{
|
||||
return lll_adv_pdu_alloc(&lll->aux_data, idx);
|
||||
return lll_adv_pdu_alloc(&lll->data, idx);
|
||||
}
|
||||
|
||||
static inline void lll_adv_aux_data_enqueue(struct lll_adv *lll, uint8_t idx)
|
||||
static inline void lll_adv_aux_data_enqueue(struct lll_adv_aux *lll,
|
||||
uint8_t idx)
|
||||
{
|
||||
lll_adv_pdu_enqueue(&lll->aux_data, idx);
|
||||
lll_adv_pdu_enqueue(&lll->data, idx);
|
||||
}
|
||||
|
||||
static inline struct pdu_adv *lll_adv_aux_data_peek(struct lll_adv *lll)
|
||||
static inline struct pdu_adv *lll_adv_aux_data_peek(struct lll_adv_aux *lll)
|
||||
{
|
||||
return (void *)lll->aux_data.pdu[lll->aux_data.last];
|
||||
return (void *)lll->data.pdu[lll->data.last];
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
|
|
|
@ -8,9 +8,11 @@
|
|||
|
||||
#include <toolchain.h>
|
||||
#include <zephyr/types.h>
|
||||
#include <sys/byteorder.h>
|
||||
|
||||
#include "hal/ccm.h"
|
||||
#include "hal/radio.h"
|
||||
#include "hal/ticker.h"
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/memq.h"
|
||||
|
@ -18,9 +20,11 @@
|
|||
#include "pdu.h"
|
||||
|
||||
#include "lll.h"
|
||||
#include "lll_vendor.h"
|
||||
#include "lll_clock.h"
|
||||
#include "lll_adv.h"
|
||||
#include "lll_chan.h"
|
||||
#include "lll_adv.h"
|
||||
#include "lll_adv_aux.h"
|
||||
|
||||
#include "lll_internal.h"
|
||||
#include "lll_adv_internal.h"
|
||||
|
@ -31,28 +35,107 @@
|
|||
#include <soc.h>
|
||||
#include "hal/debug.h"
|
||||
|
||||
void lll_adv_aux_prepare(struct lll_adv *lll)
|
||||
static int init_reset(void);
|
||||
static int prepare_cb(struct lll_prepare_param *prepare_param);
|
||||
static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
|
||||
|
||||
int lll_adv_aux_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = init_reset();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int lll_adv_aux_reset(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = init_reset();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void lll_adv_aux_prepare(void *param)
|
||||
{
|
||||
struct lll_prepare_param *p = param;
|
||||
int err;
|
||||
|
||||
err = lll_hfclock_on();
|
||||
LL_ASSERT(!err || err == -EINPROGRESS);
|
||||
|
||||
err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0, p);
|
||||
LL_ASSERT(!err || err == -EINPROGRESS);
|
||||
}
|
||||
|
||||
void lll_adv_aux_offset_fill(uint32_t ticks_offset, uint32_t start_us,
|
||||
struct pdu_adv *pdu)
|
||||
{
|
||||
struct pdu_adv_com_ext_adv *p;
|
||||
struct ext_adv_aux_ptr *aux;
|
||||
struct pdu_adv *pri, *sec;
|
||||
struct ext_adv_hdr *h;
|
||||
uint32_t start_us;
|
||||
uint8_t *ptr;
|
||||
uint8_t upd = 0U;
|
||||
|
||||
/* TODO: if coded we use S8? */
|
||||
radio_phy_set(lll->phy_s, 1);
|
||||
radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (lll->phy_s << 1));
|
||||
p = (void *)&pdu->adv_ext_ind;
|
||||
h = (void *)p->ext_hdr_adi_adv_data;
|
||||
ptr = (uint8_t *)h + sizeof(*h);
|
||||
|
||||
if (h->adv_addr) {
|
||||
ptr += BDADDR_SIZE;
|
||||
}
|
||||
|
||||
if (h->adi) {
|
||||
ptr += sizeof(struct ext_adv_adi);
|
||||
}
|
||||
|
||||
aux = (void *)ptr;
|
||||
aux->offs = (HAL_TICKER_TICKS_TO_US(ticks_offset) - start_us) / 30;
|
||||
if (aux->offs_units) {
|
||||
aux->offs /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
void lll_adv_aux_pback_prepare(void *param)
|
||||
{
|
||||
}
|
||||
|
||||
static int init_reset(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int prepare_cb(struct lll_prepare_param *prepare_param)
|
||||
{
|
||||
struct lll_adv_aux *lll = prepare_param->param;
|
||||
uint32_t aa = sys_cpu_to_le32(PDU_AC_ACCESS_ADDR);
|
||||
uint32_t ticks_at_event, ticks_at_start;
|
||||
struct pdu_adv_com_ext_adv *p;
|
||||
struct ext_adv_aux_ptr *aux;
|
||||
struct pdu_adv *pri, *sec;
|
||||
struct lll_adv *lll_adv;
|
||||
struct ext_adv_hdr *h;
|
||||
struct evt_hdr *evt;
|
||||
uint32_t remainder;
|
||||
uint32_t start_us;
|
||||
uint8_t phy_s;
|
||||
uint8_t *ptr;
|
||||
uint8_t upd;
|
||||
|
||||
DEBUG_RADIO_START_A(1);
|
||||
|
||||
/* AUX_ADV_IND PDU buffer get */
|
||||
/* FIXME: get latest only when primary PDU without Aux PDUs */
|
||||
sec = lll_adv_aux_data_latest_get(lll, &upd);
|
||||
|
||||
radio_pkt_tx_set(sec);
|
||||
|
||||
/* Get reference to primary PDU aux_ptr */
|
||||
pri = lll_adv_data_curr_get(lll);
|
||||
lll_adv = lll->adv;
|
||||
pri = lll_adv_data_curr_get(lll_adv);
|
||||
p = (void *)&pri->adv_ext_ind;
|
||||
h = (void *)p->ext_hdr_adi_adv_data;
|
||||
ptr = (uint8_t *)h + sizeof(*h);
|
||||
|
@ -68,23 +151,109 @@ void lll_adv_aux_prepare(struct lll_adv *lll)
|
|||
}
|
||||
aux = (void *)ptr;
|
||||
|
||||
#if !defined(CONFIG_BT_CTLR_ADV_EXT_PBACK)
|
||||
/* Set up Radio H/W */
|
||||
radio_reset();
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT_PBACK */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
|
||||
radio_tx_power_set(lll->tx_pwr_lvl);
|
||||
#else
|
||||
radio_tx_power_set(RADIO_TXP_DEFAULT);
|
||||
#endif /* CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL */
|
||||
|
||||
phy_s = lll_adv->phy_s;
|
||||
|
||||
/* TODO: if coded we use S8? */
|
||||
radio_phy_set(phy_s, 1);
|
||||
radio_pkt_configure(8, PDU_AC_PAYLOAD_SIZE_MAX, (phy_s << 1));
|
||||
|
||||
#if !defined(CONFIG_BT_CTLR_ADV_EXT_PBACK)
|
||||
/* Access address and CRC */
|
||||
radio_aa_set((uint8_t *)&aa);
|
||||
radio_crc_configure(((0x5bUL) | ((0x06UL) << 8) | ((0x00UL) << 16)),
|
||||
0x555555);
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT_PBACK */
|
||||
|
||||
/* Use channel idx in aux_ptr */
|
||||
lll_chan_set(aux->chan_idx);
|
||||
|
||||
/* Set the Radio Tx Packet */
|
||||
radio_pkt_tx_set(sec);
|
||||
|
||||
/* TODO: Based on adv_mode switch to Rx, if needed */
|
||||
radio_isr_set(lll_isr_done, lll);
|
||||
radio_switch_complete_and_disable();
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT_PBACK)
|
||||
start_us = 1000;
|
||||
radio_tmr_start_us(1, start_us);
|
||||
#else /* !CONFIG_BT_CTLR_ADV_EXT_PBACK */
|
||||
|
||||
ticks_at_event = prepare_param->ticks_at_expire;
|
||||
evt = HDR_LLL2EVT(lll);
|
||||
ticks_at_event += lll_evt_offset_get(evt);
|
||||
|
||||
ticks_at_start = ticks_at_event;
|
||||
ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
|
||||
|
||||
remainder = prepare_param->remainder;
|
||||
start_us = radio_tmr_start(1, ticks_at_start, remainder);
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_EXT_PBACK */
|
||||
|
||||
/* capture end of Tx-ed PDU, used to calculate HCTO. */
|
||||
radio_tmr_end_capture();
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
|
||||
radio_gpio_pa_setup();
|
||||
radio_gpio_pa_lna_enable(start_us +
|
||||
radio_tx_ready_delay_get(0, 0) -
|
||||
radio_gpio_pa_lna_enable(start_us + radio_tx_ready_delay_get(phy_s, 1) -
|
||||
CONFIG_BT_CTLR_GPIO_PA_OFFSET);
|
||||
#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
|
||||
ARG_UNUSED(start_us);
|
||||
#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
|
||||
(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
|
||||
/* check if preempt to start has changed */
|
||||
if (lll_preempt_calc(evt, (TICKER_ID_ADV_AUX_BASE +
|
||||
ull_adv_aux_lll_handle_get(lll)),
|
||||
ticks_at_event)) {
|
||||
radio_isr_set(lll_isr_abort, lll);
|
||||
radio_disable();
|
||||
} else
|
||||
#endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
ret = lll_prepare_done(lll);
|
||||
LL_ASSERT(!ret);
|
||||
}
|
||||
|
||||
DEBUG_RADIO_START_A(1);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
|
||||
{
|
||||
int err;
|
||||
|
||||
/* NOTE: This is not a prepare being cancelled */
|
||||
if (!prepare_param) {
|
||||
/* Perform event abort here.
|
||||
* After event has been cleanly aborted, clean up resources
|
||||
* and dispatch event done.
|
||||
*/
|
||||
radio_isr_set(lll_isr_done, param);
|
||||
radio_disable();
|
||||
return;
|
||||
}
|
||||
|
||||
/* NOTE: Else clean the top half preparations of the aborted event
|
||||
* currently in preparation pipeline.
|
||||
*/
|
||||
err = lll_hfclock_off();
|
||||
LL_ASSERT(!err || err == -EBUSY);
|
||||
|
||||
lll_done(param);
|
||||
}
|
||||
|
|
|
@ -4,4 +4,11 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
void lll_adv_aux_prepare(struct lll_adv *lll);
|
||||
int lll_adv_aux_init(void);
|
||||
int lll_adv_aux_reset(void);
|
||||
void lll_adv_aux_prepare(void *param);
|
||||
void lll_adv_aux_offset_fill(uint32_t ticks_offset, uint32_t start_us,
|
||||
struct pdu_adv *pdu);
|
||||
|
||||
|
||||
extern uint16_t ull_adv_aux_lll_handle_get(struct lll_adv_aux *lll);
|
||||
|
|
|
@ -45,15 +45,15 @@ static inline struct pdu_adv *lll_adv_scan_rsp_curr_get(struct lll_adv *lll)
|
|||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
static inline struct pdu_adv *lll_adv_aux_data_latest_get(struct lll_adv *lll,
|
||||
uint8_t *is_modified)
|
||||
static inline struct pdu_adv *
|
||||
lll_adv_aux_data_latest_get(struct lll_adv_aux *lll, uint8_t *is_modified)
|
||||
{
|
||||
return lll_adv_pdu_latest_get(&lll->aux_data, is_modified);
|
||||
return lll_adv_pdu_latest_get(&lll->data, is_modified);
|
||||
}
|
||||
|
||||
static inline struct pdu_adv *lll_adv_aux_data_curr_get(struct lll_adv *lll)
|
||||
static inline struct pdu_adv *lll_adv_aux_data_curr_get(struct lll_adv_aux *lll)
|
||||
{
|
||||
return (void *)lll->aux_data.pdu[lll->aux_data.first];
|
||||
return (void *)lll->data.pdu[lll->data.first];
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
|
|
|
@ -76,6 +76,37 @@ void lll_adv_sync_prepare(void *param)
|
|||
LL_ASSERT(!err || err == -EINPROGRESS);
|
||||
}
|
||||
|
||||
void lll_adv_sync_offset_fill(uint32_t ticks_offset, uint32_t start_us,
|
||||
struct pdu_adv *pdu)
|
||||
{
|
||||
struct pdu_adv_com_ext_adv *p;
|
||||
struct ext_adv_sync_info *si;
|
||||
struct ext_adv_hdr *h;
|
||||
uint8_t *ptr;
|
||||
|
||||
p = (void *)&pdu->adv_ext_ind;
|
||||
h = (void *)p->ext_hdr_adi_adv_data;
|
||||
ptr = (uint8_t *)h + sizeof(*h);
|
||||
|
||||
if (h->adv_addr) {
|
||||
ptr += BDADDR_SIZE;
|
||||
}
|
||||
|
||||
if (h->adi) {
|
||||
ptr += sizeof(struct ext_adv_adi);
|
||||
}
|
||||
|
||||
if (h->aux_ptr) {
|
||||
ptr += sizeof(struct ext_adv_aux_ptr);
|
||||
}
|
||||
|
||||
si = (void *)ptr;
|
||||
si->offs = (HAL_TICKER_TICKS_TO_US(ticks_offset) - start_us) / 30;
|
||||
if (si->offs_units) {
|
||||
si->offs /= 10;
|
||||
}
|
||||
}
|
||||
|
||||
static int init_reset(void)
|
||||
{
|
||||
return 0;
|
||||
|
@ -88,9 +119,9 @@ static int prepare_cb(struct lll_prepare_param *prepare_param)
|
|||
struct pdu_adv *pdu;
|
||||
struct evt_hdr *evt;
|
||||
uint16_t event_counter;
|
||||
uint32_t remainder_us;
|
||||
uint8_t data_chan_use;
|
||||
uint32_t remainder;
|
||||
uint32_t start_us;
|
||||
uint16_t lazy;
|
||||
uint8_t phy_s;
|
||||
uint8_t upd;
|
||||
|
@ -154,23 +185,15 @@ static int prepare_cb(struct lll_prepare_param *prepare_param)
|
|||
ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
|
||||
|
||||
remainder = prepare_param->remainder;
|
||||
remainder_us = radio_tmr_start(1, ticks_at_start, remainder);
|
||||
start_us = radio_tmr_start(1, ticks_at_start, remainder);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_GPIO_PA_PIN)
|
||||
radio_gpio_pa_setup();
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_PHY)
|
||||
radio_gpio_pa_lna_enable(remainder_us +
|
||||
radio_tx_ready_delay_get(lll->phy_tx,
|
||||
lll->phy_flags) -
|
||||
radio_gpio_pa_lna_enable(start_us + radio_tx_ready_delay_get(phy_s, 1) -
|
||||
CONFIG_BT_CTLR_GPIO_PA_OFFSET);
|
||||
#else /* !CONFIG_BT_CTLR_PHY */
|
||||
radio_gpio_pa_lna_enable(remainder_us +
|
||||
radio_tx_ready_delay_get(0, 0) -
|
||||
CONFIG_BT_CTLR_GPIO_PA_OFFSET);
|
||||
#endif /* !CONFIG_BT_CTLR_PHY */
|
||||
#else /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
|
||||
ARG_UNUSED(remainder_us);
|
||||
ARG_UNUSED(start_us);
|
||||
#endif /* !CONFIG_BT_CTLR_GPIO_PA_PIN */
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
|
||||
|
|
|
@ -7,5 +7,7 @@
|
|||
int lll_adv_sync_init(void);
|
||||
int lll_adv_sync_reset(void);
|
||||
void lll_adv_sync_prepare(void *param);
|
||||
void lll_adv_sync_offset_fill(uint32_t ticks_offset, uint32_t start_us,
|
||||
struct pdu_adv *pdu);
|
||||
|
||||
extern uint16_t ull_adv_sync_lll_handle_get(struct lll_adv_sync *lll);
|
||||
|
|
|
@ -74,9 +74,24 @@
|
|||
|
||||
#if defined(CONFIG_BT_BROADCASTER)
|
||||
#define BT_ADV_TICKER_NODES ((TICKER_ID_ADV_LAST) - (TICKER_ID_ADV_STOP) + 1)
|
||||
#else
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
|
||||
#define BT_ADV_AUX_TICKER_NODES ((TICKER_ID_ADV_AUX_LAST) - \
|
||||
(TICKER_ID_ADV_AUX_BASE) + 1)
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
#define BT_ADV_SYNC_TICKER_NODES ((TICKER_ID_ADV_SYNC_LAST) - \
|
||||
(TICKER_ID_ADV_SYNC_BASE) + 1)
|
||||
#else /* !CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
#define BT_ADV_SYNC_TICKER_NODES 0
|
||||
#endif /* !CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
#else /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
|
||||
#define BT_ADV_AUX_TICKER_NODES 0
|
||||
#define BT_ADV_SYNC_TICKER_NODES 0
|
||||
#endif /* (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
|
||||
#else /* !CONFIG_BT_BROADCASTER */
|
||||
#define BT_ADV_TICKER_NODES 0
|
||||
#endif
|
||||
#define BT_ADV_AUX_TICKER_NODES 0
|
||||
#define BT_ADV_SYNC_TICKER_NODES 0
|
||||
#endif /* !CONFIG_BT_BROADCASTER */
|
||||
|
||||
#if defined(CONFIG_BT_OBSERVER)
|
||||
#define BT_SCAN_TICKER_NODES ((TICKER_ID_SCAN_LAST) - (TICKER_ID_SCAN_STOP) + 1)
|
||||
|
@ -106,6 +121,8 @@
|
|||
|
||||
#define TICKER_NODES (TICKER_ID_ULL_BASE + \
|
||||
BT_ADV_TICKER_NODES + \
|
||||
BT_ADV_AUX_TICKER_NODES + \
|
||||
BT_ADV_SYNC_TICKER_NODES + \
|
||||
BT_SCAN_TICKER_NODES + \
|
||||
BT_CONN_TICKER_NODES + \
|
||||
FLASH_TICKER_NODES + \
|
||||
|
|
|
@ -50,8 +50,6 @@
|
|||
#include <soc.h>
|
||||
#include "hal/debug.h"
|
||||
|
||||
#define ULL_ADV_RANDOM_DELAY HAL_TICKER_US_TO_TICKS(10000)
|
||||
|
||||
inline struct ll_adv_set *ull_adv_set_get(uint8_t handle);
|
||||
inline uint16_t ull_adv_handle_get(struct ll_adv_set *adv);
|
||||
|
||||
|
@ -469,6 +467,8 @@ uint8_t ll_adv_enable(uint8_t handle, uint8_t enable)
|
|||
struct ll_adv_sync_set *sync;
|
||||
uint8_t sync_is_started = 0U;
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
struct ll_adv_aux_set *aux;
|
||||
uint8_t aux_is_started = 0U;
|
||||
uint32_t ticks_anchor;
|
||||
#endif /* !CONFIG_BT_HCI_MESH_EXT */
|
||||
#else /* !CONFIG_BT_CTLR_ADV_EXT || !CONFIG_BT_HCI_MESH_EXT */
|
||||
|
@ -531,7 +531,7 @@ uint8_t ll_adv_enable(uint8_t enable)
|
|||
struct ext_adv_hdr *hs;
|
||||
uint8_t *ps;
|
||||
|
||||
pdu_aux = lll_adv_aux_data_peek(lll);
|
||||
pdu_aux = lll_adv_aux_data_peek(lll->aux);
|
||||
|
||||
s = (void *)&pdu_aux->adv_ext_ind;
|
||||
hs = (void *)s->ext_hdr_adi_adv_data;
|
||||
|
@ -986,24 +986,48 @@ uint8_t ll_adv_enable(uint8_t enable)
|
|||
#endif /* CONFIG_BT_TICKER_EXT */
|
||||
);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
if (lll->sync) {
|
||||
struct lll_adv_sync *lll_sync = lll->sync;
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
if (lll->aux) {
|
||||
struct lll_adv_aux *lll_aux = lll->aux;
|
||||
|
||||
sync = (void *)HDR_LLL2EVT(lll_sync);
|
||||
if (sync->is_enabled && !sync->is_started) {
|
||||
ret = ull_ticker_status_take(ret, &ret_cb);
|
||||
if (ret != TICKER_STATUS_SUCCESS) {
|
||||
goto failure_cleanup;
|
||||
}
|
||||
|
||||
ret = ull_adv_sync_start(sync, ticks_anchor,
|
||||
&ret_cb);
|
||||
|
||||
sync_is_started = 1U;
|
||||
ret = ull_ticker_status_take(ret, &ret_cb);
|
||||
if (ret != TICKER_STATUS_SUCCESS) {
|
||||
goto failure_cleanup;
|
||||
}
|
||||
|
||||
aux = (void *)HDR_LLL2EVT(lll_aux);
|
||||
ull_hdr_init(&aux->ull);
|
||||
aux->interval =
|
||||
adv->interval +
|
||||
(HAL_TICKER_TICKS_TO_US(ULL_ADV_RANDOM_DELAY) /
|
||||
625U);
|
||||
|
||||
ret = ull_adv_aux_start(aux, ticks_anchor, &ret_cb);
|
||||
|
||||
aux_is_started = 1U;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
if (lll->sync) {
|
||||
struct lll_adv_sync *lll_sync = lll->sync;
|
||||
|
||||
sync = (void *)HDR_LLL2EVT(lll_sync);
|
||||
if (sync->is_enabled && !sync->is_started) {
|
||||
ret = ull_ticker_status_take(ret,
|
||||
&ret_cb);
|
||||
if (ret != TICKER_STATUS_SUCCESS) {
|
||||
goto failure_cleanup;
|
||||
}
|
||||
|
||||
ret = ull_adv_sync_start(sync,
|
||||
ticks_anchor,
|
||||
&ret_cb);
|
||||
|
||||
sync_is_started = 1U;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
}
|
||||
|
||||
ret = ull_ticker_status_take(ret, &ret_cb);
|
||||
|
@ -1011,11 +1035,17 @@ uint8_t ll_adv_enable(uint8_t enable)
|
|||
goto failure_cleanup;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT)
|
||||
if (aux_is_started) {
|
||||
aux->is_started = aux_is_started;
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
if (sync_is_started) {
|
||||
sync->is_started = sync_is_started;
|
||||
}
|
||||
if (sync_is_started) {
|
||||
sync->is_started = sync_is_started;
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT */
|
||||
|
||||
adv->is_enabled = 1;
|
||||
|
||||
|
@ -1050,10 +1080,21 @@ int ull_adv_init(void)
|
|||
{
|
||||
int err;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC)) {
|
||||
err = ull_adv_sync_init();
|
||||
if (err) {
|
||||
return err;
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT)) {
|
||||
#if defined(CONFIG_BT_CTLR_ADV_AUX_SET)
|
||||
if (CONFIG_BT_CTLR_ADV_AUX_SET > 0) {
|
||||
err = ull_adv_aux_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC)) {
|
||||
err = ull_adv_sync_init();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1070,10 +1111,21 @@ int ull_adv_reset(void)
|
|||
uint8_t handle;
|
||||
int err;
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC)) {
|
||||
err = ull_adv_sync_reset();
|
||||
if (err) {
|
||||
return err;
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_EXT)) {
|
||||
#if defined(CONFIG_BT_CTLR_ADV_AUX_SET)
|
||||
if (CONFIG_BT_CTLR_ADV_AUX_SET > 0) {
|
||||
err = ull_adv_aux_reset();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_ADV_PERIODIC)) {
|
||||
err = ull_adv_sync_reset();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1232,6 +1284,12 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder, uint16_t laz
|
|||
(ret == TICKER_STATUS_BUSY));
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
|
||||
if (adv->lll.aux) {
|
||||
ull_adv_aux_offset_get(adv);
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
|
||||
|
||||
DEBUG_RADIO_PREPARE_A(1);
|
||||
}
|
||||
|
||||
|
@ -1380,6 +1438,22 @@ static inline uint8_t disable(uint8_t handle)
|
|||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_EXT) && (CONFIG_BT_CTLR_ADV_AUX_SET > 0)
|
||||
struct lll_adv_aux *lll_aux = adv->lll.aux;
|
||||
|
||||
if (lll_aux) {
|
||||
struct ll_adv_aux_set *aux;
|
||||
uint8_t err;
|
||||
|
||||
aux = (void *)HDR_LLL2EVT(lll_aux);
|
||||
|
||||
err = ull_adv_aux_stop(aux);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_EXT && (CONFIG_BT_CTLR_ADV_AUX_SET > 0) */
|
||||
|
||||
mark = ull_disable_mark(adv);
|
||||
LL_ASSERT(mark == adv);
|
||||
|
||||
|
|
|
@ -4,24 +4,50 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr/types.h>
|
||||
#include <sys/byteorder.h>
|
||||
#include <bluetooth/hci.h>
|
||||
|
||||
#include "hal/ccm.h"
|
||||
#include "hal/ticker.h"
|
||||
|
||||
#include "util/util.h"
|
||||
#include "util/mem.h"
|
||||
#include "util/memq.h"
|
||||
#include "util/mayfly.h"
|
||||
|
||||
#include "ticker/ticker.h"
|
||||
|
||||
#include "pdu.h"
|
||||
#include "ll.h"
|
||||
#include "lll.h"
|
||||
#include "lll_vendor.h"
|
||||
#include "lll_adv.h"
|
||||
#include "lll_conn.h"
|
||||
#include "ull_internal.h"
|
||||
#include "lll_adv_aux.h"
|
||||
#include "lll_adv_internal.h"
|
||||
|
||||
#include "ull_adv_types.h"
|
||||
|
||||
#include "ull_internal.h"
|
||||
#include "ull_adv_internal.h"
|
||||
|
||||
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
|
||||
#define LOG_MODULE_NAME bt_ctlr_ull_adv_aux
|
||||
#include "common/log.h"
|
||||
#include <soc.h>
|
||||
#include "hal/debug.h"
|
||||
|
||||
static int init_reset(void);
|
||||
static inline struct ll_adv_aux_set *aux_acquire(void);
|
||||
static inline void aux_release(struct ll_adv_aux_set *aux);
|
||||
static inline uint16_t aux_handle_get(struct ll_adv_aux_set *aux);
|
||||
static void mfy_aux_offset_get(void *param);
|
||||
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *param);
|
||||
static void ticker_op_cb(uint32_t status, void *param);
|
||||
|
||||
static struct ll_adv_aux_set ll_adv_aux_pool[CONFIG_BT_CTLR_ADV_AUX_SET];
|
||||
static void *adv_aux_free;
|
||||
|
||||
uint8_t ll_adv_aux_random_addr_set(uint8_t handle, uint8_t *addr)
|
||||
{
|
||||
/* TODO: store in adv set instance */
|
||||
|
@ -41,8 +67,11 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui
|
|||
uint8_t pri_len, _pri_len, sec_len, _sec_len;
|
||||
struct pdu_adv *_pri, *pri, *_sec, *sec;
|
||||
struct ext_adv_hdr *hp, _hp, *hs, _hs;
|
||||
struct lll_adv_aux *lll_aux;
|
||||
struct ll_adv_aux_set *aux;
|
||||
uint8_t *_pp, *pp, *ps, *_ps;
|
||||
struct ll_adv_set *adv;
|
||||
struct lll_adv *lll;
|
||||
uint8_t ip, is;
|
||||
|
||||
/* op param definitions:
|
||||
|
@ -66,8 +95,29 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui
|
|||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
lll = &adv->lll;
|
||||
|
||||
lll_aux = lll->aux;
|
||||
if (!lll_aux) {
|
||||
aux = aux_acquire();
|
||||
if (!aux) {
|
||||
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
|
||||
}
|
||||
|
||||
lll_aux = &aux->lll;
|
||||
lll->aux = lll_aux;
|
||||
lll_aux->adv = lll;
|
||||
|
||||
/* NOTE: ull_hdr_init(&aux->ull); is done on start */
|
||||
lll_hdr_init(lll_aux, aux);
|
||||
|
||||
aux->is_started = 0;
|
||||
} else {
|
||||
aux = (void *)HDR_LLL2EVT(lll_aux);
|
||||
}
|
||||
|
||||
/* Do not update data if not extended advertising. */
|
||||
_pri = lll_adv_data_peek(&adv->lll);
|
||||
_pri = lll_adv_data_peek(lll);
|
||||
if (_pri->type != PDU_ADV_TYPE_EXT_IND) {
|
||||
/* Advertising Handle has not been created using
|
||||
* Set Extended Advertising Parameter command
|
||||
|
@ -82,7 +132,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui
|
|||
_pp = (uint8_t *)hp + sizeof(*hp);
|
||||
|
||||
/* Get reference to new primary PDU data buffer */
|
||||
pri = lll_adv_data_alloc(&adv->lll, &ip);
|
||||
pri = lll_adv_data_alloc(lll, &ip);
|
||||
pri->type = _pri->type;
|
||||
pri->rfu = 0U;
|
||||
pri->chan_sel = 0U;
|
||||
|
@ -93,14 +143,14 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui
|
|||
*(uint8_t *)hp = 0U;
|
||||
|
||||
/* Get reference to previous secondary PDU data */
|
||||
_sec = lll_adv_aux_data_peek(&adv->lll);
|
||||
_sec = lll_adv_aux_data_peek(lll_aux);
|
||||
_s = (void *)&_sec->adv_ext_ind;
|
||||
hs = (void *)_s->ext_hdr_adi_adv_data;
|
||||
*(uint8_t *)&_hs = *(uint8_t *)hs;
|
||||
_ps = (uint8_t *)hs + sizeof(*hs);
|
||||
|
||||
/* Get reference to new secondary PDU data buffer */
|
||||
sec = lll_adv_aux_data_alloc(&adv->lll, &is);
|
||||
sec = lll_adv_aux_data_alloc(lll_aux, &is);
|
||||
sec->type = pri->type;
|
||||
sec->rfu = 0U;
|
||||
|
||||
|
@ -187,7 +237,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui
|
|||
/* C1, Tx Power is optional on the LE 1M PHY, and reserved for
|
||||
* for future use on the LE Coded PHY.
|
||||
*/
|
||||
if (adv->lll.phy_p != BIT(2)) {
|
||||
if (lll->phy_p != BIT(2)) {
|
||||
hp->tx_pwr = 1;
|
||||
pp++;
|
||||
} else {
|
||||
|
@ -265,7 +315,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui
|
|||
aux->chan_idx = 0; /* FIXME: implementation defined */
|
||||
aux->ca = 0; /* FIXME: implementation defined */
|
||||
aux->offs_units = 0; /* FIXME: implementation defined */
|
||||
aux->phy = find_lsb_set(adv->lll.phy_s) - 1;
|
||||
aux->phy = find_lsb_set(lll->phy_s) - 1;
|
||||
}
|
||||
if (_hs.aux_ptr) {
|
||||
struct ext_adv_aux_ptr *aux;
|
||||
|
@ -278,7 +328,7 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui
|
|||
aux->chan_idx = 0; /* FIXME: implementation defined */
|
||||
aux->ca = 0; /* FIXME: implementation defined */
|
||||
aux->offs_units = 0; /* FIXME: implementation defined */
|
||||
aux->phy = find_lsb_set(adv->lll.phy_s) - 1;
|
||||
aux->phy = find_lsb_set(lll->phy_s) - 1;
|
||||
}
|
||||
|
||||
/* ADI */
|
||||
|
@ -340,8 +390,31 @@ uint8_t ll_adv_aux_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref, ui
|
|||
memcpy(ps, bdaddr, BDADDR_SIZE);
|
||||
}
|
||||
|
||||
lll_adv_aux_data_enqueue(&adv->lll, is);
|
||||
lll_adv_data_enqueue(&adv->lll, ip);
|
||||
lll_adv_aux_data_enqueue(lll_aux, is);
|
||||
lll_adv_data_enqueue(lll, ip);
|
||||
|
||||
if (adv->is_enabled && !aux->is_started) {
|
||||
volatile uint32_t ret_cb;
|
||||
uint32_t ticks_anchor;
|
||||
uint32_t ret;
|
||||
|
||||
ull_hdr_init(&aux->ull);
|
||||
aux->interval = adv->interval +
|
||||
(HAL_TICKER_TICKS_TO_US(ULL_ADV_RANDOM_DELAY) /
|
||||
625U);
|
||||
|
||||
ticks_anchor = ticker_ticks_now_get();
|
||||
|
||||
ret = ull_adv_aux_start(aux, ticks_anchor, &ret_cb);
|
||||
|
||||
ret = ull_ticker_status_take(ret, &ret_cb);
|
||||
if (ret != TICKER_STATUS_SUCCESS) {
|
||||
/* FIXME: Use a better error code */
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
aux->is_started = 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -378,3 +451,252 @@ uint8_t ll_adv_aux_set_clear(void)
|
|||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ull_adv_aux_init(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = init_reset();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ull_adv_aux_reset(void)
|
||||
{
|
||||
int err;
|
||||
|
||||
err = init_reset();
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t ull_adv_aux_lll_handle_get(struct lll_adv_aux *lll)
|
||||
{
|
||||
return aux_handle_get((void *)lll->hdr.parent);
|
||||
}
|
||||
|
||||
uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
|
||||
uint32_t volatile *ret_cb)
|
||||
{
|
||||
uint32_t slot_us = EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
|
||||
uint32_t ticks_slot_overhead;
|
||||
uint8_t aux_handle;
|
||||
uint32_t ret;
|
||||
|
||||
/* TODO: Calc AUX_ADV_IND slot_us */
|
||||
slot_us += 1000;
|
||||
|
||||
/* TODO: active_to_start feature port */
|
||||
aux->evt.ticks_active_to_start = 0;
|
||||
aux->evt.ticks_xtal_to_start =
|
||||
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_XTAL_US);
|
||||
aux->evt.ticks_preempt_to_start =
|
||||
HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_PREEMPT_MIN_US);
|
||||
aux->evt.ticks_slot = HAL_TICKER_US_TO_TICKS(slot_us);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_CTLR_LOW_LAT)) {
|
||||
ticks_slot_overhead = MAX(aux->evt.ticks_active_to_start,
|
||||
aux->evt.ticks_xtal_to_start);
|
||||
} else {
|
||||
ticks_slot_overhead = 0;
|
||||
}
|
||||
|
||||
aux_handle = aux_handle_get(aux);
|
||||
|
||||
*ret_cb = TICKER_STATUS_BUSY;
|
||||
ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
|
||||
(TICKER_ID_ADV_AUX_BASE + aux_handle),
|
||||
ticks_anchor, 0,
|
||||
HAL_TICKER_US_TO_TICKS((uint64_t)aux->interval *
|
||||
625),
|
||||
TICKER_NULL_REMAINDER, TICKER_NULL_LAZY,
|
||||
(aux->evt.ticks_slot + ticks_slot_overhead),
|
||||
ticker_cb, aux,
|
||||
ull_ticker_status_give, (void *)ret_cb);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint8_t ull_adv_aux_stop(struct ll_adv_aux_set *aux)
|
||||
{
|
||||
volatile uint32_t ret_cb = TICKER_STATUS_BUSY;
|
||||
uint8_t aux_handle;
|
||||
void *mark;
|
||||
uint32_t ret;
|
||||
|
||||
mark = ull_disable_mark(aux);
|
||||
LL_ASSERT(mark == aux);
|
||||
|
||||
aux_handle = aux_handle_get(aux);
|
||||
|
||||
ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
|
||||
TICKER_ID_ADV_AUX_BASE + aux_handle,
|
||||
ull_ticker_status_give, (void *)&ret_cb);
|
||||
|
||||
ret = ull_ticker_status_take(ret, &ret_cb);
|
||||
if (ret) {
|
||||
mark = ull_disable_mark(aux);
|
||||
LL_ASSERT(mark == aux);
|
||||
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
ret = ull_disable(&aux->lll);
|
||||
LL_ASSERT(!ret);
|
||||
|
||||
mark = ull_disable_unmark(aux);
|
||||
LL_ASSERT(mark == aux);
|
||||
|
||||
aux->is_started = 0U;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ull_adv_aux_offset_get(struct ll_adv_set *adv)
|
||||
{
|
||||
static memq_link_t link;
|
||||
static struct mayfly mfy = {0, 0, &link, NULL, mfy_aux_offset_get};
|
||||
uint32_t ret;
|
||||
|
||||
mfy.param = adv;
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
|
||||
&mfy);
|
||||
LL_ASSERT(!ret);
|
||||
}
|
||||
|
||||
static int init_reset(void)
|
||||
{
|
||||
/* Initialize adv aux pool. */
|
||||
mem_init(ll_adv_aux_pool, sizeof(struct ll_adv_aux_set),
|
||||
sizeof(ll_adv_aux_pool) / sizeof(struct ll_adv_aux_set),
|
||||
&adv_aux_free);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct ll_adv_aux_set *aux_acquire(void)
|
||||
{
|
||||
return mem_acquire(&adv_aux_free);
|
||||
}
|
||||
|
||||
static inline void aux_release(struct ll_adv_aux_set *aux)
|
||||
{
|
||||
mem_release(aux, &adv_aux_free);
|
||||
}
|
||||
|
||||
static inline uint16_t aux_handle_get(struct ll_adv_aux_set *aux)
|
||||
{
|
||||
return mem_index_get(aux, ll_adv_aux_pool,
|
||||
sizeof(struct ll_adv_aux_set));
|
||||
}
|
||||
|
||||
static void mfy_aux_offset_get(void *param)
|
||||
{
|
||||
struct ll_adv_set *adv = param;
|
||||
struct ll_adv_aux_set *aux;
|
||||
uint32_t ticks_to_expire;
|
||||
uint32_t ticks_current;
|
||||
struct pdu_adv *pdu;
|
||||
uint8_t ticker_id;
|
||||
uint8_t retry;
|
||||
uint8_t id;
|
||||
|
||||
aux = (void *)HDR_LLL2EVT(adv->lll.aux);
|
||||
ticker_id = TICKER_ID_ADV_AUX_BASE + aux_handle_get(aux);
|
||||
|
||||
id = TICKER_NULL;
|
||||
ticks_to_expire = 0U;
|
||||
ticks_current = 0U;
|
||||
retry = 4U;
|
||||
do {
|
||||
uint32_t volatile ret_cb = TICKER_STATUS_BUSY;
|
||||
uint32_t ticks_previous;
|
||||
uint32_t ret;
|
||||
|
||||
ticks_previous = ticks_current;
|
||||
|
||||
ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR,
|
||||
TICKER_USER_ID_ULL_LOW,
|
||||
&id,
|
||||
&ticks_current, &ticks_to_expire,
|
||||
ticker_op_cb, (void *)&ret_cb);
|
||||
if (ret == TICKER_STATUS_BUSY) {
|
||||
while (ret_cb == TICKER_STATUS_BUSY) {
|
||||
ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
|
||||
TICKER_USER_ID_ULL_LOW);
|
||||
}
|
||||
}
|
||||
|
||||
LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS);
|
||||
|
||||
LL_ASSERT((ticks_current == ticks_previous) || retry--);
|
||||
|
||||
LL_ASSERT(id != TICKER_NULL);
|
||||
} while (id != ticker_id);
|
||||
|
||||
/* NOTE: as remainder not used in scheduling primary PDU
|
||||
* packet timer starts transmission after 1 tick hence the +1.
|
||||
*/
|
||||
aux->lll.ticks_offset = ticks_to_expire + 1;
|
||||
|
||||
pdu = lll_adv_data_curr_get(&adv->lll);
|
||||
lll_adv_aux_offset_fill(ticks_to_expire, 0, pdu);
|
||||
}
|
||||
|
||||
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *param)
|
||||
{
|
||||
static memq_link_t link;
|
||||
static struct mayfly mfy = {0, 0, &link, NULL, lll_adv_aux_prepare};
|
||||
static struct lll_prepare_param p;
|
||||
struct ll_adv_aux_set *aux = param;
|
||||
struct lll_adv_aux *lll;
|
||||
uint32_t ret;
|
||||
uint8_t ref;
|
||||
|
||||
DEBUG_RADIO_PREPARE_A(1);
|
||||
|
||||
lll = &aux->lll;
|
||||
|
||||
/* Increment prepare reference count */
|
||||
ref = ull_ref_inc(&aux->ull);
|
||||
LL_ASSERT(ref);
|
||||
|
||||
/* Append timing parameters */
|
||||
p.ticks_at_expire = ticks_at_expire;
|
||||
p.remainder = remainder;
|
||||
p.lazy = lazy;
|
||||
p.param = lll;
|
||||
mfy.param = &p;
|
||||
|
||||
/* Kick LLL prepare */
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH,
|
||||
TICKER_USER_ID_LLL, 0, &mfy);
|
||||
LL_ASSERT(!ret);
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ADV_PERIODIC)
|
||||
struct ll_adv_set *adv;
|
||||
|
||||
adv = (void *)HDR_LLL2EVT(lll->adv);
|
||||
if (adv->lll.sync) {
|
||||
struct ll_adv_sync_set *sync;
|
||||
|
||||
sync = (void *)HDR_LLL2EVT(adv->lll.sync);
|
||||
if (sync->is_started) {
|
||||
ull_adv_sync_offset_get(adv);
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ADV_PERIODIC */
|
||||
DEBUG_RADIO_PREPARE_A(1);
|
||||
}
|
||||
|
||||
static void ticker_op_cb(uint32_t status, void *param)
|
||||
{
|
||||
*((uint32_t volatile *)param) = status;
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#define ULL_ADV_RANDOM_DELAY HAL_TICKER_US_TO_TICKS(10000)
|
||||
|
||||
int ull_adv_init(void);
|
||||
int ull_adv_reset(void);
|
||||
|
||||
|
@ -25,9 +27,25 @@ uint32_t ull_adv_filter_pol_get(uint8_t handle);
|
|||
/* Return ll_adv_set context if created */
|
||||
struct ll_adv_set *ull_adv_is_created_get(uint8_t handle);
|
||||
|
||||
int ull_adv_aux_init(void);
|
||||
int ull_adv_aux_reset(void);
|
||||
|
||||
/* helper function to start auxiliary advertising */
|
||||
uint32_t ull_adv_aux_start(struct ll_adv_aux_set *aux, uint32_t ticks_anchor,
|
||||
uint32_t volatile *ret_cb);
|
||||
|
||||
/* helper function to stop auxiliary advertising */
|
||||
uint8_t ull_adv_aux_stop(struct ll_adv_aux_set *aux);
|
||||
|
||||
/* helper function to schedule a mayfly to get aux offset */
|
||||
void ull_adv_aux_offset_get(struct ll_adv_set *adv);
|
||||
|
||||
int ull_adv_sync_init(void);
|
||||
int ull_adv_sync_reset(void);
|
||||
|
||||
/* helper function to start periodic advertising */
|
||||
uint32_t ull_adv_sync_start(struct ll_adv_sync_set *sync, uint32_t ticks_anchor,
|
||||
uint32_t volatile *ret_cb);
|
||||
|
||||
/* helper function to schedule a mayfly to get sync offset */
|
||||
void ull_adv_sync_offset_get(struct ll_adv_set *adv);
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "lll_vendor.h"
|
||||
#include "lll_adv.h"
|
||||
#include "lll_adv_sync.h"
|
||||
#include "lll_adv_internal.h"
|
||||
|
||||
#include "ull_adv_types.h"
|
||||
|
||||
|
@ -39,18 +40,21 @@ static int init_reset(void);
|
|||
static inline struct ll_adv_sync_set *sync_acquire(void);
|
||||
static inline void sync_release(struct ll_adv_sync_set *sync);
|
||||
static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync);
|
||||
static inline uint8_t sync_stop(struct ll_adv_sync_set *sync);
|
||||
static void mfy_sync_offset_get(void *param);
|
||||
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *param);
|
||||
static void ticker_op_cb(uint32_t status, void *param);
|
||||
|
||||
static struct ll_adv_sync_set ll_adv_sync_pool[CONFIG_BT_CTLR_ADV_SYNC_SET];
|
||||
static void *adv_sync_free;
|
||||
|
||||
uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
|
||||
{
|
||||
struct lll_adv_sync *lll_sync;
|
||||
struct pdu_adv_com_ext_adv *t;
|
||||
struct ll_adv_sync_set *sync;
|
||||
struct ext_adv_hdr *ht, _ht;
|
||||
struct lll_adv_sync *lll;
|
||||
struct ll_adv_set *adv;
|
||||
struct pdu_adv *pdu;
|
||||
uint8_t *_pt, *pt;
|
||||
|
@ -61,48 +65,55 @@ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
|
|||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
lll = adv->lll.sync;
|
||||
if (!lll) {
|
||||
lll_sync = adv->lll.sync;
|
||||
if (!lll_sync) {
|
||||
struct pdu_adv_com_ext_adv *p, *_p, *s, *_s;
|
||||
uint8_t pri_len, _pri_len, sec_len, _sec_len;
|
||||
struct pdu_adv *_pri, *pri, *_sec, *sec;
|
||||
struct ext_adv_hdr *hp, _hp, *hs, _hs;
|
||||
struct ext_adv_sync_info *si;
|
||||
struct lll_adv_aux *lll_aux;
|
||||
uint8_t *_pp, *pp, *ps, *_ps;
|
||||
uint8_t ip, is, ad_len;
|
||||
struct lll_adv *lll;
|
||||
|
||||
sync = sync_acquire();
|
||||
if (!sync) {
|
||||
return BT_HCI_ERR_MEM_CAPACITY_EXCEEDED;
|
||||
}
|
||||
|
||||
lll = &sync->lll;
|
||||
adv->lll.sync = lll;
|
||||
lll = &adv->lll;
|
||||
lll_aux = lll->aux;
|
||||
if (!lll_aux) {
|
||||
}
|
||||
|
||||
lll_sync = &sync->lll;
|
||||
lll->sync = lll_sync;
|
||||
lll_sync->adv = lll;
|
||||
|
||||
ull_hdr_init(&sync->ull);
|
||||
lll_hdr_init(lll, sync);
|
||||
lll_hdr_init(lll_sync, sync);
|
||||
|
||||
util_aa_to_le32(lll->access_addr);
|
||||
util_rand(lll->crc_init, sizeof(lll->crc_init));
|
||||
util_aa_to_le32(lll_sync->access_addr);
|
||||
util_rand(lll_sync->crc_init, sizeof(lll_sync->crc_init));
|
||||
|
||||
lll->latency_prepare = 0;
|
||||
lll->latency_event = 0;
|
||||
lll->event_counter = 0;
|
||||
lll_sync->latency_prepare = 0;
|
||||
lll_sync->latency_event = 0;
|
||||
lll_sync->event_counter = 0;
|
||||
|
||||
lll->data_chan_count = ull_chan_map_get(lll->data_chan_map);
|
||||
lll->data_chan_id = 0;
|
||||
|
||||
lll->adv = &adv->lll;
|
||||
lll_sync->data_chan_count =
|
||||
ull_chan_map_get(lll_sync->data_chan_map);
|
||||
lll_sync->data_chan_id = 0;
|
||||
|
||||
/* Get reference to previous primary PDU data */
|
||||
_pri = lll_adv_data_peek(&adv->lll);
|
||||
_pri = lll_adv_data_peek(lll);
|
||||
_p = (void *)&_pri->adv_ext_ind;
|
||||
hp = (void *)_p->ext_hdr_adi_adv_data;
|
||||
*(uint8_t *)&_hp = *(uint8_t *)hp;
|
||||
_pp = (uint8_t *)hp + sizeof(*hp);
|
||||
|
||||
/* Get reference to new primary PDU data buffer */
|
||||
pri = lll_adv_data_alloc(&adv->lll, &ip);
|
||||
pri = lll_adv_data_alloc(lll, &ip);
|
||||
pri->type = _pri->type;
|
||||
pri->rfu = 0U;
|
||||
pri->chan_sel = 0U;
|
||||
|
@ -113,14 +124,14 @@ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
|
|||
*(uint8_t *)hp = 0U;
|
||||
|
||||
/* Get reference to previous secondary PDU data */
|
||||
_sec = lll_adv_aux_data_peek(&adv->lll);
|
||||
_sec = lll_adv_aux_data_peek(lll_aux);
|
||||
_s = (void *)&_sec->adv_ext_ind;
|
||||
hs = (void *)_s->ext_hdr_adi_adv_data;
|
||||
*(uint8_t *)&_hs = *(uint8_t *)hs;
|
||||
_ps = (uint8_t *)hs + sizeof(*hs);
|
||||
|
||||
/* Get reference to new secondary PDU data buffer */
|
||||
sec = lll_adv_aux_data_alloc(&adv->lll, &is);
|
||||
sec = lll_adv_aux_data_alloc(lll_aux, &is);
|
||||
sec->type = pri->type;
|
||||
sec->rfu = 0U;
|
||||
|
||||
|
@ -266,9 +277,10 @@ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
|
|||
si->offs = 0; /* NOTE: Filled by secondary prepare */
|
||||
si->offs_units = 0;
|
||||
si->interval = interval;
|
||||
memcpy(si->sca_chm, lll->data_chan_map, sizeof(si->sca_chm));
|
||||
memcpy(&si->aa, lll->access_addr, sizeof(si->aa));
|
||||
memcpy(si->crc_init, lll->crc_init, sizeof(si->crc_init));
|
||||
memcpy(si->sca_chm, lll_sync->data_chan_map,
|
||||
sizeof(si->sca_chm));
|
||||
memcpy(&si->aa, lll_sync->access_addr, sizeof(si->aa));
|
||||
memcpy(si->crc_init, lll_sync->crc_init, sizeof(si->crc_init));
|
||||
|
||||
si->evt_cntr = 0; /* TODO: Implementation defined */
|
||||
|
||||
|
@ -368,15 +380,15 @@ uint8_t ll_adv_sync_param_set(uint8_t handle, uint16_t interval, uint16_t flags)
|
|||
memcpy(ps, bdaddr, BDADDR_SIZE);
|
||||
}
|
||||
|
||||
lll_adv_aux_data_enqueue(&adv->lll, is);
|
||||
lll_adv_data_enqueue(&adv->lll, ip);
|
||||
lll_adv_aux_data_enqueue(lll_aux, is);
|
||||
lll_adv_data_enqueue(lll, ip);
|
||||
} else {
|
||||
sync = (void *)HDR_LLL2EVT(lll);
|
||||
sync = (void *)HDR_LLL2EVT(lll_sync);
|
||||
}
|
||||
|
||||
sync->interval = interval;
|
||||
|
||||
pdu = lll_adv_sync_data_peek(lll);
|
||||
pdu = lll_adv_sync_data_peek(lll_sync);
|
||||
pdu->type = PDU_ADV_TYPE_AUX_SYNC_IND;
|
||||
pdu->rfu = 0U;
|
||||
pdu->chan_sel = 0U;
|
||||
|
@ -440,7 +452,7 @@ uint8_t ll_adv_sync_ad_data_set(uint8_t handle, uint8_t op, uint8_t frag_pref,
|
|||
|
||||
uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
|
||||
{
|
||||
struct lll_adv_sync *lll;
|
||||
struct lll_adv_sync *lll_sync;
|
||||
struct ll_adv_sync_set *sync;
|
||||
struct ll_adv_set *adv;
|
||||
|
||||
|
@ -449,16 +461,22 @@ uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
|
|||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
lll = adv->lll.sync;
|
||||
if (!lll) {
|
||||
lll_sync = adv->lll.sync;
|
||||
if (!lll_sync) {
|
||||
return BT_HCI_ERR_UNKNOWN_ADV_IDENTIFIER;
|
||||
}
|
||||
|
||||
sync = (void *)HDR_LLL2EVT(lll);
|
||||
sync = (void *)HDR_LLL2EVT(lll_sync);
|
||||
|
||||
if (!enable) {
|
||||
/* TODO */
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
uint8_t err;
|
||||
|
||||
err = sync_stop(sync);
|
||||
if (err) {
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: Check for periodic data being complete */
|
||||
|
@ -474,6 +492,7 @@ uint8_t ll_adv_sync_enable(uint8_t handle, uint8_t enable)
|
|||
}
|
||||
|
||||
if (!sync->is_started) {
|
||||
/* TODO: */
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -513,11 +532,12 @@ uint32_t ull_adv_sync_start(struct ll_adv_sync_set *sync, uint32_t ticks_anchor,
|
|||
{
|
||||
uint32_t slot_us = EVENT_OVERHEAD_START_US + EVENT_OVERHEAD_END_US;
|
||||
uint32_t ticks_slot_overhead;
|
||||
uint32_t interval_us;
|
||||
uint8_t sync_handle;
|
||||
uint32_t ret;
|
||||
|
||||
/* TODO: Calc AUX_SYNC_IND slot_us */
|
||||
slot_us = 1000;
|
||||
slot_us += 1000;
|
||||
|
||||
/* TODO: active_to_start feature port */
|
||||
sync->evt.ticks_active_to_start = 0;
|
||||
|
@ -534,15 +554,16 @@ uint32_t ull_adv_sync_start(struct ll_adv_sync_set *sync, uint32_t ticks_anchor,
|
|||
ticks_slot_overhead = 0;
|
||||
}
|
||||
|
||||
interval_us = (uint64_t)sync->interval * 1250U;
|
||||
|
||||
sync_handle = sync_handle_get(sync);
|
||||
|
||||
*ret_cb = TICKER_STATUS_BUSY;
|
||||
ret = ticker_start(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
|
||||
(TICKER_ID_ADV_SYNC_BASE + sync_handle),
|
||||
ticks_anchor, 0,
|
||||
HAL_TICKER_US_TO_TICKS((uint64_t)sync->interval *
|
||||
1250),
|
||||
TICKER_NULL_REMAINDER, TICKER_NULL_LAZY,
|
||||
HAL_TICKER_US_TO_TICKS(interval_us),
|
||||
HAL_TICKER_REMAINDER(interval_us), TICKER_NULL_LAZY,
|
||||
(sync->evt.ticks_slot + ticks_slot_overhead),
|
||||
ticker_cb, sync,
|
||||
ull_ticker_status_give, (void *)ret_cb);
|
||||
|
@ -550,6 +571,18 @@ uint32_t ull_adv_sync_start(struct ll_adv_sync_set *sync, uint32_t ticks_anchor,
|
|||
return ret;
|
||||
}
|
||||
|
||||
void ull_adv_sync_offset_get(struct ll_adv_set *adv)
|
||||
{
|
||||
static memq_link_t link;
|
||||
static struct mayfly mfy = {0, 0, &link, NULL, mfy_sync_offset_get};
|
||||
uint32_t ret;
|
||||
|
||||
mfy.param = adv;
|
||||
ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_ULL_LOW, 1,
|
||||
&mfy);
|
||||
LL_ASSERT(!ret);
|
||||
}
|
||||
|
||||
static int init_reset(void)
|
||||
{
|
||||
/* Initialize adv sync pool. */
|
||||
|
@ -576,6 +609,94 @@ static inline uint16_t sync_handle_get(struct ll_adv_sync_set *sync)
|
|||
sizeof(struct ll_adv_sync_set));
|
||||
}
|
||||
|
||||
static inline uint8_t sync_stop(struct ll_adv_sync_set *sync)
|
||||
{
|
||||
volatile uint32_t ret_cb = TICKER_STATUS_BUSY;
|
||||
uint8_t sync_handle;
|
||||
void *mark;
|
||||
uint32_t ret;
|
||||
|
||||
mark = ull_disable_mark(sync);
|
||||
LL_ASSERT(mark == sync);
|
||||
|
||||
sync_handle = sync_handle_get(sync);
|
||||
|
||||
ret = ticker_stop(TICKER_INSTANCE_ID_CTLR, TICKER_USER_ID_THREAD,
|
||||
TICKER_ID_ADV_SYNC_BASE + sync_handle,
|
||||
ull_ticker_status_give, (void *)&ret_cb);
|
||||
|
||||
ret = ull_ticker_status_take(ret, &ret_cb);
|
||||
if (ret) {
|
||||
mark = ull_disable_mark(sync);
|
||||
LL_ASSERT(mark == sync);
|
||||
|
||||
return BT_HCI_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
ret = ull_disable(&sync->lll);
|
||||
LL_ASSERT(!ret);
|
||||
|
||||
mark = ull_disable_unmark(sync);
|
||||
LL_ASSERT(mark == sync);
|
||||
|
||||
sync->is_started = 0U;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mfy_sync_offset_get(void *param)
|
||||
{
|
||||
struct ll_adv_set *adv = param;
|
||||
struct ll_adv_sync_set *sync;
|
||||
uint32_t ticks_to_expire;
|
||||
uint32_t ticks_current;
|
||||
struct pdu_adv *pdu;
|
||||
uint8_t ticker_id;
|
||||
uint8_t retry;
|
||||
uint8_t id;
|
||||
|
||||
sync = (void *)HDR_LLL2EVT(adv->lll.sync);
|
||||
ticker_id = TICKER_ID_ADV_SYNC_BASE + sync_handle_get(sync);
|
||||
|
||||
id = TICKER_NULL;
|
||||
ticks_to_expire = 0U;
|
||||
ticks_current = 0U;
|
||||
retry = 4U;
|
||||
do {
|
||||
uint32_t volatile ret_cb = TICKER_STATUS_BUSY;
|
||||
uint32_t ticks_previous;
|
||||
uint32_t ret;
|
||||
|
||||
ticks_previous = ticks_current;
|
||||
|
||||
ret = ticker_next_slot_get(TICKER_INSTANCE_ID_CTLR,
|
||||
TICKER_USER_ID_ULL_LOW,
|
||||
&id,
|
||||
&ticks_current, &ticks_to_expire,
|
||||
ticker_op_cb, (void *)&ret_cb);
|
||||
if (ret == TICKER_STATUS_BUSY) {
|
||||
while (ret_cb == TICKER_STATUS_BUSY) {
|
||||
ticker_job_sched(TICKER_INSTANCE_ID_CTLR,
|
||||
TICKER_USER_ID_ULL_LOW);
|
||||
}
|
||||
}
|
||||
|
||||
LL_ASSERT(ret_cb == TICKER_STATUS_SUCCESS);
|
||||
|
||||
LL_ASSERT((ticks_current == ticks_previous) || retry--);
|
||||
|
||||
LL_ASSERT(id != TICKER_NULL);
|
||||
} while (id != ticker_id);
|
||||
|
||||
/* NOTE: as remainder not used in scheduling primary PDU
|
||||
* packet timer starts transmission after 1 tick hence the +1.
|
||||
*/
|
||||
sync->lll.ticks_offset = ticks_to_expire + 1;
|
||||
|
||||
pdu = lll_adv_aux_data_curr_get(adv->lll.aux);
|
||||
lll_adv_sync_offset_fill(ticks_to_expire, 0, pdu);
|
||||
}
|
||||
|
||||
static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
|
||||
uint16_t lazy, void *param)
|
||||
{
|
||||
|
@ -609,3 +730,8 @@ static void ticker_cb(uint32_t ticks_at_expire, uint32_t remainder,
|
|||
|
||||
DEBUG_RADIO_PREPARE_A(1);
|
||||
}
|
||||
|
||||
static void ticker_op_cb(uint32_t status, void *param)
|
||||
{
|
||||
*((uint32_t volatile *)param) = status;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,16 @@ struct ll_adv_set {
|
|||
#endif /* CONFIG_BT_CTLR_PRIVACY */
|
||||
};
|
||||
|
||||
struct ll_adv_aux_set {
|
||||
struct evt_hdr evt;
|
||||
struct ull_hdr ull;
|
||||
struct lll_adv_aux lll;
|
||||
|
||||
uint16_t interval;
|
||||
|
||||
uint8_t is_started:1;
|
||||
};
|
||||
|
||||
struct ll_adv_sync_set {
|
||||
struct evt_hdr evt;
|
||||
struct ull_hdr ull;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue