1 /*
2 * Copyright (c) 2018 - 2020 Nordic Semiconductor ASA
3 * Copyright (c) 2018 Ioannis Glaropoulos
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 #if defined(CONFIG_BT_CTLR_PHY_CODED)
9 /* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
10 * SW_SWITCH_TIMER-based auto-switch for TIFS, when receiving in LE Coded PHY.
11 * 'index' must be 0 or 1.
12 */
13 #define SW_SWITCH_TIMER_S2_EVTS_COMP(index) \
14 (SW_SWITCH_TIMER_EVTS_COMP_S2_BASE + (index))
15
16 /* Wire the SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
17 * to RADIO TASKS_TXEN/RXEN task.
18 */
19 #define HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(index) \
20 (HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE + (index))
21
22 static inline void hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,
23 uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index);
24 #endif
25
hal_radio_nrf_ppi_channels_enable(uint32_t mask)26 static inline void hal_radio_nrf_ppi_channels_enable(uint32_t mask)
27 {
28 nrf_ppi_channels_enable(NRF_PPI, mask);
29 }
30
hal_radio_nrf_ppi_channels_disable(uint32_t mask)31 static inline void hal_radio_nrf_ppi_channels_disable(uint32_t mask)
32 {
33 nrf_ppi_channels_disable(NRF_PPI, mask);
34 }
35
36 /*******************************************************************************
37 * Enable Radio on Event Timer tick:
38 * wire the EVENT_TIMER EVENTS_COMPARE[0] event to RADIO TASKS_TXEN/RXEN task.
39 *
40 * Use the pre-programmed PPI channels if possible (if TIMER0 is used as the
41 * EVENT_TIMER).
42 */
43 #if (EVENT_TIMER_ID == 0)
44
hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)45 static inline void hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)
46 {
47 /* No need to configure anything for the pre-programmed channels.
48 * Just enable and disable them accordingly.
49 */
50 if (trx) {
51 nrf_ppi_channels_enable(NRF_PPI,
52 BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI));
53 } else {
54 nrf_ppi_channels_enable(NRF_PPI,
55 BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI));
56 }
57 }
58
59 #else
60
hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)61 static inline void hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)
62 {
63 if (trx) {
64 nrf_ppi_channel_endpoint_setup(NRF_PPI,
65 HAL_RADIO_ENABLE_TX_ON_TICK_PPI,
66 (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[HAL_EVENT_TIMER_TRX_CC_OFFSET]),
67 (uint32_t)&(NRF_RADIO->TASKS_TXEN));
68
69 #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
70 NRF_PPI->CHG[SW_SWITCH_SINGLE_TIMER_TASK_GROUP_IDX] =
71 BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI);
72
73 nrf_ppi_fork_endpoint_setup(NRF_PPI,
74 HAL_RADIO_ENABLE_TX_ON_TICK_PPI,
75 (uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_SINGLE_TIMER_TASK_GROUP_IDX].DIS));
76 #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
77
78 nrf_ppi_channels_enable(NRF_PPI,
79 BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI));
80 } else {
81 nrf_ppi_channel_endpoint_setup(NRF_PPI,
82 HAL_RADIO_ENABLE_RX_ON_TICK_PPI,
83 (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[HAL_EVENT_TIMER_TRX_CC_OFFSET]),
84 (uint32_t)&(NRF_RADIO->TASKS_RXEN));
85
86 #if defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
87 NRF_PPI->CHG[SW_SWITCH_SINGLE_TIMER_TASK_GROUP_IDX] =
88 BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI);
89
90 nrf_ppi_fork_endpoint_setup(NRF_PPI,
91 HAL_RADIO_ENABLE_RX_ON_TICK_PPI,
92 (uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_SINGLE_TIMER_TASK_GROUP_IDX].DIS));
93 #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
94
95 nrf_ppi_channels_enable(NRF_PPI,
96 BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI));
97 }
98 }
99
100 #endif /* (EVENT_TIMER_ID == 0) */
101
102 /*******************************************************************************
103 * Capture event timer on Address reception:
104 * wire the RADIO EVENTS_ADDRESS event to the
105 * EVENT_TIMER TASKS_CAPTURE[<address timer>] task.
106 *
107 * Use the pre-programmed PPI channel if possible (if TIMER0 is used as the
108 * EVENT_TIMER).
109 */
110 #if (EVENT_TIMER_ID == 0)
111
hal_radio_recv_timeout_cancel_ppi_config(void)112 static inline void hal_radio_recv_timeout_cancel_ppi_config(void)
113 {
114 /* No need to configure anything for the pre-programmed channel. */
115 }
116
117 #else
118
hal_radio_recv_timeout_cancel_ppi_config(void)119 static inline void hal_radio_recv_timeout_cancel_ppi_config(void)
120 {
121 nrf_ppi_channel_endpoint_setup(
122 NRF_PPI,
123 HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI,
124 (uint32_t)&(NRF_RADIO->EVENTS_ADDRESS),
125 (uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[HAL_EVENT_TIMER_HCTO_CC_OFFSET]));
126 }
127
128 #endif /* (EVENT_TIMER_ID == 0) */
129
130 /*******************************************************************************
131 * Disable Radio on HCTO:
132 * wire the EVENT_TIMER EVENTS_COMPARE[<HCTO timer>] event
133 * to the RADIO TASKS_DISABLE task.
134 *
135 * Use the pre-programmed PPI channel if possible (if TIMER0 is used as the
136 * EVENT_TIMER).
137 */
138 #if (EVENT_TIMER_ID == 0)
139
hal_radio_disable_on_hcto_ppi_config(void)140 static inline void hal_radio_disable_on_hcto_ppi_config(void)
141 {
142 /* No need to configure anything for the pre-programmed channel. */
143 }
144
145 #else
146
hal_radio_disable_on_hcto_ppi_config(void)147 static inline void hal_radio_disable_on_hcto_ppi_config(void)
148 {
149 nrf_ppi_channel_endpoint_setup(
150 NRF_PPI,
151 HAL_RADIO_DISABLE_ON_HCTO_PPI,
152 (uint32_t)&(EVENT_TIMER->EVENTS_COMPARE[HAL_EVENT_TIMER_HCTO_CC_OFFSET]),
153 (uint32_t)&(NRF_RADIO->TASKS_DISABLE));
154 }
155
156 #endif /* (EVENT_TIMER_ID == 0) */
157
158 /*******************************************************************************
159 * Capture event timer on Radio end:
160 * wire the RADIO EVENTS_END event to the
161 * EVENT_TIMER TASKS_CAPTURE[<radio end timer>] task.
162 *
163 * Use the pre-programmed PPI channel if possible (if TIMER0 is used as the
164 * EVENT_TIMER).
165 */
166 #if (EVENT_TIMER_ID == 0)
167
hal_radio_end_time_capture_ppi_config(void)168 static inline void hal_radio_end_time_capture_ppi_config(void)
169 {
170 /* No need to configure anything for the pre-programmed channel. */
171 }
172
173 #else /* !(EVENT_TIMER_ID == 0) */
174
hal_radio_end_time_capture_ppi_config(void)175 static inline void hal_radio_end_time_capture_ppi_config(void)
176 {
177 nrf_ppi_channel_endpoint_setup(
178 NRF_PPI,
179 HAL_RADIO_END_TIME_CAPTURE_PPI,
180 (uint32_t)&(NRF_RADIO->HAL_RADIO_EVENTS_END),
181 (uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[HAL_EVENT_TIMER_TRX_END_CC_OFFSET]));
182 }
183
184 #endif /* !(EVENT_TIMER_ID == 0) */
185
186 /*******************************************************************************
187 * Start event timer on RTC tick:
188 * wire the RTC0 EVENTS_COMPARE[2] event to EVENT_TIMER TASKS_START task.
189 */
hal_event_timer_start_ppi_config(void)190 static inline void hal_event_timer_start_ppi_config(void)
191 {
192 nrf_ppi_channel_endpoint_setup(
193 NRF_PPI,
194 HAL_EVENT_TIMER_START_PPI,
195 (uint32_t)&(NRF_RTC0->EVENTS_COMPARE[2]),
196 (uint32_t)&(EVENT_TIMER->TASKS_START));
197 }
198
199 /*******************************************************************************
200 * Capture event timer on Radio ready:
201 * wire the RADIO EVENTS_READY event to the
202 * EVENT_TIMER TASKS_CAPTURE[<radio ready timer>] task.
203 */
hal_radio_ready_time_capture_ppi_config(void)204 static inline void hal_radio_ready_time_capture_ppi_config(void)
205 {
206 nrf_ppi_channel_endpoint_setup(
207 NRF_PPI,
208 HAL_RADIO_READY_TIME_CAPTURE_PPI,
209 (uint32_t)&(NRF_RADIO->EVENTS_READY),
210 (uint32_t)&(EVENT_TIMER->TASKS_CAPTURE[HAL_EVENT_TIMER_TRX_CC_OFFSET]));
211 }
212
213 /*******************************************************************************
214 * Trigger encryption task upon address reception:
215 * wire the RADIO EVENTS_ADDRESS event to the CCM TASKS_CRYPT task.
216 *
217 * PPI channel 25 is pre-programmed with the following fixed settings:
218 * EEP: RADIO->EVENTS_ADDRESS
219 * TEP: CCM->TASKS_CRYPT
220 */
hal_trigger_crypt_ppi_config(void)221 static inline void hal_trigger_crypt_ppi_config(void)
222 {
223 /* No need to configure anything for the pre-programmed channel. */
224 }
225
226 /*******************************************************************************
227 * Disable trigger encryption task
228 */
hal_trigger_crypt_ppi_disable(void)229 static inline void hal_trigger_crypt_ppi_disable(void)
230 {
231 /* No need to disable anything as ppi channel will be disabled in a
232 * separate disable ppi call by the caller of this function.
233 */
234 }
235
236 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
237 /*******************************************************************************
238 * Trigger encryption task on Bit counter match:
239 * wire the RADIO EVENTS_BCMATCH event to the CCM TASKS_CRYPT task.
240 *
241 * PPI channel HAL_TRIGGER_CRYPT_DELAY_PPI is also used for HAL_TRIGGER-
242 * _RATEOVERRIDE_PPI.
243 * Make sure the same PPI is not configured for both events at once.
244 *
245 * EEP: RADIO->EVENTS_BCMATCH
246 * TEP: CCM->TASKS_CRYPT
247 */
hal_trigger_crypt_by_bcmatch_ppi_config(void)248 static inline void hal_trigger_crypt_by_bcmatch_ppi_config(void)
249 {
250 /* Configure Bit counter to trigger EVENTS_BCMATCH for CCM_TASKS_CRYPT-
251 * _DELAY_BITS bit. This is a time required for Radio to store
252 * received data in memory before the CCM TASKS_CRYPT starts. This
253 * makes CCM to do not read the memory before Radio stores received
254 * data.
255 */
256 nrf_ppi_channel_endpoint_setup(NRF_PPI, HAL_TRIGGER_CRYPT_DELAY_PPI,
257 (uint32_t)&(NRF_RADIO->EVENTS_BCMATCH),
258 (uint32_t)&(NRF_CCM->TASKS_CRYPT));
259 }
260 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
261
262 /*******************************************************************************
263 * Trigger automatic address resolution on Bit counter match:
264 * wire the RADIO EVENTS_BCMATCH event to the AAR TASKS_START task.
265 *
266 * PPI channel 23 is pre-programmed with the following fixed settings:
267 * EEP: RADIO->EVENTS_BCMATCH
268 * TEP: AAR->TASKS_START
269 */
hal_trigger_aar_ppi_config(void)270 static inline void hal_trigger_aar_ppi_config(void)
271 {
272 /* No need to configure anything for the pre-programmed channel. */
273 }
274
275 /*******************************************************************************
276 * Trigger Radio Rate override upon Rateboost event.
277 */
278 #if defined(CONFIG_BT_CTLR_PHY_CODED) && defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
hal_trigger_rateoverride_ppi_config(void)279 static inline void hal_trigger_rateoverride_ppi_config(void)
280 {
281 nrf_ppi_channel_endpoint_setup(
282 NRF_PPI,
283 HAL_TRIGGER_RATEOVERRIDE_PPI,
284 (uint32_t)&(NRF_RADIO->EVENTS_RATEBOOST),
285 (uint32_t)&(NRF_CCM->TASKS_RATEOVERRIDE));
286 }
287 #endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
288
289 /******************************************************************************/
290 #if !defined(CONFIG_BT_CTLR_TIFS_HW)
291 /* PPI setup used for SW-based auto-switching during TIFS. */
292
293 #if !defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
294
295 /* Clear SW-switch timer on packet end:
296 * wire the RADIO EVENTS_END event to SW_SWITCH_TIMER TASKS_CLEAR task.
297 *
298 * Note: this PPI is not needed if we use a single TIMER instance in radio.c
299 */
300
hal_sw_switch_timer_clear_ppi_config(void)301 static inline void hal_sw_switch_timer_clear_ppi_config(void)
302 {
303 nrf_ppi_channel_endpoint_setup(
304 NRF_PPI,
305 HAL_SW_SWITCH_TIMER_CLEAR_PPI,
306 (uint32_t)&(NRF_RADIO->HAL_RADIO_TRX_EVENTS_END),
307 (uint32_t)&(SW_SWITCH_TIMER->TASKS_CLEAR));
308 }
309
310 #else /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
311
312 /* Clear event timer (sw-switch timer) on Radio end:
313 * wire the RADIO EVENTS_END event to the
314 * EVENT_TIMER TASKS_CLEAR task.
315 *
316 * Note: in nRF52X this PPI channel is forked for both capturing and clearing
317 * timer on RADIO EVENTS_END.
318 */
319
hal_sw_switch_timer_clear_ppi_config(void)320 static inline void hal_sw_switch_timer_clear_ppi_config(void)
321 {
322 nrf_ppi_fork_endpoint_setup(
323 NRF_PPI,
324 HAL_RADIO_END_TIME_CAPTURE_PPI,
325 (uint32_t)&(SW_SWITCH_TIMER->TASKS_CLEAR));
326 }
327
328 #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
329
330 /* The 2 adjacent PPI groups used for implementing SW_SWITCH_TIMER-based
331 * auto-switch for TIFS. 'index' must be 0 or 1.
332 */
333 #define SW_SWITCH_TIMER_TASK_GROUP(index) \
334 (SW_SWITCH_TIMER_TASK_GROUP_BASE + (index))
335
336 /* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
337 * SW_SWITCH_TIMER-based auto-switch for TIFS. 'index' must be 0 or 1.
338 */
339 #define SW_SWITCH_TIMER_EVTS_COMP(index) \
340 (SW_SWITCH_TIMER_EVTS_COMP_BASE + (index))
341
342 /* Wire a SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
343 * to a PPI GROUP TASK DISABLE task (PPI group with index <index>).
344 * 2 adjacent PPIs (9 & 10) and 2 adjacent PPI groups are used for this wiring;
345 * <index> must be 0 or 1. <offset> must be a valid TIMER CC register offset.
346 */
347 /* Because nRF52805 has limited number of programmable PPI channels,
348 * tIFS Trx SW switching on this SoC can be used only when pre-programmed
349 * PPI channels are also in use, i.e. when TIMER0 is the event timer.
350 */
351 #if (EVENT_TIMER_ID != 0) && defined(CONFIG_SOC_NRF52805)
352 #error "tIFS Trx SW switch can be used on this SoC only with TIMER0 as the event timer"
353 #endif
354
355 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(index) \
356 (HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE + (index))
357 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(cc_offset) \
358 ((uint32_t)&(SW_SWITCH_TIMER->EVENTS_COMPARE[cc_offset]))
359 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(index) \
360 ((uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].DIS))
361
362 /* Wire the RADIO EVENTS_END or EVENTS_PHYEND event to one of the PPI GROUP
363 * TASK ENABLE task. 2 adjacent PPI groups are used for this wiring.
364 * 'index' must be 0 or 1.
365 */
366 #define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT \
367 ((uint32_t)&(NRF_RADIO->HAL_RADIO_TRX_EVENTS_END))
368 #define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK(index) \
369 ((uint32_t)&(NRF_PPI->TASKS_CHG[SW_SWITCH_TIMER_TASK_GROUP(index)].EN))
370
371 /*Enable Radio at specific time-stamp:
372 * wire the SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
373 * to RADIO TASKS_TXEN/RXEN task.
374 * 2 adjacent PPIs (12 & 13) are used for this wiring; <index> must be 0 or 1.
375 * <offset> must be a valid TIMER CC register offset.
376 */
377 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI(index) \
378 (HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE + (index))
379 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(cc_offset) \
380 ((uint32_t)&(SW_SWITCH_TIMER->EVENTS_COMPARE[cc_offset]))
381 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX \
382 ((uint32_t)&(NRF_RADIO->TASKS_TXEN))
383 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX \
384 ((uint32_t)&(NRF_RADIO->TASKS_RXEN))
385
hal_radio_sw_switch_setup(uint8_t ppi_group_index)386 static inline void hal_radio_sw_switch_setup(uint8_t ppi_group_index)
387 {
388 /* Set up software switch mechanism for next Radio switch. */
389
390 /* Wire RADIO END event to PPI Group[<index>] enable task,
391 * over PPI[<HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI>]
392 */
393 nrf_ppi_channel_endpoint_setup(
394 NRF_PPI,
395 HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI,
396 HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT,
397 HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_TASK(ppi_group_index));
398 }
399
hal_radio_txen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)400 static inline void hal_radio_txen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
401 {
402 /* Wire SW Switch timer event <compare_reg> to the
403 * PPI[<radio_enable_ppi>] for enabling Radio. Do
404 * not wire the task; it is done by the caller of
405 * the function depending on the desired direction
406 * (TX/RX).
407 */
408 nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi,
409 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg_index));
410
411 nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi,
412 HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX);
413 }
414
hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)415 static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index,
416 uint8_t radio_enable_ppi)
417 {
418 /* NOTE: As independent PPI are used to trigger the Radio Tx task,
419 * double buffers implementation works for sw_switch using PPIs,
420 * simply reuse the hal_radio_txen_on_sw_switch() function to set
421 * the next PPIs task to be Radio Tx enable.
422 */
423 hal_radio_txen_on_sw_switch(compare_reg_index, radio_enable_ppi);
424 }
425
hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)426 static inline void hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
427 {
428 /* Wire SW Switch timer event <compare_reg> to the
429 * PPI[<radio_enable_ppi>] for enabling Radio. Do
430 * not wire the task; it is done by the caller of
431 * the function depending on the desired direction
432 * (TX/RX).
433 */
434 nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi,
435 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(compare_reg_index));
436
437 nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi,
438 HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_RX);
439 }
440
hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)441 static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index,
442 uint8_t radio_enable_ppi)
443 {
444 /* NOTE: As independent PPI are used to trigger the Radio Tx task,
445 * double buffers implementation works for sw_switch using PPIs,
446 * simply reuse the hal_radio_txen_on_sw_switch() function to set
447 * the next PPIs task to be Radio Tx enable.
448 */
449 hal_radio_rxen_on_sw_switch(compare_reg_index, radio_enable_ppi);
450 }
451
hal_radio_sw_switch_disable(void)452 static inline void hal_radio_sw_switch_disable(void)
453 {
454 /* Disable the following PPI channels that implement SW Switch:
455 * - Clearing SW SWITCH TIMER on RADIO END event
456 * - Do not clear for single timer use as it uses the same PPI as
457 * end time capture
458 * - Enabling SW SWITCH PPI Group on RADIO END event
459 */
460 nrf_ppi_channels_disable(
461 NRF_PPI,
462 #if !defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
463 BIT(HAL_SW_SWITCH_TIMER_CLEAR_PPI) |
464 #endif /* !CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
465 BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI));
466
467 /* Invalidation of subscription of S2 timer Compare used when
468 * RXing on LE Coded PHY is not needed, as other DPPI subscription
469 * is disable on each sw_switch call already.
470 */
471 }
472
hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index)473 static inline void hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index)
474 {
475 hal_radio_sw_switch_disable();
476 }
477
hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index)478 static inline void hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index)
479 {
480 hal_radio_sw_switch_disable();
481 }
482
hal_radio_sw_switch_cleanup(void)483 static inline void hal_radio_sw_switch_cleanup(void)
484 {
485 hal_radio_sw_switch_disable();
486 nrf_ppi_group_disable(NRF_PPI, SW_SWITCH_TIMER_TASK_GROUP(0));
487 nrf_ppi_group_disable(NRF_PPI, SW_SWITCH_TIMER_TASK_GROUP(1));
488 }
489
490 #if defined(CONFIG_BT_CTLR_PHY_CODED) && \
491 defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
492 /* Cancel the SW switch timer running considering S8 timing:
493 * wire the RADIO EVENTS_RATEBOOST event to SW_SWITCH_TIMER TASKS_CAPTURE task.
494 */
495 #define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT \
496 ((uint32_t)&(NRF_RADIO->EVENTS_RATEBOOST))
497 #define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_TASK(index) \
498 ((uint32_t)&(SW_SWITCH_TIMER->TASKS_CAPTURE[index]))
499
hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en,uint8_t ppi_dis,uint8_t cc_s2,uint8_t group_index)500 static inline void hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en,
501 uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index)
502 {
503 nrf_ppi_event_endpoint_setup(NRF_PPI, ppi_en,
504 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(cc_s2));
505
506 nrf_ppi_task_endpoint_setup(NRF_PPI, ppi_en,
507 HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX);
508
509 /* Wire the Group task disable
510 * to the S2 EVENTS_COMPARE.
511 */
512 nrf_ppi_event_endpoint_setup(NRF_PPI, ppi_dis,
513 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(cc_s2));
514
515 nrf_ppi_task_endpoint_setup(NRF_PPI, ppi_dis,
516 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(group_index));
517
518 /* Capture CC to cancel the timer that has assumed
519 * S8 reception, if packet will be received in S2.
520 */
521 nrf_ppi_event_endpoint_setup(NRF_PPI, HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI,
522 HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT);
523 nrf_ppi_task_endpoint_setup(NRF_PPI, HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI,
524 HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_TASK(
525 SW_SWITCH_TIMER_EVTS_COMP(group_index)));
526
527 nrf_ppi_channels_enable(
528 NRF_PPI,
529 BIT(HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI));
530
531 /* Note: below code is not absolutely needed, as other DPPI subscription
532 * is disable on each sw_switch call already.
533 */
534 if (IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) && false) {
535 /* We need to clear the other group S2 PPI */
536 group_index = (group_index + 1) & 0x01;
537 hal_radio_sw_switch_coded_config_clear(
538 HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(group_index),
539 0U, 0U, 0U);
540 }
541 }
542
hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,uint8_t ppi_dis,uint8_t cc_s2,uint8_t group_index)543 static inline void hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,
544 uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index)
545 {
546 /* Invalidate PPI used when RXing on LE Coded PHY. */
547 nrf_ppi_event_endpoint_setup(NRF_PPI, ppi_en, 0);
548 nrf_ppi_task_endpoint_setup(NRF_PPI, ppi_en, 0);
549 }
550
hal_radio_sw_switch_disable_group_clear(uint8_t ppi_dis,uint8_t cc_reg,uint8_t group_index)551 static inline void hal_radio_sw_switch_disable_group_clear(uint8_t ppi_dis, uint8_t cc_reg,
552 uint8_t group_index)
553 {
554 /* Wire the Group task disable to the default EVENTS_COMPARE. */
555 nrf_ppi_event_endpoint_setup(NRF_PPI, ppi_dis,
556 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(cc_reg));
557 nrf_ppi_task_endpoint_setup(NRF_PPI, ppi_dis,
558 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(group_index));
559 }
560
561 #else
562
hal_radio_group_task_disable_ppi_setup(void)563 static inline void hal_radio_group_task_disable_ppi_setup(void)
564 {
565 /* Wire SW SWITCH TIMER EVENTS COMPARE event <cc index-0> to
566 * PPI Group TASK [<index-0>] DISABLE task, over PPI<index-0>.
567 */
568 nrf_ppi_channel_endpoint_setup(
569 NRF_PPI,
570 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0),
571 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
572 SW_SWITCH_TIMER_EVTS_COMP(0)),
573 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(0));
574
575 /* Wire SW SWITCH TIMER event <compare index-1> to
576 * PPI Group[<index-1>] Disable Task, over PPI<index-1>.
577 */
578 nrf_ppi_channel_endpoint_setup(
579 NRF_PPI,
580 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1),
581 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
582 SW_SWITCH_TIMER_EVTS_COMP(1)),
583 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_TASK(1));
584 }
585 #endif /* CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
586
587 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
588 /* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing PHYEND delay compensation
589 * for SW_SWITCH_TIMER-based TIFS auto-switch. 'index' must be 0 or 1.
590 */
591 #define SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_EVTS_COMP(index) \
592 (SW_SWITCH_TIMER_EVTS_COMP_PHYEND_DELAY_COMPENSATION_BASE + (index))
593 /* Wire the SW SWITCH PHYEND delay compensation TIMER EVENTS_COMPARE[<cc_offset>] event to software
594 * switch TIMER0->CLEAR task.
595 */
596 #define HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI(index) \
597 (HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI_BASE + (index))
598
599 /* Cancel the SW switch timer running considering PHYEND delay compensation timing:
600 * wire the RADIO EVENTS_CTEPRESENT event to SW_SWITCH_TIMER TASKS_CAPTURE task.
601 */
602 #define HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_EVT \
603 ((uint32_t)&(NRF_RADIO->EVENTS_CTEPRESENT))
604 #define HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_TASK(index) \
605 ((uint32_t)&(SW_SWITCH_TIMER->TASKS_CAPTURE[index]))
606
607 /**
608 * @brief Setup additional EVENTS_COMPARE to compensate EVENTS_PHYEND delay.
609 *
610 * When EVENTS_PHYEND event is used to mark actual end of PDU, CTEINLINE is enabled but received
611 * PDU does not include CTE after CRC, the EVENTS_PHYEND will be generated with a short delay.
612 * That influences maintenance of TISF by software switch. To compensate the delay additional
613 * EVENTS_COMPARE events is set with TIFS value subtracted by the delay. This EVENT_COMPARE
614 * event will timeout before regular EVENTS_COMPARE and start radio switching procedure.
615 * In case there is a CTEInfo in the received PDU, an EVENTS_CTEPRESENT will be generated by
616 * Radio peripheral. The EVENTS_CTEPRESENT event is wired to cancel EVENTS_COMPARE setup for
617 * handling delayed EVENTS_PHYEND.
618 *
619 * Disable of the group of PPIs responsible for handling of software based switch is done by
620 * timeout of regular EVENTS_PHYEND event. The EVENTS_PHYEND delay is short enough (16 us) that
621 * it can use the same PPI to trigger disable the group for timeout for both EVENTS_COMPAREs.
622 * In case the EVENTS_COMPARE for delayed EVENTS_PHYEND event timesout, the group will be disabled
623 * within the Radio TX rampup period.
624 *
625 * @param radio_enable_ppi Index of PPI to wire EVENTS_PHYEND event to Radio enable TX task.
626 * @param phyend_delay_cc Index of EVENTS_COMPARE event to be set for delayed EVENTS_PHYEND event
627 */
628 static inline void
hal_radio_sw_switch_phyend_delay_compensation_config_set(uint8_t radio_enable_ppi,uint8_t phyend_delay_cc)629 hal_radio_sw_switch_phyend_delay_compensation_config_set(uint8_t radio_enable_ppi,
630 uint8_t phyend_delay_cc)
631 {
632 /* Wire EVENTS_COMPARE[<phyend_delay_cc_offs>] event to Radio TASKS_TXEN */
633 nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi,
634 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(phyend_delay_cc));
635
636 nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi,
637 HAL_SW_SWITCH_RADIO_ENABLE_PPI_TASK_TX);
638
639 /* Wire Radio CTEPRESENT event to cancel EVENTS_COMPARE[<cc_offs>] timer */
640 nrf_ppi_event_endpoint_setup(NRF_PPI,
641 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI,
642 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_EVT);
643 nrf_ppi_task_endpoint_setup(NRF_PPI,
644 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI,
645 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_TASK(phyend_delay_cc));
646
647 /* Enable CTEPRESENT event to disable EVENTS_COMPARE[<cc_offs>] PPI channel */
648 nrf_ppi_channels_enable(NRF_PPI,
649 BIT(HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI));
650 }
651
652 /**
653 * @brief Clear additional EVENTS_COMAPRE responsible for compensation EVENTS_PHYEND delay.
654 *
655 * Disables PPI responsible for cancel of EVENTS_COMPARE set for delayed EVENTS_PHYEND.
656 * Removes wireing of delayed EVENTS_COMPARE event to enable Radio TX task.
657 *
658 * @param radio_enable_ppi Index of PPI to wire EVENTS_PHYEND event to Radio enable TX task.
659 * @param phyend_delay_cc Not used in context of nRF52 SOCs
660 */
661 static inline void
hal_radio_sw_switch_phyend_delay_compensation_config_clear(uint8_t radio_enable_ppi,uint8_t phyend_delay_cc)662 hal_radio_sw_switch_phyend_delay_compensation_config_clear(uint8_t radio_enable_ppi,
663 uint8_t phyend_delay_cc)
664 {
665 /* Invalidate PPI used when */
666 nrf_ppi_event_endpoint_setup(NRF_PPI, radio_enable_ppi, NRF_PPI_NONE);
667 nrf_ppi_task_endpoint_setup(NRF_PPI, radio_enable_ppi, NRF_PPI_NONE);
668
669 /* Disable CTEPRESENT event to disable EVENTS_COMPARE[<phyend_delay_cc_offs>] PPI channel */
670 nrf_ppi_channels_disable(NRF_PPI,
671 BIT(HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI));
672 }
673 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
674
hal_radio_sw_switch_ppi_group_setup(void)675 static inline void hal_radio_sw_switch_ppi_group_setup(void)
676 {
677 /* Include the appropriate PPI channels in the two PPI Groups. */
678 #if !defined(CONFIG_BT_CTLR_PHY_CODED) || \
679 !defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
680 NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(0)] =
681 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)) |
682 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
683 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI(0)) |
684 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
685 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0));
686 NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(1)] =
687 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)) |
688 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
689 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI(1)) |
690 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
691 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1));
692 #else
693 NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(0)] =
694 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)) |
695 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0)) |
696 BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(0));
697 NRF_PPI->CHG[SW_SWITCH_TIMER_TASK_GROUP(1)] =
698 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)) |
699 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1)) |
700 BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(1));
701 #endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
702 }
703
704 #endif /* !CONFIG_BT_CTLR_TIFS_HW */
705