1 /*
2  * Copyright (c) 2020 Nordic Semiconductor ASA
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdint.h>
8 
9 #include <soc.h>
10 
11 #include <zephyr/sys/byteorder.h>
12 
13 #include "hal/cpu.h"
14 #include "hal/ccm.h"
15 #include "hal/radio.h"
16 #include "hal/ticker.h"
17 #include "hal/radio_df.h"
18 
19 #include "util/util.h"
20 #include "util/mem.h"
21 #include "util/memq.h"
22 #include "util/dbuf.h"
23 
24 #include "pdu_df.h"
25 #include "pdu_vendor.h"
26 #include "pdu.h"
27 
28 #include "lll.h"
29 #include "lll_vendor.h"
30 #include "lll_clock.h"
31 #include "lll_chan.h"
32 #include "lll_adv_types.h"
33 #include "lll_adv.h"
34 #include "lll_adv_pdu.h"
35 #include "lll_adv_sync.h"
36 #include "lll_adv_iso.h"
37 #include "lll_df_types.h"
38 
39 #include "lll_internal.h"
40 #include "lll_adv_internal.h"
41 #include "lll_tim_internal.h"
42 #include "lll_prof_internal.h"
43 #include "lll_df_internal.h"
44 
45 #include "hal/debug.h"
46 
47 static int init_reset(void);
48 static int prepare_cb(struct lll_prepare_param *p);
49 static void abort_cb(struct lll_prepare_param *prepare_param, void *param);
50 static void isr_done(void *param);
51 
52 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
53 static void isr_tx(void *param);
54 static int aux_ptr_get(struct pdu_adv *pdu, struct pdu_adv_aux_ptr **aux_ptr);
55 static void chain_pdu_aux_ptr_chan_idx_set(struct lll_adv_sync *lll);
56 static void aux_ptr_chan_idx_set(struct lll_adv_sync *lll, struct pdu_adv *pdu);
57 static void switch_radio_complete_and_b2b_tx(const struct lll_adv_sync *lll, uint8_t phy_s);
58 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
59 
lll_adv_sync_init(void)60 int lll_adv_sync_init(void)
61 {
62 	int err;
63 
64 	err = init_reset();
65 	if (err) {
66 		return err;
67 	}
68 
69 	return 0;
70 }
71 
lll_adv_sync_reset(void)72 int lll_adv_sync_reset(void)
73 {
74 	int err;
75 
76 	err = init_reset();
77 	if (err) {
78 		return err;
79 	}
80 
81 	return 0;
82 }
83 
lll_adv_sync_prepare(void * param)84 void lll_adv_sync_prepare(void *param)
85 {
86 	int err;
87 
88 	err = lll_hfclock_on();
89 	LL_ASSERT(err >= 0);
90 
91 	/* Invoke common pipeline handling of prepare */
92 	err = lll_prepare(lll_is_abort_cb, abort_cb, prepare_cb, 0, param);
93 	LL_ASSERT(!err || err == -EINPROGRESS);
94 }
95 
init_reset(void)96 static int init_reset(void)
97 {
98 	return 0;
99 }
100 
is_instant_or_past(uint16_t event_counter,uint16_t instant)101 static bool is_instant_or_past(uint16_t event_counter, uint16_t instant)
102 {
103 	uint16_t instant_latency;
104 
105 	instant_latency = (event_counter - instant) &
106 			  EVENT_INSTANT_MAX;
107 
108 	return instant_latency <= EVENT_INSTANT_LATENCY_MAX;
109 }
110 
prepare_cb(struct lll_prepare_param * p)111 static int prepare_cb(struct lll_prepare_param *p)
112 {
113 	struct lll_adv_sync *lll;
114 	uint32_t ticks_at_event;
115 	uint32_t ticks_at_start;
116 	uint8_t data_chan_count;
117 	uint8_t *data_chan_map;
118 	uint16_t event_counter;
119 	uint8_t data_chan_use;
120 	struct pdu_adv *pdu;
121 	struct ull_hdr *ull;
122 	uint32_t cte_len_us;
123 	uint32_t remainder;
124 	uint32_t start_us;
125 	uint8_t phy_s;
126 	uint32_t ret;
127 	uint8_t upd;
128 
129 	DEBUG_RADIO_START_A(1);
130 
131 	lll = p->param;
132 
133 	/* Calculate the current event latency */
134 	lll->latency_event = lll->latency_prepare + p->lazy;
135 
136 	/* Calculate the current event counter value */
137 	event_counter = lll->event_counter + lll->latency_event;
138 
139 	/* Update event counter to next value */
140 	lll->event_counter = (event_counter + 1);
141 
142 	/* Reset accumulated latencies */
143 	lll->latency_prepare = 0;
144 
145 	/* Process channel map update, if any */
146 	if ((lll->chm_first != lll->chm_last) &&
147 	    is_instant_or_past(event_counter, lll->chm_instant)) {
148 		/* At or past the instant, use channelMapNew */
149 		lll->chm_first = lll->chm_last;
150 	}
151 
152 	/* Calculate the radio channel to use */
153 	data_chan_map = lll->chm[lll->chm_first].data_chan_map;
154 	data_chan_count = lll->chm[lll->chm_first].data_chan_count;
155 	data_chan_use = lll_chan_sel_2(event_counter, lll->data_chan_id,
156 				       data_chan_map, data_chan_count);
157 
158 	/* Start setting up of Radio h/w */
159 	radio_reset();
160 #if defined(CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL)
161 	radio_tx_power_set(lll->adv->tx_pwr_lvl);
162 #else
163 	radio_tx_power_set(RADIO_TXP_DEFAULT);
164 #endif
165 
166 	phy_s = lll->adv->phy_s;
167 
168 	/* TODO: if coded we use S8? */
169 	radio_phy_set(phy_s, lll->adv->phy_flags);
170 	radio_pkt_configure(RADIO_PKT_CONF_LENGTH_8BIT, PDU_AC_PAYLOAD_SIZE_MAX,
171 			    RADIO_PKT_CONF_PHY(phy_s));
172 	radio_aa_set(lll->access_addr);
173 	radio_crc_configure(PDU_CRC_POLYNOMIAL,
174 				sys_get_le24(lll->crc_init));
175 	lll_chan_set(data_chan_use);
176 
177 	upd = 0U;
178 	pdu = lll_adv_sync_data_latest_get(lll, NULL, &upd);
179 	LL_ASSERT(pdu);
180 
181 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
182 	lll_df_cte_tx_enable(lll, pdu, &cte_len_us);
183 #else
184 	cte_len_us = 0U;
185 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX) */
186 
187 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
188 	if (pdu->adv_ext_ind.ext_hdr_len && pdu->adv_ext_ind.ext_hdr.aux_ptr) {
189 		/* Set the last used auxiliary PDU for transmission */
190 		lll->last_pdu = pdu;
191 
192 		/* Populate chan idx for AUX_ADV_IND PDU */
193 		aux_ptr_chan_idx_set(lll, pdu);
194 
195 		radio_isr_set(isr_tx, lll);
196 		radio_tmr_tifs_set(EVENT_SYNC_B2B_MAFS_US);
197 		switch_radio_complete_and_b2b_tx(lll, phy_s);
198 	} else {
199 		/* No chain PDU */
200 		lll->last_pdu = NULL;
201 
202 #else /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
203 	{
204 #endif /* !CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
205 
206 		radio_isr_set(isr_done, lll);
207 		radio_switch_complete_and_disable();
208 	}
209 
210 #if defined(CONFIG_BT_CTLR_ADV_ISO) && defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
211 	if (lll->iso) {
212 		ull_adv_iso_lll_biginfo_fill(pdu, lll);
213 	}
214 #endif /* CONFIG_BT_CTLR_ADV_ISO && CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
215 
216 	/* Set the Radio Tx Packet */
217 	radio_pkt_tx_set(pdu);
218 
219 	ticks_at_event = p->ticks_at_expire;
220 	ull = HDR_LLL2ULL(lll);
221 	ticks_at_event += lll_event_offset_get(ull);
222 
223 	ticks_at_start = ticks_at_event;
224 	ticks_at_start += HAL_TICKER_US_TO_TICKS(EVENT_OVERHEAD_START_US);
225 
226 	remainder = p->remainder;
227 	start_us = radio_tmr_start(1, ticks_at_start, remainder);
228 
229 #if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
230 	defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
231 	/* capture end of AUX_SYNC_IND/AUX_CHAIN_IND PDU, used for calculating
232 	 * next PDU timestamp.
233 	 *
234 	 * In Periodic Advertising without chaining there is no need for LLL to
235 	 * get the end time from radio, hence there is no call to
236 	 * radio_tmr_end_capture() to capture the radio end time.
237 	 *
238 	 * With chaining the sw_switch used PPI/DPPI for back to back Tx, no
239 	 * radio end time capture is needed there either.
240 	 *
241 	 * For PA LNA (and ISR profiling), the radio end time is required to
242 	 * setup the GPIOTE using radio_gpio_pa_lna_enable which needs call to
243 	 * radio_tmr_tifs_base_get(), both PA/LNA and ISR profiling call
244 	 * radio_tmr_end_get().
245 	 */
246 	radio_tmr_end_capture();
247 #endif /* CONFIG_BT_CTLR_PROFILE_ISR */
248 
249 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
250 	radio_gpio_pa_setup();
251 
252 	radio_gpio_pa_lna_enable(start_us + radio_tx_ready_delay_get(phy_s, 1) -
253 				 HAL_RADIO_GPIO_PA_OFFSET);
254 #else /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
255 	ARG_UNUSED(start_us);
256 #endif /* !HAL_RADIO_GPIO_HAVE_PA_PIN */
257 
258 #if defined(CONFIG_BT_CTLR_XTAL_ADVANCED) && \
259 	(EVENT_OVERHEAD_PREEMPT_US <= EVENT_OVERHEAD_PREEMPT_MIN_US)
260 	uint32_t overhead;
261 
262 	overhead = lll_preempt_calc(ull, (TICKER_ID_ADV_SYNC_BASE +
263 					  ull_adv_sync_lll_handle_get(lll)), ticks_at_event);
264 	/* check if preempt to start has changed */
265 	if (overhead) {
266 		LL_ASSERT_OVERHEAD(overhead);
267 
268 		radio_isr_set(lll_isr_abort, lll);
269 		radio_disable();
270 
271 		return -ECANCELED;
272 	}
273 #endif /* CONFIG_BT_CTLR_XTAL_ADVANCED */
274 
275 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
276 	/* Populate chan idx for AUX_CHAIN_IND PDU */
277 	chain_pdu_aux_ptr_chan_idx_set(lll);
278 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
279 
280 	ret = lll_prepare_done(lll);
281 	LL_ASSERT(!ret);
282 
283 	DEBUG_RADIO_START_A(1);
284 
285 	return 0;
286 }
287 
288 static void abort_cb(struct lll_prepare_param *prepare_param, void *param)
289 {
290 	struct lll_adv_sync *lll;
291 	int err;
292 
293 	/* NOTE: This is not a prepare being cancelled */
294 	if (!prepare_param) {
295 		/* Perform event abort here.
296 		 * After event has been cleanly aborted, clean up resources
297 		 * and dispatch event done.
298 		 */
299 		radio_isr_set(isr_done, param);
300 		radio_disable();
301 		return;
302 	}
303 
304 	/* NOTE: Else clean the top half preparations of the aborted event
305 	 * currently in preparation pipeline.
306 	 */
307 	err = lll_hfclock_off();
308 	LL_ASSERT(err >= 0);
309 
310 	/* Accumulate the latency as event is aborted while being in pipeline */
311 	lll = prepare_param->param;
312 	lll->latency_prepare += (prepare_param->lazy + 1);
313 
314 	lll_done(param);
315 }
316 
317 static void isr_done(void *param)
318 {
319 	struct lll_adv_sync *lll = param;
320 
321 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
322 	if (lll->cte_started) {
323 		lll_df_cte_tx_disable();
324 	}
325 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
326 
327 	/* Signal thread mode to remove Channel Map Update Indication in the
328 	 * ACAD.
329 	 */
330 	if ((lll->chm_first != lll->chm_last) &&
331 	    is_instant_or_past(lll->event_counter, lll->chm_instant)) {
332 		struct node_rx_pdu *rx;
333 
334 		/* Allocate, prepare and dispatch Channel Map Update
335 		 * complete message towards ULL, then subsequently to
336 		 * the thread context.
337 		 */
338 		rx = ull_pdu_rx_alloc();
339 		LL_ASSERT(rx);
340 
341 		rx->hdr.type = NODE_RX_TYPE_SYNC_CHM_COMPLETE;
342 		rx->rx_ftr.param = lll;
343 
344 		ull_rx_put_sched(rx->hdr.link, rx);
345 	}
346 
347 	lll_isr_done(lll);
348 }
349 
350 #if defined(CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK)
351 static void isr_tx(void *param)
352 {
353 	struct pdu_adv_aux_ptr *aux_ptr;
354 	struct lll_adv_sync *lll_sync;
355 	struct pdu_adv *pdu;
356 	struct lll_adv *lll;
357 	uint32_t cte_len_us;
358 	int err;
359 
360 	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
361 		lll_prof_latency_capture();
362 	}
363 
364 	/* Clear radio tx status and events */
365 	lll_isr_tx_status_reset();
366 
367 	/* Get reference to sync and primary advertising LLL contexts */
368 	lll_sync = param;
369 	lll = lll_sync->adv;
370 
371 	/* Get reference to aux pointer structure */
372 	err = aux_ptr_get(lll_sync->last_pdu, &aux_ptr);
373 	LL_ASSERT(!err && aux_ptr);
374 
375 	/* Use channel idx that was in aux_ptr */
376 	lll_chan_set(aux_ptr->chan_idx);
377 
378 	/* Get reference to the auxiliary chain PDU */
379 	pdu = lll_adv_pdu_linked_next_get(lll_sync->last_pdu);
380 	LL_ASSERT(pdu);
381 
382 	/* Set the last used auxiliary PDU for transmission */
383 	lll_sync->last_pdu = pdu;
384 
385 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
386 	lll_df_cte_tx_enable(lll_sync, pdu, &cte_len_us);
387 #else
388 	cte_len_us = 0;
389 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
390 
391 	/* setup tIFS switching */
392 	if (pdu->adv_ext_ind.ext_hdr_len && pdu->adv_ext_ind.ext_hdr.aux_ptr) {
393 		radio_tmr_tifs_set(EVENT_SYNC_B2B_MAFS_US);
394 		radio_isr_set(isr_tx, lll_sync);
395 		switch_radio_complete_and_b2b_tx(lll_sync, lll->phy_s);
396 	} else {
397 		radio_isr_set(isr_done, lll_sync);
398 		radio_switch_complete_and_b2b_tx_disable();
399 	}
400 
401 	radio_pkt_tx_set(pdu);
402 
403 	/* assert if radio packet ptr is not set and radio started rx */
404 	LL_ASSERT(!radio_is_ready());
405 
406 	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
407 		lll_prof_cputime_capture();
408 	}
409 
410 #if defined(CONFIG_BT_CTLR_PROFILE_ISR) || \
411 	defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
412 	/* capture end of AUX_SYNC_IND/AUX_CHAIN_IND PDU, used for calculating
413 	 * next PDU timestamp.
414 	 */
415 	radio_tmr_end_capture();
416 #endif /* CONFIG_BT_CTLR_PROFILE_ISR */
417 
418 #if defined(HAL_RADIO_GPIO_HAVE_PA_PIN)
419 	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
420 		/* PA/LNA enable is overwriting packet end used in ISR
421 		 * profiling, hence back it up for later use.
422 		 */
423 		lll_prof_radio_end_backup();
424 	}
425 
426 	radio_gpio_pa_setup();
427 	radio_gpio_pa_lna_enable(radio_tmr_tifs_base_get() +
428 				 EVENT_SYNC_B2B_MAFS_US -
429 				 (EVENT_CLOCK_JITTER_US << 1) + cte_len_us -
430 				 radio_tx_chain_delay_get(lll->phy_s, 0) -
431 				 HAL_RADIO_GPIO_PA_OFFSET);
432 #endif /* HAL_RADIO_GPIO_HAVE_PA_PIN */
433 
434 	/* Populate chan idx for AUX_CHAIN_IND PDU */
435 	chain_pdu_aux_ptr_chan_idx_set(lll_sync);
436 
437 	if (IS_ENABLED(CONFIG_BT_CTLR_PROFILE_ISR)) {
438 		lll_prof_send();
439 	}
440 }
441 
442 static int aux_ptr_get(struct pdu_adv *pdu, struct pdu_adv_aux_ptr **aux_ptr)
443 {
444 	struct pdu_adv_com_ext_adv *com_hdr;
445 	struct pdu_adv_ext_hdr *hdr;
446 	uint8_t *dptr;
447 
448 	/* Get reference to common extended header */
449 	com_hdr = (void *)&pdu->adv_ext_ind;
450 	if (com_hdr->ext_hdr_len == 0U) {
451 		return -EINVAL;
452 	}
453 
454 	/* Get reference to extended header flags and header fields */
455 	hdr = (void *)com_hdr->ext_hdr_adv_data;
456 	dptr = hdr->data;
457 
458 	/* No traverse through of AdvA and TargetA.
459 	 * These are RFU for periodic advertising, is not set by local device.
460 	 */
461 
462 	/* traverse through CTEInfo flag, if present */
463 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
464 	if (hdr->cte_info) {
465 		dptr += sizeof(struct pdu_cte_info);
466 	}
467 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
468 
469 	/* traverse through adi, if present */
470 	if (hdr->adi) {
471 		dptr += sizeof(struct pdu_adv_adi);
472 	}
473 
474 	/* check for aux_ptr flag */
475 	if (hdr->aux_ptr) {
476 		/* Return reference to aux pointer structure */
477 		*aux_ptr = (void *)dptr;
478 	} else {
479 		*aux_ptr = NULL;
480 	}
481 
482 	return 0;
483 }
484 
485 static void chain_pdu_aux_ptr_chan_idx_set(struct lll_adv_sync *lll)
486 {
487 	struct pdu_adv *chain_pdu;
488 
489 	/* No chain PDU */
490 	if (!lll->last_pdu) {
491 		return;
492 	}
493 
494 	/* Get reference to the auxiliary chain PDU */
495 	chain_pdu = lll_adv_pdu_linked_next_get(lll->last_pdu);
496 
497 	/* Check if there is further chain PDU */
498 	if (chain_pdu && chain_pdu->adv_ext_ind.ext_hdr_len &&
499 	    chain_pdu->adv_ext_ind.ext_hdr.aux_ptr) {
500 		aux_ptr_chan_idx_set(lll, chain_pdu);
501 	}
502 }
503 
504 static void aux_ptr_chan_idx_set(struct lll_adv_sync *lll, struct pdu_adv *pdu)
505 {
506 	struct pdu_adv_aux_ptr *aux_ptr;
507 	uint8_t chan_idx;
508 	int err;
509 
510 	/* Get reference to aux pointer structure */
511 	err = aux_ptr_get(pdu, &aux_ptr);
512 	LL_ASSERT(!err && aux_ptr);
513 
514 	/* Calculate a new channel index */
515 	chan_idx = lll_chan_sel_2(lll->data_chan_counter, lll->data_chan_id,
516 				  lll->chm[lll->chm_first].data_chan_map,
517 				  lll->chm[lll->chm_first].data_chan_count);
518 
519 	/* Increment counter, for next channel index calculation */
520 	lll->data_chan_counter++;
521 
522 	/* Set the channel index for the auxiliary chain PDU */
523 	aux_ptr->chan_idx = chan_idx;
524 }
525 static void switch_radio_complete_and_b2b_tx(const struct lll_adv_sync *lll,
526 					     uint8_t phy_s)
527 {
528 #if defined(CONFIG_BT_CTLR_DF_ADV_CTE_TX)
529 	if (lll->cte_started) {
530 		radio_switch_complete_and_phy_end_b2b_tx(phy_s, 0, phy_s, 0);
531 	} else
532 #endif /* CONFIG_BT_CTLR_DF_ADV_CTE_TX */
533 	{
534 		radio_switch_complete_and_b2b_tx(phy_s, 0, phy_s, 0);
535 	}
536 }
537 #endif /* CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK */
538