Bluetooth: controller: ISO resume ticker in ULL
Added function ull_conn_iso_resume_ticker_start to enable LLL ISO
peripheral/central to start the one-shot resume ticker.
At timeout the common lll_resume handler is called, and based on the
LLL state, the peripheral/central is able to resume the CIG event.
The resume acts exactly like a normal event resume from the prepare
pipeline, with the exception that the LLL must provide specific
lll_event instances.
Signed-off-by: Morten Priess <mtpr@oticon.com>
diff --git a/subsys/bluetooth/controller/ll_sw/lll.h b/subsys/bluetooth/controller/ll_sw/lll.h
index 25feeb6..1352e93 100644
--- a/subsys/bluetooth/controller/ll_sw/lll.h
+++ b/subsys/bluetooth/controller/ll_sw/lll.h
@@ -113,6 +113,9 @@
TICKER_ID_CONN_ISO_BASE,
TICKER_ID_CONN_ISO_LAST = ((TICKER_ID_CONN_ISO_BASE) +
(CONFIG_BT_CTLR_CONN_ISO_GROUPS) - 1),
+ TICKER_ID_CONN_ISO_RESUME_BASE,
+ TICKER_ID_CONN_ISO_RESUME_LAST = ((TICKER_ID_CONN_ISO_RESUME_BASE) +
+ (CONFIG_BT_CTLR_CONN_ISO_GROUPS) - 1),
#endif /* CONFIG_BT_CTLR_CONN_ISO */
#if defined(CONFIG_BT_CTLR_USER_EXT) && \
diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h
index c95236b..7e2bbf0 100644
--- a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h
+++ b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h
@@ -31,7 +31,6 @@
uint8_t access_addr[4]; /* Access address */
uint32_t offset; /* Offset of CIS from start of CIG in us */
uint32_t sub_interval; /* Interval between subevents in us */
- uint32_t subevent_length; /* Length of subevent in us */
uint8_t num_subevents; /* Number of subevents */
struct lll_conn_iso_stream_rxtx rx; /* RX parameters */
struct lll_conn_iso_stream_rxtx tx; /* TX parameters */
@@ -57,16 +56,16 @@
struct lll_conn_iso_group {
struct lll_hdr hdr;
- uint16_t handle; /* CIG handle (internal) */
- uint8_t num_cis; /* Number of CISes in this CIG */
- uint8_t role; /* 0: CENTRAL, 1: PERIPHERAL*/
+ uint16_t handle; /* CIG handle (internal) */
+ uint8_t num_cis : 5; /* Number of CISes in this CIG */
+ uint8_t role : 1; /* 0: CENTRAL, 1: PERIPHERAL*/
+ uint8_t paused : 1; /* 1: CIG is paused */
#if defined(CONFIG_BT_CTLR_CONN_ISO_STREAMS_PER_GROUP)
uint16_t cis_handles[CONFIG_BT_CTLR_CONN_ISO_STREAMS_PER_GROUP];
#endif /* CONFIG_BT_CTLR_CONN_ISO_STREAMS */
/* Resumption information */
- uint8_t next_cis; /* Next CIS to schedule */
- uint32_t next_time; /* When to trigger next activity in the CIG */
+ uint8_t resume_cis; /* CIS index to schedule at resume */
};
int lll_conn_iso_init(void);
diff --git a/subsys/bluetooth/controller/ll_sw/ull.c b/subsys/bluetooth/controller/ll_sw/ull.c
index f8e2e7f..d1086230 100644
--- a/subsys/bluetooth/controller/ll_sw/ull.c
+++ b/subsys/bluetooth/controller/ll_sw/ull.c
@@ -146,7 +146,10 @@
#if defined(CONFIG_BT_CTLR_CONN_ISO)
#define BT_CIG_TICKER_NODES ((TICKER_ID_CONN_ISO_LAST) - \
- (TICKER_ID_CONN_ISO_BASE) + 1)
+ (TICKER_ID_CONN_ISO_BASE) + 1 + \
+ (TICKER_ID_CONN_ISO_RESUME_LAST) - \
+ (TICKER_ID_CONN_ISO_RESUME_BASE) + 1)
+
#else
#define BT_CIG_TICKER_NODES 0
#endif
diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c
index a7ebf12..4d2d5a4 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c
+++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso.c
@@ -11,12 +11,19 @@
#include "util/memq.h"
#include "util/mayfly.h"
#include "ticker/ticker.h"
+#include "hal/ccm.h"
+#include "hal/ticker.h"
+#include "pdu.h"
#include "lll.h"
+#include "lll_conn.h"
+#include "ull_conn_types.h"
#include "lll_conn_iso.h"
#include "ull_conn_iso_types.h"
+#include "ull_conn_internal.h"
#include "ull_internal.h"
+#include "lll/lll_vendor.h"
#define BT_DBG_ENABLED IS_ENABLED(CONFIG_BT_DEBUG_HCI_DRIVER)
#define LOG_MODULE_NAME bt_ctlr_ull_conn_iso
@@ -226,3 +233,94 @@
((void *)conn == ull_disable_mark_get()));
}
}
+
+static void ticker_resume_op_cb(uint32_t status, void *param)
+{
+ ARG_UNUSED(param);
+
+ LL_ASSERT(status == TICKER_STATUS_SUCCESS);
+}
+
+static void ticker_resume_cb(uint32_t ticks_at_expire, uint32_t remainder,
+ uint16_t lazy, uint8_t force, void *param)
+{
+ static memq_link_t link;
+ static struct mayfly mfy = {0, 0, &link, NULL, lll_resume};
+ struct lll_event *resume_event;
+ uint32_t ret;
+
+ LL_ASSERT(lazy == 0);
+
+ resume_event = param;
+
+ /* Append timing parameters */
+ resume_event->prepare_param.ticks_at_expire = ticks_at_expire;
+ resume_event->prepare_param.remainder = remainder;
+ resume_event->prepare_param.lazy = 0;
+ resume_event->prepare_param.force = force;
+ mfy.param = resume_event;
+
+ /* Kick LLL resume */
+ ret = mayfly_enqueue(TICKER_USER_ID_ULL_HIGH, TICKER_USER_ID_LLL,
+ 0, &mfy);
+
+ LL_ASSERT(!ret);
+}
+
+void ull_conn_iso_resume_ticker_start(struct lll_event *resume_event,
+ uint8_t resume_cis_index,
+ uint32_t ticks_anchor,
+ uint32_t resume_timeout)
+{
+ struct lll_conn_iso_group *cig;
+ uint32_t ready_delay_us;
+ uint32_t resume_delay_us;
+ int32_t resume_offset_us;
+ uint8_t ticker_id;
+ uint32_t ret;
+
+ cig = resume_event->prepare_param.param;
+ ticker_id = TICKER_ID_CONN_ISO_RESUME_BASE + cig->handle;
+
+ cig->resume_cis = resume_cis_index;
+
+ if (0) {
+#if defined(CONFIG_BT_CTLR_PHY)
+ } else {
+ struct ll_conn_iso_stream *cis;
+ struct ll_conn *acl;
+
+ cis = ll_conn_iso_stream_get(cig->cis_handles[resume_cis_index]);
+ acl = ll_conn_get(cis->lll.acl_handle);
+
+ ready_delay_us = lll_radio_rx_ready_delay_get(acl->lll.phy_rx, 1);
+#else
+ } else {
+ ready_delay_us = lll_radio_rx_ready_delay_get(0, 0);
+#endif /* CONFIG_BT_CTLR_PHY */
+ }
+
+ resume_delay_us = EVENT_OVERHEAD_START_US;
+ resume_delay_us += EVENT_TICKER_RES_MARGIN_US;
+ resume_delay_us += EVENT_JITTER_US;
+ resume_delay_us += ready_delay_us;
+
+ resume_offset_us = (int32_t)(resume_timeout - resume_delay_us);
+ LL_ASSERT(resume_offset_us >= 0);
+
+ /* Setup resume timeout as single-shot */
+ ret = ticker_start(TICKER_INSTANCE_ID_CTLR,
+ TICKER_USER_ID_LLL,
+ ticker_id,
+ ticks_anchor,
+ HAL_TICKER_US_TO_TICKS(resume_offset_us),
+ TICKER_NULL_PERIOD,
+ TICKER_NULL_REMAINDER,
+ TICKER_NULL_LAZY,
+ TICKER_NULL_SLOT,
+ ticker_resume_cb, resume_event,
+ ticker_resume_op_cb, NULL);
+
+ LL_ASSERT((ret == TICKER_STATUS_SUCCESS) ||
+ (ret == TICKER_STATUS_BUSY));
+}
diff --git a/subsys/bluetooth/controller/ll_sw/ull_conn_iso_internal.h b/subsys/bluetooth/controller/ll_sw/ull_conn_iso_internal.h
index 0f7557c..bb73ce5 100644
--- a/subsys/bluetooth/controller/ll_sw/ull_conn_iso_internal.h
+++ b/subsys/bluetooth/controller/ll_sw/ull_conn_iso_internal.h
@@ -22,3 +22,8 @@
void ull_conn_iso_done(struct node_rx_event_done *done);
void ull_conn_iso_cis_established(struct ll_conn_iso_stream *cis);
+
+void ull_conn_iso_resume_ticker_start(struct lll_event *resume_event,
+ uint8_t resume_cis,
+ uint32_t ticks_anchor,
+ uint32_t resume_timeout);