diff --git a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h index dadaa37ac3a5d53..0568cbc0308a8fc 100644 --- a/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h +++ b/subsys/bluetooth/controller/ll_sw/lll_conn_iso.h @@ -12,8 +12,7 @@ struct lll_conn_iso_stream_rxtx { uint64_t bn:4; /* Burst number (BN) */ uint64_t phy:3; /* PHY */ uint64_t rfu:1; - uint8_t bn_curr:4; /* Current burst number */ - + uint8_t bn_curr:4; /* Current burst number */ #if defined(CONFIG_BT_CTLR_LE_ENC) struct ccm ccm; @@ -46,6 +45,8 @@ struct lll_conn_iso_stream { uint8_t active:1; /* 1 if CIS LLL is active */ uint8_t datapath_ready_rx:1;/* 1 if datapath for RX is ready */ + uint8_t se_curr:5; + #if !defined(CONFIG_BT_CTLR_JIT_SCHEDULING) /* Lazy at CIS active. Number of previously skipped CIG events that is * determined when CIS is made active and subtracted from total CIG diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c index f46fc50bdce2dc8..34b8430b4d57e85 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_central_iso.c @@ -40,14 +40,15 @@ #include "hal/debug.h" static int init_reset(void); -static inline void lll_flush_tx(struct lll_conn_iso_stream *cis_lll); -static inline void lll_flush_rx(struct lll_conn_iso_stream *cis_lll); static int prepare_cb(struct lll_prepare_param *p); static void abort_cb(struct lll_prepare_param *prepare_param, void *param); static void isr_tx(void *param); static void isr_rx(void *param); static void isr_prepare_subevent(void *param); static void isr_done(void *param); +static void payload_count_flush(struct lll_conn_iso_stream *cis_lll); +static void payload_count_flush_or_inc_on_close(struct lll_conn_iso_stream *cis_lll); +static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy); static uint16_t next_cis_chan_remap_idx; static uint16_t next_cis_chan_prn_s; @@ -118,24 +119,6 @@ static int init_reset(void) return 0; } -static inline void lll_flush_tx(struct lll_conn_iso_stream *cis_lll) -{ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; - - /* we'll re-use sn_update when implementing flush timeout */ - cis_lll->sn += sn_update; -} - -static inline void lll_flush_rx(struct lll_conn_iso_stream *cis_lll) -{ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; - - /* we'll re-use sn_update when implementing flush timeout */ - cis_lll->nesn += nesn_update; -} - static int prepare_cb(struct lll_prepare_param *p) { struct lll_conn_iso_group *cig_lll = p->param; @@ -207,14 +190,11 @@ static int prepare_cb(struct lll_prepare_param *p) cis_lazy = lazy; } - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - cis_lll->sn += cis_lll->tx.bn * cis_lazy; - cis_lll->nesn += cis_lll->rx.bn * cis_lazy; + /* Adjust sn and nesn for skipped CIG events */ + payload_count_lazy(cis_lll, cis_lazy); } se_curr = 1U; - cis_lll->tx.bn_curr = 1U; - cis_lll->rx.bn_curr = 1U; /* Start setting up of Radio h/w */ radio_reset(); @@ -248,7 +228,8 @@ static int prepare_cb(struct lll_prepare_param *p) struct node_tx_iso *node_tx; memq_link_t *link; - payload_count = cis_lll->event_count * cis_lll->tx.bn; + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; do { link = memq_peek(cis_lll->memq_tx.head, @@ -407,23 +388,12 @@ static int prepare_cb(struct lll_prepare_param *p) cis_lazy = lazy; } - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - cis_lll->sn += cis_lll->tx.bn * cis_lazy; - cis_lll->nesn += cis_lll->rx.bn * cis_lazy; + /* Adjust sn and nesn for skipped CIG events */ + payload_count_lazy(cis_lll, cis_lazy); /* Adjust sn and nesn for canceled events */ if (err) { - /* Adjust sn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } + payload_count_flush_or_inc_on_close(cis_lll); } } } @@ -449,9 +419,21 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* NOTE: This is not a prepare being cancelled */ if (!prepare_param) { + struct lll_conn_iso_stream *next_cis_lll; struct lll_conn_iso_stream *cis_lll; + struct lll_conn_iso_group *cig_lll; cis_lll = ull_conn_iso_lll_stream_get(cis_handle_curr); + cig_lll = param; + + /* Adjust the SN, NESN and payload_count on abort for CISes */ + do { + next_cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, + &cis_handle_curr); + if (next_cis_lll && next_cis_lll->active) { + payload_count_flush_or_inc_on_close(next_cis_lll); + } + } while (next_cis_lll); /* Perform event abort here. * After event has been cleanly aborted, clean up resources @@ -504,8 +486,8 @@ static void isr_tx(void *param) uint64_t payload_count; uint8_t pkt_flags; - payload_count = (cis_lll->event_count * cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + payload_count = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; cis_lll->rx.ccm.counter = payload_count; pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_DC, @@ -646,7 +628,9 @@ static void isr_tx(void *param) cis_lll = next_cis_lll; /* Tx Ack stale ISO Data */ - payload_count = cis_lll->event_count * cis_lll->tx.bn; + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; + do { link = memq_peek(cis_lll->memq_tx.head, cis_lll->memq_tx.tail, @@ -708,6 +692,8 @@ static void isr_rx(void *param) /* No Rx */ if (!trx_done) { + payload_count_flush(cis_lll); + goto isr_rx_next_subevent; } @@ -725,15 +711,16 @@ static void isr_rx(void *param) if (crc_ok) { /* Tx ACK */ - if (pdu_rx->nesn != cis_lll->sn) { - /* Increment sequence number */ - cis_lll->sn++; - - /* Increment burst number */ + if (cis_lll->npi || (pdu_rx->nesn != cis_lll->sn)) { if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - + cis_lll->sn++; cis_lll->tx.bn_curr++; - + if ((cis_lll->tx.bn_curr > cis_lll->tx.bn) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < + cis_lll->event_count)) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } } /* TODO: Implement early Tx Ack. Currently Tx Ack @@ -749,7 +736,6 @@ static void isr_rx(void *param) ull_iso_pdu_rx_alloc_peek(2U)) { struct node_rx_iso_meta *iso_meta; - /* Increment next expected sequence number */ cis_lll->nesn++; #if defined(CONFIG_BT_CTLR_LE_ENC) @@ -780,9 +766,8 @@ static void isr_rx(void *param) node_rx->hdr.type = NODE_RX_TYPE_ISO_PDU; node_rx->hdr.handle = cis_lll->handle; iso_meta = &node_rx->hdr.rx_iso_meta; - iso_meta->payload_number = (cis_lll->event_count * - cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + iso_meta->payload_number = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; iso_meta->timestamp = HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + radio_tmr_ready_restore(); @@ -797,8 +782,12 @@ static void isr_rx(void *param) iso_rx_sched(); #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */ - /* Increment burst number */ cis_lll->rx.bn_curr++; + if ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) < cis_lll->event_count)) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } /* Need to be acked */ ack_pending = 1U; @@ -810,11 +799,14 @@ static void isr_rx(void *param) * burst. */ if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - /* Increment next expected serial number */ cis_lll->nesn++; - - /* Increment burst number */ cis_lll->rx.bn_curr++; + if ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) < + cis_lll->event_count)) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } } /* Not NPI, or more than the BN, or no free Rx ISO PDU buffers. @@ -827,6 +819,8 @@ static void isr_rx(void *param) cie = cie || pdu_rx->cie; } + payload_count_flush(cis_lll); + /* Close Isochronous Event */ cie = cie || ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && (cis_lll->tx.bn_curr > cis_lll->tx.bn) && @@ -887,7 +881,8 @@ static void isr_rx(void *param) old_cis_lll = cis_lll; cis_lll = next_cis_lll; - payload_count = cis_lll->event_count * cis_lll->tx.bn; + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; do { link = memq_peek(cis_lll->memq_tx.head, @@ -921,22 +916,10 @@ static void isr_rx(void *param) cis_lll = old_cis_lll; } - /* Adjust sn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } + payload_count_flush_or_inc_on_close(cis_lll); /* Reset indices for the next CIS */ se_curr = 0U; /* isr_prepare_subevent() will increase se_curr */ - next_cis_lll->tx.bn_curr = 1U; - next_cis_lll->rx.bn_curr = 1U; #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL) radio_tx_power_set(next_cis_lll->tx_pwr_lvl); @@ -995,8 +978,7 @@ static void isr_prepare_subevent(void *param) memq_link_t *link; payload_index = cis_lll->tx.bn_curr - 1U; - payload_count = cis_lll->event_count * cis_lll->tx.bn + - payload_index; + payload_count = cis_lll->tx.payload_count + payload_index; link = memq_peek_n(cis_lll->memq_tx.head, cis_lll->memq_tx.tail, payload_index, (void **)&node_tx); @@ -1131,17 +1113,7 @@ static void isr_done(void *param) /* Get reference to CIS LLL context */ cis_lll = param; - /* Adjust sn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } + payload_count_flush_or_inc_on_close(cis_lll); e = ull_event_done_extra_get(); LL_ASSERT(e); @@ -1156,3 +1128,147 @@ static void isr_done(void *param) lll_isr_cleanup(param); } + +static void payload_count_flush(struct lll_conn_iso_stream *cis_lll) +{ + if (cis_lll->tx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + if (((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr + + cis_lll->tx.ft + u) < + (cis_lll->event_count + se_curr + 2U)) { + uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn += sn_update; + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + } + + if (cis_lll->rx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + if (((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr + + cis_lll->rx.ft + u) < + (cis_lll->event_count + se_curr + 2U)) { + uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn += nesn_update; + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + } +} + +static void payload_count_flush_or_inc_on_close(struct lll_conn_iso_stream *cis_lll) +{ + if (cis_lll->tx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + if ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr + + cis_lll->tx.ft + u) <= + (cis_lll->event_count + cis_lll->nse + 2U)) || + (((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr) > + (cis_lll->event_count + cis_lll->tx.bn))) { + uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn += sn_update; + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + } + + if (cis_lll->rx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + if ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr + + cis_lll->rx.ft + u) <= + (cis_lll->event_count + cis_lll->nse + 2U)) || + (((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr) > + (cis_lll->event_count + cis_lll->rx.bn))) { + uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn += nesn_update; + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + } +} + +static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy) +{ + if (cis_lll->tx.bn) { + uint16_t tx_lazy; + + tx_lazy = lazy; + while (tx_lazy--) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + if ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr + + cis_lll->tx.ft + u) < + (cis_lll->event_count + cis_lll->nse + 2U)) || + (((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr) > + (cis_lll->event_count + cis_lll->tx.bn))) { + uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn += sn_update; + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + } + } + + if (cis_lll->rx.bn) { + while (lazy--) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + if ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr + + cis_lll->rx.ft + u) < + (cis_lll->event_count + cis_lll->nse + 2U)) || + (((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr) > + (cis_lll->event_count + cis_lll->rx.bn))) { + uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn += nesn_update; + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + } + } +} diff --git a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c index dacb9f409402875..96526ed96ee2d64 100644 --- a/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/nordic/lll/lll_peripheral_iso.c @@ -49,8 +49,9 @@ static void isr_prepare_subevent(void *param); static void isr_prepare_subevent_next_cis(void *param); static void isr_prepare_subevent_common(void *param); static void isr_done(void *param); -static inline void lll_flush_tx(struct lll_conn_iso_stream *cis_lll); -static inline void lll_flush_rx(struct lll_conn_iso_stream *cis_lll); +static void payload_count_txrx_flush_or_tx_inc(struct lll_conn_iso_stream *cis_lll); +static void payload_count_rx_flush_or_txrx_inc(struct lll_conn_iso_stream *cis_lll); +static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy); static uint8_t next_chan_use; static uint16_t data_chan_id; @@ -60,7 +61,6 @@ static uint16_t data_chan_remap_idx; static uint32_t trx_performed_bitmask; static uint16_t cis_offset_first; static uint16_t cis_handle_curr; -static uint8_t se_curr; static uint8_t has_tx; #if defined(CONFIG_BT_CTLR_LE_ENC) @@ -135,24 +135,6 @@ static int init_reset(void) return 0; } -static inline void lll_flush_tx(struct lll_conn_iso_stream *cis_lll) -{ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; - - /* TODO we'll re-use sn_update when implementing flush timeout */ - cis_lll->sn += sn_update; -} - -static inline void lll_flush_rx(struct lll_conn_iso_stream *cis_lll) -{ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; - - /* TODO we'll re-use nesn_update when implementing flush timeout */ - cis_lll->nesn += nesn_update; -} - static int prepare_cb(struct lll_prepare_param *p) { struct lll_conn_iso_group *cig_lll = p->param; @@ -226,12 +208,8 @@ static int prepare_cb(struct lll_prepare_param *p) } /* Adjust sn and nesn for skipped CIG events */ - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - cis_lll->sn += (cis_lll->tx.bn * lazy); - cis_lll->nesn += cis_lll->rx.bn * lazy; + payload_count_lazy(cis_lll, lazy); - se_curr = 1U; - cis_lll->rx.bn_curr = 1U; has_tx = 0U; /* Start setting up of Radio h/w */ @@ -260,8 +238,9 @@ static int prepare_cb(struct lll_prepare_param *p) uint64_t payload_count; uint8_t pkt_flags; - payload_count = (cis_lll->event_count * cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + payload_count = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; + cis_lll->rx.ccm.counter = payload_count; pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_DC, @@ -371,9 +350,10 @@ static int prepare_cb(struct lll_prepare_param *p) /* Adjust the SN and NESN for skipped CIG events */ uint16_t cis_handle = cis_handle_curr; - while (true) { - /* FIXME: Update below implementation when supporting Flush Timeout */ - payload_count = cis_lll->event_count * cis_lll->tx.bn; + do { + payload_count = cis_lll->tx.payload_count + + cis_lll->tx.bn_curr - 1U; + do { link = memq_peek(cis_lll->memq_tx.head, cis_lll->memq_tx.tail, (void **)&tx); @@ -391,26 +371,22 @@ static int prepare_cb(struct lll_prepare_param *p) } } while (link); - cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); + do { + cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); + } while (cis_lll && !cis_lll->active); + if (!cis_lll) { break; } - if (cis_lll->active) { - /* sn and nesn are 1-bit, only Least Significant bit is needed */ - cis_lll->sn += cis_lll->tx.bn * lazy; - cis_lll->nesn += cis_lll->rx.bn * lazy; - - /* Adjust sn and nesn for canceled events */ - if (err) { - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } - } + /* Adjust sn and nesn for skipped CIG events */ + payload_count_lazy(cis_lll, lazy); + + /* Adjust sn and nesn for canceled events */ + if (err) { + payload_count_rx_flush_or_txrx_inc(cis_lll); } - }; + } while (cis_lll); /* Return if prepare callback cancelled */ if (err) { @@ -432,24 +408,21 @@ static void abort_cb(struct lll_prepare_param *prepare_param, void *param) /* NOTE: This is not a prepare being cancelled */ if (!prepare_param) { - struct lll_conn_iso_group *cig_lll = param; + struct lll_conn_iso_stream *next_cis_lll; struct lll_conn_iso_stream *cis_lll; + struct lll_conn_iso_group *cig_lll; - cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, NULL); - - /* FIXME: Consider Flush Timeout when resetting current burst number */ - if (!has_tx) { - has_tx = 1U; + cis_lll = ull_conn_iso_lll_stream_get(cis_handle_curr); + cig_lll = param; - /* Adjust nesn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); + /* Adjust the SN, NESN and payload_count on abort for CISes */ + do { + next_cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, + &cis_handle_curr); + if (next_cis_lll && next_cis_lll->active) { + payload_count_txrx_flush_or_tx_inc(cis_lll); } - - /* Set to last burst number in previous event */ - cis_lll->tx.bn_curr = cis_lll->tx.bn; - } + } while (next_cis_lll); /* Perform event abort here. * After event has been cleanly aborted, clean up resources @@ -499,21 +472,9 @@ static void isr_rx(void *param) /* No Rx */ if (!trx_done) { - /* FIXME: Consider Flush Timeout when resetting current burst number */ - if (!has_tx) { - has_tx = 1U; + payload_count_txrx_flush_or_tx_inc(cis_lll); - /* Adjust nesn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Start transmitting new burst */ - cis_lll->tx.bn_curr = cis_lll->tx.bn; - } - - if (se_curr < cis_lll->nse) { + if (cis_lll->se_curr < cis_lll->nse) { radio_isr_set(isr_prepare_subevent, param); } else { next_cis_prepare(param); @@ -533,7 +494,11 @@ static void isr_rx(void *param) if (!radio_tmr_aa_restore()) { uint32_t se_offset_us; - se_offset_us = cis_lll->sub_interval * (se_curr - 1U); + if (has_tx) { + se_offset_us = cis_lll->sub_interval * (cis_lll->se_curr - 1U); + } else { + se_offset_us = 0U; + } radio_tmr_aa_save(radio_tmr_aa_get() - se_offset_us); radio_tmr_ready_save(radio_tmr_ready_get() - se_offset_us); } @@ -561,17 +526,22 @@ static void isr_rx(void *param) pdu_rx = (void *)node_rx->pdu; /* Tx ACK */ - if (pdu_rx->nesn != cis_lll->sn) { - /* Increment sequence number */ - cis_lll->sn++; - - /* Increment burst number */ + if (cis_lll->npi || (pdu_rx->nesn != cis_lll->sn)) { if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { + cis_lll->sn++; cis_lll->tx.bn_curr++; + if ((cis_lll->tx.bn_curr > cis_lll->tx.bn) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < + cis_lll->event_count)) { + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } } - /* TODO: Tx Ack */ - + /* TODO: Implement early Tx Ack. Currently Tx Ack + * generated as stale Tx Ack when payload count + * has elapsed. + */ } /* Handle valid ISO data Rx */ @@ -581,7 +551,6 @@ static void isr_rx(void *param) ull_iso_pdu_rx_alloc_peek(2U)) { struct node_rx_iso_meta *iso_meta; - /* Increment next expected sequence number */ cis_lll->nesn++; #if defined(CONFIG_BT_CTLR_LE_ENC) @@ -613,9 +582,8 @@ static void isr_rx(void *param) node_rx->hdr.type = NODE_RX_TYPE_ISO_PDU; node_rx->hdr.handle = cis_lll->handle; iso_meta = &node_rx->hdr.rx_iso_meta; - iso_meta->payload_number = (cis_lll->event_count * - cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + iso_meta->payload_number = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; iso_meta->timestamp = HAL_TICKER_TICKS_TO_US(radio_tmr_start_get()) + radio_tmr_aa_restore() - @@ -631,8 +599,12 @@ static void isr_rx(void *param) iso_rx_sched(); #endif /* CONFIG_BT_CTLR_LOW_LAT_ULL */ - /* Increment burst number */ cis_lll->rx.bn_curr++; + if ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) < cis_lll->event_count)) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } /* Handle NULL PDU indication received */ } else if (pdu_rx->npi) { @@ -641,11 +613,14 @@ static void isr_rx(void *param) * burst. */ if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - /* Increment next expected serial number */ cis_lll->nesn++; - - /* Increment burst number */ cis_lll->rx.bn_curr++; + if ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && + ((cis_lll->rx.payload_count / cis_lll->rx.bn) < + cis_lll->event_count)) { + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } } /* Not NPI, or more than the BN, or no free Rx ISO PDU buffers. @@ -658,24 +633,12 @@ static void isr_rx(void *param) cie = cie || pdu_rx->cie; } - /* FIXME: Consider Flush Timeout when resetting current burst number */ - if (!has_tx) { - has_tx = 1U; - - /* Adjust nesn when flushing Tx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->tx.bn_curr <= cis_lll->tx.bn) { - lll_flush_tx(cis_lll); - } - - /* Start transmitting new burst */ - cis_lll->tx.bn_curr = 1U; - } + payload_count_txrx_flush_or_tx_inc(cis_lll); /* Close Isochronous Event */ cie = cie || ((cis_lll->rx.bn_curr > cis_lll->rx.bn) && (cis_lll->tx.bn_curr > cis_lll->tx.bn) && - (se_curr < cis_lll->nse)); + (cis_lll->se_curr < cis_lll->nse)); /* Get ISO data PDU */ if (cis_lll->tx.bn_curr > cis_lll->tx.bn) { @@ -695,8 +658,7 @@ static void isr_rx(void *param) memq_link_t *link; payload_index = cis_lll->tx.bn_curr - 1U; - payload_count = cis_lll->event_count * cis_lll->tx.bn + - payload_index; + payload_count = cis_lll->tx.payload_count + payload_index; link = memq_peek_n(cis_lll->memq_tx.head, cis_lll->memq_tx.tail, payload_index, (void **)&tx); @@ -787,7 +749,7 @@ static void isr_rx(void *param) LL_ASSERT(!radio_is_ready()); /* Schedule next subevent */ - if (!cie && (se_curr < cis_lll->nse)) { + if (!cie && (cis_lll->se_curr < cis_lll->nse)) { /* Calculate the radio channel to use for next subevent */ next_chan_use = lll_chan_iso_subevent(data_chan_id, @@ -796,6 +758,7 @@ static void isr_rx(void *param) &data_chan_prn_s, &data_chan_remap_idx); } else { + struct lll_conn_iso_stream *next_cis_lll; struct lll_conn_iso_group *cig_lll; uint16_t event_counter; uint16_t cis_handle; @@ -804,40 +767,45 @@ static void isr_rx(void *param) cig_lll = ull_conn_iso_lll_group_get_by_stream(cis_lll); cis_handle = cis_handle_curr; do { - cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); - } while (cis_lll && !cis_lll->active); + next_cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); + } while (next_cis_lll && !next_cis_lll->active); - if (!cis_lll) { + if (!next_cis_lll) { /* ISO Event Done */ radio_isr_set(isr_done, param); return; } + payload_count_rx_flush_or_txrx_inc(cis_lll); + cis_handle_curr = cis_handle; /* Event counter value, 0-15 bit of cisEventCounter */ - event_counter = cis_lll->event_count; + event_counter = next_cis_lll->event_count; /* Calculate the radio channel to use for next CIS ISO event */ - data_chan_id = lll_chan_id(cis_lll->access_addr); + data_chan_id = lll_chan_id(next_cis_lll->access_addr); next_chan_use = lll_chan_iso_event(event_counter, data_chan_id, conn_lll->data_chan_map, conn_lll->data_chan_count, &data_chan_prn_s, &data_chan_remap_idx); - /* Reset indices for the next CIS */ - se_curr = 0U; /* isr_tx() will increase se_curr */ - cis_lll->tx.bn_curr = 1U; /* FIXME: may be this should be previous event value? */ - cis_lll->rx.bn_curr = 1U; + /* Next CIS, se_curr is incremented in isr_tx() */ + cis_lll = next_cis_lll; + cis_lll->se_curr--; has_tx = 0U; } /* Schedule next subevent reception */ subevent_us = radio_tmr_aa_restore(); - subevent_us += cis_lll->offset - cis_offset_first + - (cis_lll->sub_interval * se_curr); + if (has_tx) { + subevent_us += cis_lll->offset - cis_offset_first + + (cis_lll->sub_interval * cis_lll->se_curr); + } else { + subevent_us += cis_lll->offset - cis_offset_first; + } subevent_us -= addr_us_get(cis_lll->rx.phy); #if defined(CONFIG_BT_CTLR_PHY) @@ -886,8 +854,9 @@ static void isr_tx(void *param) uint64_t payload_count; uint8_t pkt_flags; - payload_count = (cis_lll->event_count * cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + payload_count = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; + cis_lll->rx.ccm.counter = payload_count; pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_DC, @@ -931,8 +900,12 @@ static void isr_tx(void *param) cig_lll = ull_conn_iso_lll_group_get_by_stream(cis_lll); subevent_us = radio_tmr_aa_restore(); - subevent_us += cis_lll->offset - cis_offset_first + - (cis_lll->sub_interval * se_curr); + if (has_tx) { + subevent_us += cis_lll->offset - cis_offset_first + + (cis_lll->sub_interval * cis_lll->se_curr); + } else { + subevent_us += cis_lll->offset - cis_offset_first; + } subevent_us -= addr_us_get(cis_lll->rx.phy); #if defined(CONFIG_BT_CTLR_PHY) @@ -982,26 +955,26 @@ static void isr_tx(void *param) radio_isr_set(isr_rx, cis_lll); - se_curr++; + cis_lll->se_curr++; } static void next_cis_prepare(void *param) { - struct lll_conn_iso_stream *cis_lll; + struct lll_conn_iso_stream *next_cis_lll; struct lll_conn_iso_group *cig_lll; uint16_t cis_handle; /* Get reference to CIS LLL context */ - cis_lll = param; + next_cis_lll = param; /* Check for next active CIS */ - cig_lll = ull_conn_iso_lll_group_get_by_stream(cis_lll); + cig_lll = ull_conn_iso_lll_group_get_by_stream(next_cis_lll); cis_handle = cis_handle_curr; do { - cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); - } while (cis_lll && !cis_lll->active); + next_cis_lll = ull_conn_iso_lll_stream_get_by_group(cig_lll, &cis_handle); + } while (next_cis_lll && !next_cis_lll->active); - if (!cis_lll) { + if (!next_cis_lll) { /* ISO Event Done */ radio_isr_set(isr_done, param); @@ -1010,7 +983,7 @@ static void next_cis_prepare(void *param) cis_handle_curr = cis_handle; - radio_isr_set(isr_prepare_subevent_next_cis, cis_lll); + radio_isr_set(isr_prepare_subevent_next_cis, next_cis_lll); } static void isr_prepare_subevent(void *param) @@ -1062,10 +1035,8 @@ static void isr_prepare_subevent_next_cis(void *param) &data_chan_prn_s, &data_chan_remap_idx); - /* Reset indices for the next CIS */ - se_curr = 0U; /* isr_prepare_subevent_common() will increase se_curr */ - cis_lll->tx.bn_curr = 1U; /* FIXME: may be this should be previous event value? */ - cis_lll->rx.bn_curr = 1U; + /* se_curr is incremented in isr_prepare_subevent_common() */ + cis_lll->se_curr--; has_tx = 0U; isr_prepare_subevent_common(param); @@ -1099,8 +1070,9 @@ static void isr_prepare_subevent_common(void *param) uint64_t payload_count; uint8_t pkt_flags; - payload_count = (cis_lll->event_count * cis_lll->rx.bn) + - (cis_lll->rx.bn_curr - 1U); + payload_count = cis_lll->rx.payload_count + + cis_lll->rx.bn_curr - 1U; + cis_lll->rx.ccm.counter = payload_count; pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_DC, @@ -1144,8 +1116,12 @@ static void isr_prepare_subevent_common(void *param) /* Anchor point sync-ed */ if (trx_performed_bitmask) { subevent_us = radio_tmr_aa_restore(); - subevent_us += cis_lll->offset - cis_offset_first + - (cis_lll->sub_interval * se_curr); + if (has_tx) { + subevent_us += cis_lll->offset - cis_offset_first + + (cis_lll->sub_interval * cis_lll->se_curr); + } else { + subevent_us += cis_lll->offset - cis_offset_first; + } subevent_us -= addr_us_get(cis_lll->rx.phy); #if defined(CONFIG_BT_CTLR_PHY) @@ -1159,8 +1135,12 @@ static void isr_prepare_subevent_common(void *param) #endif /* !CONFIG_BT_CTLR_PHY */ } else { subevent_us = radio_tmr_ready_restore(); - subevent_us += cis_lll->offset - cis_offset_first + - (cis_lll->sub_interval * se_curr); + if (has_tx) { + subevent_us += cis_lll->offset - cis_offset_first + + (cis_lll->sub_interval * cis_lll->se_curr); + } else { + subevent_us += cis_lll->offset - cis_offset_first; + } } start_us = radio_tmr_start_us(0U, subevent_us); @@ -1209,7 +1189,7 @@ static void isr_prepare_subevent_common(void *param) radio_isr_set(isr_rx, cis_lll); - se_curr++; + cis_lll->se_curr++; } static void isr_done(void *param) @@ -1222,11 +1202,7 @@ static void isr_done(void *param) /* Get reference to CIS LLL context */ cis_lll = param; - /* Adjust nesn when flushing Rx */ - /* FIXME: When Flush Timeout is implemented */ - if (cis_lll->rx.bn_curr <= cis_lll->rx.bn) { - lll_flush_rx(cis_lll); - } + payload_count_rx_flush_or_txrx_inc(cis_lll); e = ull_event_done_extra_get(); LL_ASSERT(e); @@ -1262,3 +1238,166 @@ static void isr_done(void *param) lll_isr_cleanup(param); } + +static void payload_count_txrx_flush_or_tx_inc(struct lll_conn_iso_stream *cis_lll) +{ + if (cis_lll->tx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + if ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr + + cis_lll->tx.ft + u) < + (cis_lll->event_count + cis_lll->se_curr + 2U)) || + ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr) > + cis_lll->event_count) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < cis_lll->event_count))) { + uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn += sn_update; + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + } + + if (!has_tx) { + has_tx = 1U; + cis_lll->se_curr = 1U; + } + + if (cis_lll->rx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + if (((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr + + cis_lll->rx.ft + u) < + (cis_lll->event_count + cis_lll->se_curr + 2U)) { + uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn += nesn_update; + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + } +} + +static void payload_count_rx_flush_or_txrx_inc(struct lll_conn_iso_stream *cis_lll) +{ + if (cis_lll->tx.bn && + (((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr) > + (cis_lll->event_count + cis_lll->tx.bn))) { + uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn += sn_update; + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + cis_lll->npi = 0U; + } + + if (cis_lll->rx.bn) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + if ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr + + cis_lll->rx.ft + u) <= + (cis_lll->event_count + cis_lll->nse + 2U)) || + (((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr) > + (cis_lll->event_count + cis_lll->rx.bn))) { + uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn += nesn_update; + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + } +} + +static void payload_count_lazy(struct lll_conn_iso_stream *cis_lll, uint16_t lazy) +{ + if (cis_lll->tx.bn && lazy) { + uint64_t payload_count; + uint16_t tx_lazy; + uint8_t u; + + tx_lazy = lazy - 1U; + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + if ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr + + cis_lll->tx.ft + u) < + (cis_lll->event_count + cis_lll->se_curr + 2U)) || + ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr) > + cis_lll->event_count) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < cis_lll->event_count))) { + uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn += sn_update; + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + + cis_lll->se_curr = cis_lll->nse; + + while (tx_lazy--) { + payload_count = cis_lll->tx.payload_count + cis_lll->tx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->tx.bn) * + (cis_lll->tx.bn - 1U - + (payload_count % cis_lll->tx.bn))); + if ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr + + cis_lll->tx.ft + u) < + (cis_lll->event_count + cis_lll->se_curr + 2U)) || + ((((cis_lll->tx.payload_count / cis_lll->tx.bn) + cis_lll->tx.bn_curr) > + cis_lll->event_count) && + ((cis_lll->tx.payload_count / cis_lll->tx.bn) < + cis_lll->event_count))) { + uint8_t sn_update = cis_lll->tx.bn + 1U - cis_lll->tx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->sn += sn_update; + cis_lll->tx.payload_count += cis_lll->tx.bn; + cis_lll->tx.bn_curr = 1U; + } + } + } + + if (cis_lll->rx.bn) { + while (lazy--) { + uint64_t payload_count; + uint8_t u; + + payload_count = cis_lll->rx.payload_count + cis_lll->rx.bn_curr - 1U; + u = cis_lll->nse - ((cis_lll->nse / cis_lll->rx.bn) * + (cis_lll->rx.bn - 1U - + (payload_count % cis_lll->rx.bn))); + if ((((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr + + cis_lll->rx.ft + u) < + (cis_lll->event_count + cis_lll->nse + 2U)) || + (((cis_lll->rx.payload_count / cis_lll->rx.bn) + cis_lll->rx.bn_curr) > + (cis_lll->event_count + cis_lll->rx.bn))) { + uint8_t nesn_update = cis_lll->rx.bn + 1U - cis_lll->rx.bn_curr; + + /* sn and nesn are 1-bit, only Least Significant bit is needed */ + cis_lll->nesn += nesn_update; + cis_lll->rx.payload_count += cis_lll->rx.bn; + cis_lll->rx.bn_curr = 1U; + } + } + } +} diff --git a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c index 1c2ea8726ad8241..eb845201a9cf115 100644 --- a/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c +++ b/subsys/bluetooth/controller/ll_sw/ull_peripheral_iso.c @@ -324,6 +324,7 @@ uint8_t ull_peripheral_iso_setup(struct pdu_data_llctrl_cis_ind *ind, cis->lll.nesn = 0U; cis->lll.cie = 0U; cis->lll.npi = 0U; + cis->lll.se_curr = 1U; cis->lll.flushed = 0U; cis->lll.active = 0U; cis->lll.datapath_ready_rx = 0U;