1 /*
2 * Copyright (c) 2021 Nordic Semiconductor ASA
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <stdint.h>
8 #include <string.h>
9
10 #include <soc.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <zephyr/sys/util.h>
13
14 #include "hal/cpu.h"
15 #include "hal/ccm.h"
16 #include "hal/radio.h"
17 #include "hal/ticker.h"
18
19 #include "util/util.h"
20 #include "util/mem.h"
21 #include "util/memq.h"
22
23 #include "pdu_df.h"
24 #include "pdu_vendor.h"
25 #include "pdu.h"
26
27 #include "lll.h"
28 #include "lll_clock.h"
29 #include "lll_chan.h"
30 #include "lll_vendor.h"
31 #include "lll_adv_types.h"
32 #include "lll_adv.h"
33 #include "lll_adv_pdu.h"
34 #include "lll_adv_iso.h"
35 #include "lll_iso_tx.h"
36
37 #include "lll_internal.h"
38 #include "lll_adv_iso_internal.h"
39 #include "lll_prof_internal.h"
40
41 #include "ll_feat.h"
42
43 #include "hal/debug.h"
44
45 #define TEST_WITH_DUMMY_PDU 0
46
47 static int init_reset(void);
48 static void prepare(void *param);
49 static void create_prepare_bh(void *param);
50 static void prepare_bh(void *param);
51 static int create_prepare_cb(struct lll_prepare_param *p);
52 static int prepare_cb(struct lll_prepare_param *p);
53 static int prepare_cb_common(struct lll_prepare_param *p);
54 static void isr_tx_create(void *param);
55 static void isr_tx_normal(void *param);
56 static void isr_tx_common(void *param,
57 radio_isr_cb_t isr_tx,
58 radio_isr_cb_t isr_done);
59 static void next_chan_calc(struct lll_adv_iso *lll, uint16_t event_counter,
60 uint16_t data_chan_id);
61 static void isr_done_create(void *param);
62 static void isr_done_term(void *param);
63
lll_adv_iso_init(void)64 int lll_adv_iso_init(void)
65 {
66 int err;
67
68 err = init_reset();
69 if (err) {
70 return err;
71 }
72
73 return 0;
74 }
75
lll_adv_iso_reset(void)76 int lll_adv_iso_reset(void)
77 {
78 int err;
79
80 err = init_reset();
81 if (err) {
82 return err;
83 }
84
85 return 0;
86 }
87
lll_adv_iso_create_prepare(void * param)88 void lll_adv_iso_create_prepare(void *param)
89 {
90 prepare(param);
91 create_prepare_bh(param);
92 }
93
lll_adv_iso_prepare(void * param)94 void lll_adv_iso_prepare(void *param)
95 {
96 prepare(param);
97 prepare_bh(param);
98 }
99
init_reset(void)100 static int init_reset(void)
101 {
102 return 0;
103 }
104
prepare(void * param)105 static void prepare(void *param)
106 {
107 struct lll_prepare_param *p;
108 struct lll_adv_iso *lll;
109 uint16_t elapsed;
110 int err;
111
112 err = lll_hfclock_on();
113 LL_ASSERT(err >= 0);
114
115 p = param;
116
117 /* Instants elapsed */
118 elapsed = p->lazy + 1U;
119
120 lll = p->param;
121
122 /* Save the (latency + 1) for use in event */
123 lll->latency_prepare += elapsed;
124 }
125
create_prepare_bh(void * param)126 static void create_prepare_bh(void *param)
127 {
128 int err;
129
130 /* Invoke common pipeline handling of prepare */
131 err = lll_prepare(lll_is_abort_cb, lll_abort_cb, create_prepare_cb, 0U,
132 param);
133 LL_ASSERT(!err || err == -EINPROGRESS);
134 }
135
prepare_bh(void * param)136 static void prepare_bh(void *param)
137 {
138 int err;
139
140 /* Invoke common pipeline handling of prepare */
141 err = lll_prepare(lll_is_abort_cb, lll_abort_cb, prepare_cb, 0U, param);
142 LL_ASSERT(!err || err == -EINPROGRESS);
143 }
144
create_prepare_cb(struct lll_prepare_param * p)145 static int create_prepare_cb(struct lll_prepare_param *p)
146 {
147 int err;
148
149 err = prepare_cb_common(p);
150 if (err) {
151 DEBUG_RADIO_START_A(1);
152 return 0;
153 }
154
155 radio_isr_set(isr_tx_create, p->param);
156
157 DEBUG_RADIO_START_A(1);
158 return 0;
159 }
160
prepare_cb(struct lll_prepare_param * p)161 static int prepare_cb(struct lll_prepare_param *p)
162 {
163 int err;
164
165 err = prepare_cb_common(p);
166 if (err) {
167 DEBUG_RADIO_START_A(1);
168 return 0;
169 }
170
171 radio_isr_set(isr_tx_normal, p->param);
172
173 DEBUG_RADIO_START_A(1);
174 return 0;
175 }
176
prepare_cb_common(struct lll_prepare_param * p)177 static int prepare_cb_common(struct lll_prepare_param *p)
178 {
179 struct lll_adv_iso *lll;
180 uint32_t ticks_at_event;
181 uint32_t ticks_at_start;
182 uint16_t event_counter;
183 uint8_t access_addr[4];
184 uint64_t payload_count;
185 uint16_t data_chan_id;
186 uint8_t data_chan_use;
187 uint8_t crc_init[3];
188 struct pdu_bis *pdu;
189 struct ull_hdr *ull;
190 uint32_t remainder;
191 uint32_t start_us;
192 uint8_t pkt_flags;
193 uint32_t ret;
194 uint8_t phy;
195
196 DEBUG_RADIO_START_A(1);
197
198 lll = p->param;
199
200 /* Deduce the latency */
201 lll->latency_event = lll->latency_prepare - 1U;
202
203 /* Calculate the current event counter value */
204 event_counter = (lll->payload_count / lll->bn) + lll->latency_event;
205
206 /* Update BIS payload counter to next value */
207 lll->payload_count += (lll->latency_prepare * lll->bn);
208 payload_count = lll->payload_count - lll->bn;
209
210 /* Reset accumulated latencies */
211 lll->latency_prepare = 0U;
212
213 /* Initialize to mandatory parameter values */
214 lll->bis_curr = 1U;
215 lll->ptc_curr = 0U;
216 lll->irc_curr = 1U;
217 lll->bn_curr = 1U;
218
219 /* Calculate the Access Address for the BIS event */
220 util_bis_aa_le32(lll->bis_curr, lll->seed_access_addr, access_addr);
221 data_chan_id = lll_chan_id(access_addr);
222
223 /* Calculate the CRC init value for the BIS event,
224 * preset with the BaseCRCInit value from the BIGInfo data the most
225 * significant 2 octets and the BIS_Number for the specific BIS in the
226 * least significant octet.
227 */
228 crc_init[0] = lll->bis_curr;
229 (void)memcpy(&crc_init[1], lll->base_crc_init, sizeof(uint16_t));
230
231 /* Calculate the radio channel to use for ISO event */
232 data_chan_use = lll_chan_iso_event(event_counter, data_chan_id,
233 lll->data_chan_map,
234 lll->data_chan_count,
235 &lll->data_chan_prn_s,
236 &lll->data_chan_remap_idx);
237
238 /* Start setting up of Radio h/w */
239 radio_reset();
240
241 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
242 radio_tx_power_set(lll->adv->tx_pwr_lvl);
243 #else
244 radio_tx_power_set(RADIO_TXP_DEFAULT);
245 #endif
246
247 phy = lll->phy;
248 radio_phy_set(phy, lll->phy_flags);
249 radio_aa_set(access_addr);
250 radio_crc_configure(PDU_CRC_POLYNOMIAL, sys_get_le24(crc_init));
251 lll_chan_set(data_chan_use);
252
253 /* Get ISO data PDU */
254 #if !TEST_WITH_DUMMY_PDU
255 struct lll_adv_iso_stream *stream;
256 memq_link_t *link = NULL;
257 struct node_tx_iso *tx;
258 uint16_t stream_handle;
259 uint16_t handle;
260 uint8_t bis_idx;
261
262 bis_idx = lll->num_bis;
263 while (bis_idx--) {
264 stream_handle = lll->stream_handle[bis_idx];
265 handle = LL_BIS_ADV_HANDLE_FROM_IDX(stream_handle);
266 stream = ull_adv_iso_lll_stream_get(stream_handle);
267 LL_ASSERT(stream);
268
269 do {
270 link = memq_peek(stream->memq_tx.head,
271 stream->memq_tx.tail, (void **)&tx);
272 if (link) {
273 if (tx->payload_count < payload_count) {
274 memq_dequeue(stream->memq_tx.tail,
275 &stream->memq_tx.head,
276 NULL);
277
278 tx->next = link;
279 ull_iso_lll_ack_enqueue(handle, tx);
280 } else if (tx->payload_count >=
281 lll->payload_count) {
282 link = NULL;
283 } else {
284 if (tx->payload_count !=
285 payload_count) {
286 link = NULL;
287 }
288
289 break;
290 }
291 }
292 } while (link);
293 }
294
295 if (!link) {
296 pdu = radio_pkt_empty_get();
297 pdu->ll_id = lll->framing ? PDU_BIS_LLID_FRAMED : PDU_BIS_LLID_START_CONTINUE;
298 pdu->len = 0U;
299 } else {
300 pdu = (void *)tx->pdu;
301 }
302
303 #else /* TEST_WITH_DUMMY_PDU */
304 pdu = radio_pkt_scratch_get();
305 if (lll->bn_curr >= lll->bn) {
306 pdu->ll_id = PDU_BIS_LLID_COMPLETE_END;
307 } else {
308 pdu->ll_id = PDU_BIS_LLID_START_CONTINUE;
309 }
310 pdu->len = LL_BIS_OCTETS_TX_MAX;
311
312 pdu->payload[0] = lll->bn_curr;
313 pdu->payload[1] = lll->irc_curr;
314 pdu->payload[2] = lll->ptc_curr;
315 pdu->payload[3] = lll->bis_curr;
316
317 pdu->payload[4] = payload_count;
318 pdu->payload[5] = payload_count >> 8;
319 pdu->payload[6] = payload_count >> 16;
320 pdu->payload[7] = payload_count >> 24;
321 pdu->payload[8] = payload_count >> 32;
322 #endif /* TEST_WITH_DUMMY_PDU */
323
324 /* Initialize reserve bit */
325 pdu->rfu = 0U;
326
327 /* Handle control procedure */
328 if (unlikely(lll->term_req || !!(lll->chm_req - lll->chm_ack))) {
329 if (lll->term_req) {
330 if (!lll->term_ack) {
331 lll->term_ack = 1U;
332 lll->ctrl_expire = CONN_ESTAB_COUNTDOWN;
333 lll->ctrl_instant = event_counter +
334 lll->ctrl_expire - 1U;
335 lll->cssn++;
336 }
337 } else if (((lll->chm_req - lll->chm_ack) & CHM_STATE_MASK) ==
338 CHM_STATE_REQ) {
339 lll->chm_ack--;
340 lll->ctrl_expire = CONN_ESTAB_COUNTDOWN;
341 lll->ctrl_instant = event_counter + lll->ctrl_expire;
342 lll->cssn++;
343 }
344
345 pdu->cstf = 1U;
346 } else {
347 pdu->cstf = 0U;
348 }
349 pdu->cssn = lll->cssn;
350
351 /* Radio packet configuration */
352 pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_BIS, phy,
353 RADIO_PKT_CONF_CTE_DISABLED);
354 if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) &&
355 pdu->len && lll->enc) {
356 /* Encryption */
357 lll->ccm_tx.counter = payload_count;
358
359 (void)memcpy(lll->ccm_tx.iv, lll->giv, 4U);
360 mem_xor_32(lll->ccm_tx.iv, lll->ccm_tx.iv, access_addr);
361
362 radio_pkt_configure(RADIO_PKT_CONF_LENGTH_8BIT,
363 (lll->max_pdu + PDU_MIC_SIZE), pkt_flags);
364
365 radio_pkt_tx_set(radio_ccm_iso_tx_pkt_set(&lll->ccm_tx,
366 RADIO_PKT_CONF_PDU_TYPE_BIS,
367 pdu));
368 } else {
369 if (lll->enc) {
370 radio_pkt_configure(RADIO_PKT_CONF_LENGTH_8BIT,
371 (lll->max_pdu + PDU_MIC_SIZE),
372 pkt_flags);
373 } else {
374 radio_pkt_configure(RADIO_PKT_CONF_LENGTH_8BIT,
375 lll->max_pdu, pkt_flags);
376 }
377
378 radio_pkt_tx_set(pdu);
379 }
380
381 /* Setup radio IFS switching */
382 if ((lll->bn_curr == lll->bn) &&
383 (lll->irc_curr == lll->irc) &&
384 (lll->ptc_curr == lll->ptc) &&
385 (lll->bis_curr == lll->num_bis) &&
386 !pdu->cstf) {
387 radio_switch_complete_and_disable();
388 } else {
389 uint16_t iss_us;
390
391 /* Calculate next subevent start based on previous PDU length */
392 iss_us = lll->sub_interval -
393 PDU_BIS_US(pdu->len, ((pdu->len) ? lll->enc : 0U),
394 lll->phy, lll->phy_flags);
395
396 radio_tmr_tifs_set(iss_us);
397 radio_switch_complete_and_b2b_tx(lll->phy, lll->phy_flags,
398 lll->phy, lll->phy_flags);
399 }
400
401 ticks_at_event = p->ticks_at_expire;
402 ull = HDR_LLL2ULL(lll);
403 ticks_at_event += lll_event_offset_get(ull);
404
405 ticks_at_start = ticks_at_event;
406 ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
407
408 remainder = p->remainder;
409 start_us = radio_tmr_start(1U, ticks_at_start, remainder);
410
411 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR) || IS_ENABLED(HAL_RADIO_GPIO_HAVE_PA_PIN)) {
412 /* setup capture of PDU end timestamp */
413 radio_tmr_end_capture();
414 }
415
416 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
417 radio_gpio_pa_setup();
418
419 radio_gpio_pa_lna_enable(start_us +
420 radio_tx_ready_delay_get(lll->phy,
421 lll->phy_flags) -
422 HAL_RADIO_GPIO_PA_OFFSET);
423 #else /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
424 ARG_UNUSED(start_us);
425 #endif /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
426
427 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
428 (EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
429 uint32_t overhead;
430
431 overhead = lll_preempt_calc(ull, (TICKER_ID_ADV_ISO_BASE + lll->handle), ticks_at_event);
432 /* check if preempt to start has changed */
433 if (overhead) {
434 LL_ASSERT_OVERHEAD(overhead);
435
436 radio_isr_set(lll_isr_abort, lll);
437 radio_disable();
438
439 return -ECANCELED;
440 }
441 #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
442
443 ret = lll_prepare_done(lll);
444 LL_ASSERT(!ret);
445
446 /* Calculate ahead the next subevent channel index */
447 next_chan_calc(lll, event_counter, data_chan_id);
448
449 return 0;
450 }
451
isr_tx_create(void * param)452 static void isr_tx_create(void *param)
453 {
454 isr_tx_common(param, isr_tx_create, isr_done_create);
455 }
456
isr_tx_normal(void * param)457 static void isr_tx_normal(void *param)
458 {
459 isr_tx_common(param, isr_tx_normal, lll_isr_done);
460 }
461
isr_tx_common(void * param,radio_isr_cb_t isr_tx,radio_isr_cb_t isr_done)462 static void isr_tx_common(void *param,
463 radio_isr_cb_t isr_tx,
464 radio_isr_cb_t isr_done)
465 {
466 struct pdu_bis *pdu = NULL;
467 uint8_t data_chan_use = 0;
468 struct lll_adv_iso *lll;
469 uint8_t access_addr[4];
470 uint64_t payload_count;
471 uint16_t data_chan_id;
472 uint8_t crc_init[3];
473 uint8_t bis;
474
475 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
476 uint16_t pa_iss_us = 0U;
477 #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
478
479 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
480 lll_prof_latency_capture();
481 }
482
483 lll = param;
484 /* FIXME: Sequential or Interleaved BIS subevents decision */
485 /* Sequential Tx complete flow pseudo code */
486 if (lll->bn_curr < lll->bn) {
487 /* transmit the (bn_curr)th Tx PDU of bis_curr */
488 lll->bn_curr++; /* post increment */
489
490 bis = lll->bis_curr;
491
492 } else if (lll->irc_curr < lll->irc) {
493 /* transmit the (bn_curr)th Tx PDU of bis_curr */
494 lll->bn_curr = 1U;
495 lll->irc_curr++; /* post increment */
496
497 bis = lll->bis_curr;
498
499 } else if (lll->ptc_curr < lll->ptc) {
500 lll->ptc_curr++; /* pre increment */
501 /* transmit the (ptc_curr * bn)th Tx PDU */
502
503 bis = lll->bis_curr;
504
505 } else if (lll->bis_curr < lll->num_bis) {
506 lll->bis_curr++;
507 lll->ptc_curr = 0U;
508 lll->irc_curr = 1U;
509 /* transmit the (bn_curr)th PDU of bis_curr */
510 lll->bn_curr = 1U;
511
512 bis = lll->bis_curr;
513
514 } else if (lll->term_ack) {
515 /* Transmit the control PDU and close the BIG event
516 * there after.
517 */
518 struct pdu_big_ctrl_term_ind *term;
519
520 pdu = radio_pkt_big_ctrl_get();
521 pdu->ll_id = PDU_BIS_LLID_CTRL;
522 pdu->cssn = lll->cssn;
523 pdu->cstf = 0U;
524
525 pdu->len = offsetof(struct pdu_big_ctrl, ctrl_data) +
526 sizeof(struct pdu_big_ctrl_term_ind);
527 pdu->ctrl.opcode = PDU_BIG_CTRL_TYPE_TERM_IND;
528
529 term = (void *)&pdu->ctrl.term_ind;
530 term->reason = lll->term_reason;
531 term->instant = lll->ctrl_instant;
532
533 /* control subevent to use bis = 0 and se_n = 1 */
534 bis = 0U;
535 payload_count = lll->payload_count - lll->bn;
536
537 } else if (((lll->chm_req - lll->chm_ack) & CHM_STATE_MASK) ==
538 CHM_STATE_SEND) {
539 /* Transmit the control PDU and stop after 6 intervals
540 */
541 struct pdu_big_ctrl_chan_map_ind *chm;
542
543 pdu = radio_pkt_big_ctrl_get();
544 pdu->ll_id = PDU_BIS_LLID_CTRL;
545 pdu->cssn = lll->cssn;
546 pdu->cstf = 0U;
547
548 pdu->len = offsetof(struct pdu_big_ctrl, ctrl_data) +
549 sizeof(struct pdu_big_ctrl_chan_map_ind);
550 pdu->ctrl.opcode = PDU_BIG_CTRL_TYPE_CHAN_MAP_IND;
551
552 chm = (void *)&pdu->ctrl.chan_map_ind;
553 (void)memcpy(chm->chm, lll->chm_chan_map, sizeof(chm->chm));
554 chm->instant = lll->ctrl_instant;
555
556 /* control subevent to use bis = 0 and se_n = 1 */
557 bis = 0U;
558 payload_count = lll->payload_count - lll->bn;
559
560 } else {
561 struct lll_adv_iso_stream *stream;
562 uint16_t stream_handle;
563 memq_link_t *link;
564 uint16_t handle;
565
566 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
567 lll_prof_cputime_capture();
568 }
569
570 for (uint8_t bis_idx = 0U; bis_idx < lll->num_bis; bis_idx++) {
571 stream_handle = lll->stream_handle[bis_idx];
572 handle = LL_BIS_ADV_HANDLE_FROM_IDX(stream_handle);
573 stream = ull_adv_iso_lll_stream_get(stream_handle);
574 LL_ASSERT(stream);
575
576 do {
577 struct node_tx_iso *tx;
578
579 link = memq_peek(stream->memq_tx.head,
580 stream->memq_tx.tail,
581 (void **)&tx);
582 if (link) {
583 if (tx->payload_count >=
584 lll->payload_count) {
585 break;
586 }
587
588 memq_dequeue(stream->memq_tx.tail,
589 &stream->memq_tx.head,
590 NULL);
591
592 tx->next = link;
593 ull_iso_lll_ack_enqueue(handle, tx);
594 }
595 } while (link);
596 }
597
598 /* Close the BIG event as no more subevents */
599 radio_isr_set(isr_done, lll);
600 radio_disable();
601
602 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
603 lll_prof_send();
604 }
605
606 return;
607 }
608
609 lll_isr_tx_status_reset();
610
611 /* Calculate the Access Address for the BIS event */
612 util_bis_aa_le32(bis, lll->seed_access_addr, access_addr);
613 data_chan_id = lll_chan_id(access_addr);
614
615 /* Calculate the CRC init value for the BIS event,
616 * preset with the BaseCRCInit value from the BIGInfo data the most
617 * significant 2 octets and the BIS_Number for the specific BIS in the
618 * least significant octet.
619 */
620 crc_init[0] = bis;
621 (void)memcpy(&crc_init[1], lll->base_crc_init, sizeof(uint16_t));
622
623 radio_aa_set(access_addr);
624 radio_crc_configure(PDU_CRC_POLYNOMIAL, sys_get_le24(crc_init));
625
626 /* Get ISO data PDU, not control subevent */
627 if (!pdu) {
628 uint8_t payload_index;
629
630 payload_index = (lll->bn_curr - 1U) +
631 (lll->ptc_curr * lll->pto);
632 payload_count = lll->payload_count + payload_index - lll->bn;
633
634 #if !TEST_WITH_DUMMY_PDU
635 struct lll_adv_iso_stream *stream;
636 uint16_t stream_handle;
637 struct node_tx_iso *tx;
638 memq_link_t *link;
639
640 stream_handle = lll->stream_handle[lll->bis_curr - 1U];
641 stream = ull_adv_iso_lll_stream_get(stream_handle);
642 LL_ASSERT(stream);
643
644 link = memq_peek_n(stream->memq_tx.head, stream->memq_tx.tail,
645 payload_index, (void **)&tx);
646 if (!link || (tx->payload_count != payload_count)) {
647 payload_index = 0U;
648 do {
649 link = memq_peek_n(stream->memq_tx.head,
650 stream->memq_tx.tail,
651 payload_index, (void **)&tx);
652 payload_index++;
653 } while (link &&
654 (tx->payload_count < payload_count));
655 }
656 if (!link || (tx->payload_count != payload_count)) {
657 pdu = radio_pkt_empty_get();
658 pdu->ll_id = lll->framing ? PDU_BIS_LLID_FRAMED :
659 PDU_BIS_LLID_START_CONTINUE;
660 pdu->len = 0U;
661 } else {
662 pdu = (void *)tx->pdu;
663 }
664 pdu->cssn = lll->cssn;
665 pdu->cstf = (lll->term_req || !!(lll->chm_req - lll->chm_ack));
666
667 #else /* TEST_WITH_DUMMY_PDU */
668 pdu = radio_pkt_scratch_get();
669 if (lll->bn_curr >= lll->bn && !(lll->ptc_curr % lll->bn)) {
670 pdu->ll_id = PDU_BIS_LLID_COMPLETE_END;
671 } else {
672 pdu->ll_id = PDU_BIS_LLID_START_CONTINUE;
673 }
674 pdu->len = LL_BIS_OCTETS_TX_MAX;
675 pdu->cssn = lll->cssn;
676 pdu->cstf = 0U;
677
678 pdu->payload[0] = lll->bn_curr;
679 pdu->payload[1] = lll->irc_curr;
680 pdu->payload[2] = lll->ptc_curr;
681 pdu->payload[3] = lll->bis_curr;
682
683 pdu->payload[4] = payload_count;
684 pdu->payload[5] = payload_count >> 8;
685 pdu->payload[6] = payload_count >> 16;
686 pdu->payload[7] = payload_count >> 24;
687 pdu->payload[8] = payload_count >> 32;
688 #endif /* TEST_WITH_DUMMY_PDU */
689
690 data_chan_use = lll->next_chan_use;
691 }
692 pdu->rfu = 0U;
693
694 if (!bis) {
695 const uint16_t event_counter = payload_count / lll->bn;
696
697 /* Calculate the radio channel to use for ISO event */
698 data_chan_use = lll_chan_iso_event(event_counter, data_chan_id,
699 lll->data_chan_map,
700 lll->data_chan_count,
701 &lll->data_chan_prn_s,
702 &lll->data_chan_remap_idx);
703 }
704
705 lll_chan_set(data_chan_use);
706
707 /* Encryption */
708 if (IS_ENABLED(CONFIG_BT_CTLR_BROADCAST_ISO_ENC) &&
709 pdu->len && lll->enc) {
710 lll->ccm_tx.counter = payload_count;
711
712 (void)memcpy(lll->ccm_tx.iv, lll->giv, 4U);
713 mem_xor_32(lll->ccm_tx.iv, lll->ccm_tx.iv, access_addr);
714
715 radio_pkt_tx_set(radio_ccm_iso_tx_pkt_set(&lll->ccm_tx,
716 RADIO_PKT_CONF_PDU_TYPE_BIS,
717 pdu));
718 } else {
719 radio_pkt_tx_set(pdu);
720 }
721
722 /* Control subevent, then complete subevent and close radio use */
723 if (!bis) {
724 uint8_t pkt_flags;
725
726 pkt_flags = RADIO_PKT_CONF_FLAGS(RADIO_PKT_CONF_PDU_TYPE_BIS,
727 lll->phy,
728 RADIO_PKT_CONF_CTE_DISABLED);
729 if (lll->enc) {
730 radio_pkt_configure(RADIO_PKT_CONF_LENGTH_8BIT,
731 (sizeof(struct pdu_big_ctrl) + PDU_MIC_SIZE),
732 pkt_flags);
733 } else {
734 radio_pkt_configure(RADIO_PKT_CONF_LENGTH_8BIT,
735 sizeof(struct pdu_big_ctrl),
736 pkt_flags);
737 }
738
739 radio_switch_complete_and_b2b_tx_disable();
740
741 radio_isr_set(isr_done_term, lll);
742 } else {
743 uint16_t iss_us;
744
745 /* Calculate next subevent start based on previous PDU length */
746 iss_us = lll->sub_interval -
747 PDU_BIS_US(pdu->len, ((pdu->len) ? lll->enc : 0U),
748 lll->phy, lll->phy_flags);
749
750 radio_tmr_tifs_set(iss_us);
751 radio_switch_complete_and_b2b_tx(lll->phy, lll->phy_flags,
752 lll->phy, lll->phy_flags);
753
754 radio_isr_set(isr_tx, lll);
755
756 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
757 /* local variable used later to store iss_us next subevent PA
758 * setup.
759 */
760 pa_iss_us = iss_us;
761 #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
762 }
763
764 /* assert if radio packet ptr is not set and radio started tx */
765 LL_ASSERT(!radio_is_ready());
766
767 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
768 lll_prof_cputime_capture();
769 }
770
771 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR) || IS_ENABLED(HAL_RADIO_GPIO_HAVE_PA_PIN)) {
772 /* setup capture of PDU end timestamp */
773 radio_tmr_end_capture();
774 }
775
776 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
777 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
778 /* PA/LNA enable is overwriting packet end used in ISR
779 * profiling, hence back it up for later use.
780 */
781 lll_prof_radio_end_backup();
782 }
783
784 radio_gpio_pa_setup();
785 radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
786 lll->pa_iss_us -
787 (EVENT_CLOCK_JITTER_US << 1U) -
788 radio_tx_chain_delay_get(lll->phy,
789 lll->phy_flags) -
790 HAL_RADIO_GPIO_PA_OFFSET);
791
792 /* Remember to use it for the next subevent PA setup */
793 lll->pa_iss_us = pa_iss_us;
794
795 #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
796
797 /* Calculate ahead the next subevent channel index */
798 const uint16_t event_counter = (lll->payload_count / lll->bn) - 1U;
799
800 next_chan_calc(lll, event_counter, data_chan_id);
801
802 if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
803 lll_prof_send();
804 }
805 }
806
next_chan_calc(struct lll_adv_iso * lll,uint16_t event_counter,uint16_t data_chan_id)807 static void next_chan_calc(struct lll_adv_iso *lll, uint16_t event_counter,
808 uint16_t data_chan_id)
809 {
810 /* Calculate ahead the next subevent channel index */
811 if ((lll->bn_curr < lll->bn) ||
812 (lll->irc_curr < lll->irc) ||
813 (lll->ptc_curr < lll->ptc)) {
814 /* Calculate the radio channel to use for next subevent */
815 lll->next_chan_use = lll_chan_iso_subevent(data_chan_id,
816 lll->data_chan_map,
817 lll->data_chan_count,
818 &lll->data_chan_prn_s,
819 &lll->data_chan_remap_idx);
820 } else if (lll->bis_curr < lll->num_bis) {
821 uint8_t access_addr[4];
822
823 /* Calculate the Access Address for the next BIS subevent */
824 util_bis_aa_le32((lll->bis_curr + 1U), lll->seed_access_addr,
825 access_addr);
826 data_chan_id = lll_chan_id(access_addr);
827
828 /* Calculate the radio channel to use for next BIS */
829 lll->next_chan_use = lll_chan_iso_event(event_counter,
830 data_chan_id,
831 lll->data_chan_map,
832 lll->data_chan_count,
833 &lll->data_chan_prn_s,
834 &lll->data_chan_remap_idx);
835 }
836 }
837
isr_done_create(void * param)838 static void isr_done_create(void *param)
839 {
840 lll_isr_status_reset();
841
842 ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_ADV_ISO_COMPLETE);
843
844 lll_isr_cleanup(param);
845 }
846
isr_done_term(void * param)847 static void isr_done_term(void *param)
848 {
849 struct lll_adv_iso *lll;
850 uint16_t elapsed_event;
851
852 lll_isr_status_reset();
853
854 lll = param;
855 LL_ASSERT(lll->ctrl_expire);
856
857 elapsed_event = lll->latency_event + 1U;
858 if (lll->ctrl_expire > elapsed_event) {
859 lll->ctrl_expire -= elapsed_event;
860 } else {
861 lll->ctrl_expire = 0U;
862
863 if (lll->chm_req != lll->chm_ack) {
864 struct lll_adv_sync *sync_lll;
865 struct lll_adv *adv_lll;
866
867 /* Reset channel map procedure requested */
868 lll->chm_ack = lll->chm_req;
869
870 /* Request periodic advertising to update channel map
871 * in the BIGInfo when filling BIG Offset until Thread
872 * context gets to update it using new PDU buffer.
873 */
874 adv_lll = lll->adv;
875 sync_lll = adv_lll->sync;
876 if (sync_lll->iso_chm_done_req ==
877 sync_lll->iso_chm_done_ack) {
878 struct node_rx_pdu *rx;
879
880 /* Request ULL to update the channel map in the
881 * BIGInfo struct present in the current PDU of
882 * Periodic Advertising radio events. Channel
883 * Map is updated when filling the BIG offset.
884 */
885 sync_lll->iso_chm_done_req++;
886
887 /* Notify Thread context to update channel map
888 * in the BIGInfo struct present in the Periodic
889 * Advertising PDU.
890 */
891 rx = ull_pdu_rx_alloc();
892 LL_ASSERT(rx);
893
894 rx->hdr.type = NODE_RX_TYPE_BIG_CHM_COMPLETE;
895 rx->rx_ftr.param = lll;
896
897 ull_rx_put_sched(rx->hdr.link, rx);
898 }
899
900 /* Use new channel map */
901 lll->data_chan_count = lll->chm_chan_count;
902 (void)memcpy(lll->data_chan_map, lll->chm_chan_map,
903 sizeof(lll->data_chan_map));
904 } else {
905 ull_done_extra_type_set(EVENT_DONE_EXTRA_TYPE_ADV_ISO_TERMINATE);
906 }
907 }
908
909 lll_isr_cleanup(param);
910 }
911