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_SOC_COMPATIBLE_NRF54LX)
9 #define NRF_DPPIC NRF_DPPIC10
10 #endif /* CONFIG_SOC_COMPATIBLE_NRF54LX */
11
hal_radio_nrf_ppi_channels_enable(uint32_t mask)12 static inline void hal_radio_nrf_ppi_channels_enable(uint32_t mask)
13 {
14 nrf_dppi_channels_enable(NRF_DPPIC, mask);
15 }
16
hal_radio_nrf_ppi_channels_disable(uint32_t mask)17 static inline void hal_radio_nrf_ppi_channels_disable(uint32_t mask)
18 {
19 nrf_dppi_channels_disable(NRF_DPPIC, mask);
20 }
21
22 /*******************************************************************************
23 * Enable Radio on Event Timer tick:
24 * wire the EVENT_TIMER EVENTS_COMPARE[0] event to RADIO TASKS_TXEN/RXEN task.
25 */
hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)26 static inline void hal_radio_enable_on_tick_ppi_config_and_enable(uint8_t trx)
27 {
28 if (trx) {
29 nrf_timer_publish_set(EVENT_TIMER, NRF_TIMER_EVENT_COMPARE0,
30 HAL_RADIO_ENABLE_TX_ON_TICK_PPI);
31 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN,
32 HAL_RADIO_ENABLE_TX_ON_TICK_PPI);
33
34 /* Address nRF5340 Engineering A Errata 16 */
35 if (IS_ENABLED(CONFIG_BT_CTLR_TIFS_HW)) {
36 nrf_radio_subscribe_clear(NRF_RADIO,
37 NRF_RADIO_TASK_RXEN);
38 }
39
40 nrf_dppi_channels_enable(NRF_DPPIC,
41 BIT(HAL_RADIO_ENABLE_TX_ON_TICK_PPI));
42 } else {
43 nrf_timer_publish_set(EVENT_TIMER, NRF_TIMER_EVENT_COMPARE0,
44 HAL_RADIO_ENABLE_RX_ON_TICK_PPI);
45 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN,
46 HAL_RADIO_ENABLE_RX_ON_TICK_PPI);
47
48 /* Address nRF5340 Engineering A Errata 16 */
49 if (IS_ENABLED(CONFIG_BT_CTLR_TIFS_HW)) {
50 nrf_radio_subscribe_clear(NRF_RADIO,
51 NRF_RADIO_TASK_TXEN);
52 }
53
54 nrf_dppi_channels_enable(NRF_DPPIC,
55 BIT(HAL_RADIO_ENABLE_RX_ON_TICK_PPI));
56 }
57 }
58
59 /*******************************************************************************
60 * Capture event timer on Address reception:
61 * wire the RADIO EVENTS_ADDRESS event to the
62 * EVENT_TIMER TASKS_CAPTURE[<address timer>] task.
63 */
hal_radio_recv_timeout_cancel_ppi_config(void)64 static inline void hal_radio_recv_timeout_cancel_ppi_config(void)
65 {
66 nrf_radio_publish_set(NRF_RADIO,
67 NRF_RADIO_EVENT_ADDRESS, HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI);
68 nrf_timer_subscribe_set(EVENT_TIMER,
69 NRF_TIMER_TASK_CAPTURE1, HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI);
70 }
71
72 /*******************************************************************************
73 * Disable Radio on HCTO:
74 * wire the EVENT_TIMER EVENTS_COMPARE[<HCTO timer>] event
75 * to the RADIO TASKS_DISABLE task.
76 */
hal_radio_disable_on_hcto_ppi_config(void)77 static inline void hal_radio_disable_on_hcto_ppi_config(void)
78 {
79 nrf_timer_publish_set(EVENT_TIMER,
80 NRF_TIMER_EVENT_COMPARE1, HAL_RADIO_DISABLE_ON_HCTO_PPI);
81 nrf_radio_subscribe_set(NRF_RADIO,
82 NRF_RADIO_TASK_DISABLE, HAL_RADIO_DISABLE_ON_HCTO_PPI);
83 }
84
85 /*******************************************************************************
86 * Capture event timer on Radio end:
87 * wire the RADIO EVENTS_END event to the
88 * EVENT_TIMER TASKS_CAPTURE[<radio end timer>] task.
89 */
hal_radio_end_time_capture_ppi_config(void)90 static inline void hal_radio_end_time_capture_ppi_config(void)
91 {
92 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_END, HAL_RADIO_END_TIME_CAPTURE_PPI);
93 nrf_timer_subscribe_set(EVENT_TIMER,
94 NRF_TIMER_TASK_CAPTURE2, HAL_RADIO_END_TIME_CAPTURE_PPI);
95 }
96
97 /*******************************************************************************
98 * Start event timer on RTC tick:
99 * wire the RTC0 EVENTS_COMPARE[2] event to EVENT_TIMER TASKS_START task.
100 */
hal_event_timer_start_ppi_config(void)101 static inline void hal_event_timer_start_ppi_config(void)
102 {
103 #if defined(CONFIG_BT_CTLR_NRF_GRTC)
104 /* Publish GRTC compare */
105 nrf_grtc_publish_set(NRF_GRTC, HAL_CNTR_GRTC_EVENT_COMPARE_RADIO,
106 HAL_EVENT_TIMER_START_PPI);
107
108 /* Enable same DPPI in Global domain */
109 nrf_dppi_channels_enable(NRF_DPPIC20,
110 BIT(HAL_EVENT_TIMER_START_PPI));
111
112 /* Setup PPIB send subscribe */
113 nrf_ppib_subscribe_set(NRF_PPIB21, HAL_PPIB_SEND_EVENT_TIMER_START_PPI,
114 HAL_EVENT_TIMER_START_PPI);
115
116 /* Setup PPIB receive publish */
117 nrf_ppib_publish_set(NRF_PPIB11, HAL_PPIB_RECEIVE_EVENT_TIMER_START_PPI,
118 HAL_EVENT_TIMER_START_PPI);
119
120 #else /* !CONFIG_BT_CTLR_NRF_GRTC */
121 nrf_rtc_publish_set(NRF_RTC, NRF_RTC_EVENT_COMPARE_2, HAL_EVENT_TIMER_START_PPI);
122 #endif /* !CONFIG_BT_CTLR_NRF_GRTC */
123
124 nrf_timer_subscribe_set(EVENT_TIMER, NRF_TIMER_TASK_START, HAL_EVENT_TIMER_START_PPI);
125 }
126
127 /*******************************************************************************
128 * Capture event timer on Radio ready:
129 * wire the RADIO EVENTS_READY event to the
130 * EVENT_TIMER TASKS_CAPTURE[<radio ready timer>] task.
131 */
hal_radio_ready_time_capture_ppi_config(void)132 static inline void hal_radio_ready_time_capture_ppi_config(void)
133 {
134 nrf_radio_publish_set(NRF_RADIO,
135 NRF_RADIO_EVENT_READY, HAL_RADIO_READY_TIME_CAPTURE_PPI);
136 nrf_timer_subscribe_set(EVENT_TIMER,
137 NRF_TIMER_TASK_CAPTURE0, HAL_RADIO_READY_TIME_CAPTURE_PPI);
138 }
139
140 #if defined(CONFIG_BT_CTLR_LE_ENC) || defined(CONFIG_BT_CTLR_BROADCAST_ISO_ENC)
141 /*******************************************************************************
142 * Trigger encryption task upon address reception:
143 * wire the RADIO EVENTS_ADDRESS event to the CCM TASKS_CRYPT task.
144 *
145 * Note: we do not need an additional PPI, since we have already set up
146 * a PPI to publish RADIO ADDRESS event.
147 */
hal_trigger_crypt_ppi_config(void)148 static inline void hal_trigger_crypt_ppi_config(void)
149 {
150 nrf_radio_publish_set(NRF_RADIO,
151 NRF_RADIO_EVENT_ADDRESS, HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI);
152 nrf_ccm_subscribe_set(NRF_CCM, NRF_CCM_TASK_START, HAL_RADIO_RECV_TIMEOUT_CANCEL_PPI);
153 }
154
155 /*******************************************************************************
156 * Disable trigger encryption task
157 */
hal_trigger_crypt_ppi_disable(void)158 static inline void hal_trigger_crypt_ppi_disable(void)
159 {
160 nrf_ccm_subscribe_clear(NRF_CCM, NRF_CCM_TASK_START);
161 }
162
163 /*******************************************************************************
164 * Trigger automatic address resolution on Bit counter match:
165 * wire the RADIO EVENTS_BCMATCH event to the AAR TASKS_START task.
166 */
hal_trigger_aar_ppi_config(void)167 static inline void hal_trigger_aar_ppi_config(void)
168 {
169 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH, HAL_TRIGGER_AAR_PPI);
170 nrf_aar_subscribe_set(NRF_AAR, NRF_AAR_TASK_START, HAL_TRIGGER_AAR_PPI);
171 }
172
173 /* When hardware does not support Coded PHY we still allow the Controller
174 * implementation to accept Coded PHY flags, but the Controller will use 1M
175 * PHY on air. This is implementation specific feature.
176 */
177 #if defined(CONFIG_BT_CTLR_PHY_CODED) && defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
178 /*******************************************************************************
179 * Trigger Radio Rate override upon Rateboost event.
180 */
hal_trigger_rateoverride_ppi_config(void)181 static inline void hal_trigger_rateoverride_ppi_config(void)
182 {
183 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_RATEBOOST, HAL_TRIGGER_RATEOVERRIDE_PPI);
184 nrf_ccm_subscribe_set(NRF_CCM, NRF_CCM_TASK_RATEOVERRIDE, HAL_TRIGGER_RATEOVERRIDE_PPI);
185 }
186 #endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
187
188 #if defined(CONFIG_BT_CTLR_DF_CONN_CTE_RX)
189 /*******************************************************************************
190 * Trigger encryption task on Bit counter match:
191 * wire the RADIO EVENTS_BCMATCH event to the CCM TASKS_CRYPT task.
192 *
193 * PPI channel HAL_TRIGGER_CRYPT_DELAY_PPI is also used for HAL_TRIGGER-
194 * _RATEOVERRIDE_PPI.
195 * Make sure the same PPI is not configured for both events at once.
196 *
197 * EEP: RADIO->EVENTS_BCMATCH
198 * TEP: CCM->TASKS_CRYPT
199 */
hal_trigger_crypt_by_bcmatch_ppi_config(void)200 static inline void hal_trigger_crypt_by_bcmatch_ppi_config(void)
201 {
202 /* Configure Bit counter to trigger EVENTS_BCMATCH for CCM_TASKS_CRYPT-
203 * _DELAY_BITS bit. This is a time required for Radio to store
204 * received data in memory before the CCM TASKS_CRYPT starts. This
205 * makes CCM to do not read the memory before Radio stores received
206 * data.
207 */
208 nrf_radio_publish_set(NRF_RADIO,
209 NRF_RADIO_EVENT_BCMATCH, HAL_TRIGGER_CRYPT_DELAY_PPI);
210 nrf_ccm_subscribe_set(NRF_CCM, NRF_CCM_TASK_START, HAL_TRIGGER_CRYPT_DELAY_PPI);
211 }
212 #endif /* CONFIG_BT_CTLR_DF_CONN_CTE_RX */
213 #endif /* CONFIG_BT_CTLR_LE_ENC || CONFIG_BT_CTLR_BROADCAST_ISO_ENC */
214
215 /******************************************************************************/
216 #if !defined(CONFIG_BT_CTLR_TIFS_HW)
217
218 #if !defined(CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER)
219 #define NRF_RADIO_PUBLISH_PDU_END_EVT PUBLISH_PHYEND
220 /* Wrappenr for EVENTS_END event name used by nRFX API */
221 #define NRFX_RADIO_TXRX_END_EVENT NRF_RADIO_EVENT_PHYEND
222 #else /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
223 #define NRF_RADIO_PUBLISH_PDU_END_EVT PUBLISH_END
224 #define NRFX_RADIO_TXRX_END_EVENT NRF_RADIO_EVENT_END
225 #endif /* CONFIG_BT_CTLR_SW_SWITCH_SINGLE_TIMER */
226
227 /* DPPI setup used for SW-based auto-switching during TIFS. */
228
229 /* Clear SW-switch timer on packet end:
230 * wire the RADIO EVENTS_END event to SW_SWITCH_TIMER TASKS_CLEAR task.
231 *
232 * Note: In case of HW TIFS support or single timer configuration we do not need
233 * an additional PPI, since we have already set up a PPI to publish RADIO END
234 * event. In other case separate PPI is used because packet end is marked by
235 * PHYEND event while last bit or CRC is marked by END event.
236 */
hal_sw_switch_timer_clear_ppi_config(void)237 static inline void hal_sw_switch_timer_clear_ppi_config(void)
238 {
239 nrf_radio_publish_set(NRF_RADIO, NRFX_RADIO_TXRX_END_EVENT, HAL_SW_SWITCH_TIMER_CLEAR_PPI);
240 nrf_timer_subscribe_set(SW_SWITCH_TIMER,
241 NRF_TIMER_TASK_CLEAR, HAL_SW_SWITCH_TIMER_CLEAR_PPI);
242
243 /* NOTE: nRF5340 may share the DPPI channel being triggered by Radio End,
244 * for End time capture and sw_switch DPPI channel toggling.
245 * The channel must be always enabled when software switch is used.
246 */
247 nrf_dppi_channels_enable(NRF_DPPIC, BIT(HAL_SW_SWITCH_TIMER_CLEAR_PPI));
248 }
249
250 /* The 2 adjacent PPI groups used for implementing SW_SWITCH_TIMER-based
251 * auto-switch for TIFS. 'index' must be 0 or 1.
252 */
253 #define SW_SWITCH_TIMER_TASK_GROUP(index) \
254 (SW_SWITCH_TIMER_TASK_GROUP_BASE + (index))
255
256 /* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
257 * SW_SWITCH_TIMER-based auto-switch for TIFS. 'index' must be 0 or 1.
258 */
259 #define SW_SWITCH_TIMER_EVTS_COMP(index) \
260 (SW_SWITCH_TIMER_EVTS_COMP_BASE + (index))
261
262 /* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing
263 * SW_SWITCH_TIMER-based auto-switch for TIFS, when receiving on LE Coded
264 * PHY. 'index' must be 0 or 1.
265 */
266 #define SW_SWITCH_TIMER_S2_EVTS_COMP(index) \
267 (SW_SWITCH_TIMER_EVTS_COMP_S2_BASE + (index))
268
269 /*
270 * Convert a dppi channel group number into the *enable* task enumerate value
271 * the nrfx hal accepts
272 */
273 #define HAL_SW_DPPI_TASK_EN_FROM_IDX(index) \
274 (NRF_DPPI_TASK_CHG0_EN + ((index) * (NRF_DPPI_TASK_CHG1_EN - NRF_DPPI_TASK_CHG0_EN)))
275
276 /*
277 * Convert a dppi channel group number into the *disable* task enumerate value
278 * the nrfx hal accepts
279 */
280 #define HAL_SW_DPPI_TASK_DIS_FROM_IDX(index) \
281 (NRF_DPPI_TASK_CHG0_DIS + ((index) * (NRF_DPPI_TASK_CHG1_EN - NRF_DPPI_TASK_CHG0_EN)))
282
283 /* Wire a SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
284 * to a PPI GROUP TASK DISABLE task (PPI group with index <index>).
285 * 2 adjacent PPIs (14 & 15) and 2 adjacent PPI groups are used for this wiring;
286 * <index> must be 0 or 1. <offset> must be a valid TIMER CC register offset.
287 */
288 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(index) \
289 (HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE + (index))
290
291 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(cc_offset) \
292 SW_SWITCH_TIMER->PUBLISH_COMPARE[cc_offset]
293 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(chan) \
294 (((chan << TIMER_PUBLISH_COMPARE_CHIDX_Pos) \
295 & TIMER_PUBLISH_COMPARE_CHIDX_Msk) | \
296 ((TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos) \
297 & TIMER_PUBLISH_COMPARE_EN_Msk))
298 #define HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(index, channel) \
299 nrf_dppi_subscribe_set(NRF_DPPIC, \
300 HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(index)), \
301 channel);
302
303 /* Enable the SW Switch PPI Group on RADIO END Event.
304 *
305 * Note: we do not need an additional PPI, since we have already set up
306 * a PPI to publish RADIO END event.
307 */
308 #define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_EVT (NRF_RADIO->NRF_RADIO_PUBLISH_PDU_END_EVT)
309 #define HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT \
310 (((HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI << \
311 RADIO_PUBLISH_END_CHIDX_Pos) \
312 & RADIO_PUBLISH_END_CHIDX_Msk) | \
313 ((RADIO_PUBLISH_END_EN_Enabled << RADIO_PUBLISH_END_EN_Pos) \
314 & RADIO_PUBLISH_END_EN_Msk))
315
316 /* Enable Radio on SW Switch timer event.
317 * Wire a SW SWITCH TIMER EVENTS_COMPARE[<cc_offset>] event
318 * to a RADIO Enable task (TX or RX).
319 *
320 * Note:
321 * We use the same PPI as for disabling the SW Switch PPI groups,
322 * since we need to listen for the same event (SW Switch event).
323 *
324 * We use the same PPI for the alternative SW Switch Timer compare
325 * event.
326 */
327 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI(index) \
328 (HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE + (index))
329
330 #define HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(index) \
331 (HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE + (index))
332
333 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(cc_offset) \
334 SW_SWITCH_TIMER->PUBLISH_COMPARE[cc_offset]
335 #define HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(chan) \
336 (((chan << TIMER_PUBLISH_COMPARE_CHIDX_Pos) \
337 & TIMER_PUBLISH_COMPARE_CHIDX_Msk) | \
338 ((TIMER_PUBLISH_COMPARE_EN_Enabled << TIMER_PUBLISH_COMPARE_EN_Pos) \
339 & TIMER_PUBLISH_COMPARE_EN_Msk))
340
341 /* Cancel the SW switch timer running considering S8 timing:
342 * wire the RADIO EVENTS_RATEBOOST event to SW_SWITCH_TIMER TASKS_CAPTURE task.
343 *
344 * Note: We already have a PPI where we publish the RATEBOOST event.
345 */
346 #define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_EVT \
347 NRF_RADIO->PUBLISH_RATEBOOST
348 #define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT \
349 (((HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI << \
350 RADIO_PUBLISH_RATEBOOST_CHIDX_Pos) \
351 & RADIO_PUBLISH_RATEBOOST_CHIDX_Msk) | \
352 ((RADIO_PUBLISH_RATEBOOST_EN_Enabled << \
353 RADIO_PUBLISH_RATEBOOST_EN_Pos) \
354 & RADIO_PUBLISH_RATEBOOST_EN_Msk))
355 #define HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_TASK(cc_reg) \
356 SW_SWITCH_TIMER->SUBSCRIBE_CAPTURE[cc_reg]
357
358 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
359 /* The 2 adjacent TIMER EVENTS_COMPARE event offsets used for implementing PHYEND delay compensation
360 * for SW_SWITCH_TIMER-based TIFS auto-switch. 'index' must be 0 or 1.
361 */
362 #define SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_EVTS_COMP(index) \
363 (SW_SWITCH_TIMER_EVTS_COMP_PHYEND_DELAY_COMPENSATION_BASE + (index))
364 #define HAL_SW_SWITCH_RADIO_ENABLE_PHYEND_DELAY_COMPENSATION_PPI(index) \
365 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(index)
366
367 /* Cancel the SW switch timer running considering PHYEND delay compensation timing:
368 * wire the RADIO EVENTS_CTEPRESENT event to SW_SWITCH_TIMER TASKS_CAPTURE task.
369 */
370 #define HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_REGISTER_EVT \
371 NRF_RADIO->PUBLISH_CTEPRESENT
372
373 #define HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_EVT \
374 (((HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI \
375 << RADIO_PUBLISH_CTEPRESENT_CHIDX_Pos) & \
376 RADIO_PUBLISH_CTEPRESENT_CHIDX_Msk) | \
377 ((RADIO_PUBLISH_CTEPRESENT_EN_Enabled << RADIO_PUBLISH_CTEPRESENT_EN_Pos) & \
378 RADIO_PUBLISH_CTEPRESENT_EN_Msk))
379
380 #define HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_TASK \
381 (((HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI \
382 << TIMER_SUBSCRIBE_CAPTURE_CHIDX_Pos) & \
383 TIMER_SUBSCRIBE_CAPTURE_CHIDX_Msk) | \
384 ((TIMER_SUBSCRIBE_CAPTURE_EN_Enabled << TIMER_SUBSCRIBE_CAPTURE_EN_Pos) & \
385 TIMER_SUBSCRIBE_CAPTURE_EN_Msk))
386
387 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
388
hal_radio_sw_switch_setup(uint8_t ppi_group_index)389 static inline void hal_radio_sw_switch_setup(uint8_t ppi_group_index)
390 {
391 /* Set up software switch mechanism for next Radio switch. */
392
393 /* Wire RADIO END event to PPI Group[<index>] enable task,
394 * over PPI[<HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI>]
395 */
396 HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_REGISTER_EVT =
397 HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI_EVT;
398 nrf_dppi_subscribe_set(NRF_DPPIC,
399 HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(ppi_group_index)),
400 HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI);
401
402 /* We need to un-subscribe the other group from the PPI channel. */
403 uint8_t other_grp = (ppi_group_index + 1) & 0x01;
404
405 nrf_dppi_subscribe_clear(NRF_DPPIC,
406 HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(other_grp)));
407 }
408
hal_radio_txen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)409 static inline void hal_radio_txen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
410 {
411 /* Wire SW Switch timer event <compare_reg> to the
412 * PPI[<radio_enable_ppi>] for enabling Radio. Do
413 * not wire the task; it is done by the caller of
414 * the function depending on the desired direction
415 * (TX/RX).
416 */
417 HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) =
418 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
419
420 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, radio_enable_ppi);
421 }
422
hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)423 static inline void hal_radio_b2b_txen_on_sw_switch(uint8_t compare_reg_index,
424 uint8_t radio_enable_ppi)
425 {
426 /* Wire SW Switch timer event <compare_reg> to the
427 * PPI[<radio_enable_ppi>] for enabling Radio. Do
428 * not wire the task; it is done by the caller of
429 * the function depending on the desired direction
430 * (TX/RX).
431 */
432 HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) =
433 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
434
435 uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01;
436
437 radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx);
438 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, radio_enable_ppi);
439 }
440
hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)441 static inline void hal_radio_rxen_on_sw_switch(uint8_t compare_reg_index, uint8_t radio_enable_ppi)
442 {
443 /* Wire SW Switch timer event <compare_reg> to the
444 * PPI[<radio_enable_ppi>] for enabling Radio. Do
445 * not wire the task; it is done by the caller of
446 * the function depending on the desired direction
447 * (TX/RX).
448 */
449 HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) =
450 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
451
452 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, radio_enable_ppi);
453 }
454
hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index,uint8_t radio_enable_ppi)455 static inline void hal_radio_b2b_rxen_on_sw_switch(uint8_t compare_reg_index,
456 uint8_t radio_enable_ppi)
457 {
458 /* Wire SW Switch timer event <compare_reg> to the
459 * PPI[<radio_enable_ppi>] for enabling Radio. Do
460 * not wire the task; it is done by the caller of
461 * the function depending on the desired direction
462 * (TX/RX).
463 */
464 HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(compare_reg_index) =
465 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
466
467 uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01;
468
469 radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx);
470 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, radio_enable_ppi);
471 }
472
hal_radio_sw_switch_disable(void)473 static inline void hal_radio_sw_switch_disable(void)
474 {
475 /* We cannot deactivate the PPI channels, as other tasks
476 * are subscribed to RADIO_END event, i.e on the same channel.
477 * So we simply cancel the task subscription.
478 */
479 nrf_timer_subscribe_clear(SW_SWITCH_TIMER, NRF_TIMER_TASK_CLEAR);
480 nrf_dppi_subscribe_clear(NRF_DPPIC,
481 HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(0)));
482 nrf_dppi_subscribe_clear(NRF_DPPIC,
483 HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1)));
484
485 /* Invalidation of subscription of S2 timer Compare used when
486 * RXing on LE Coded PHY is not needed, as other DPPI subscription
487 * is disable on each sw_switch call already.
488 */
489 }
490
hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index)491 static inline void hal_radio_sw_switch_b2b_tx_disable(uint8_t compare_reg_index)
492 {
493 hal_radio_sw_switch_disable();
494
495 uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01;
496 uint8_t radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx);
497
498 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, radio_enable_ppi);
499 }
500
hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index)501 static inline void hal_radio_sw_switch_b2b_rx_disable(uint8_t compare_reg_index)
502 {
503 hal_radio_sw_switch_disable();
504
505 uint8_t prev_ppi_idx = (compare_reg_index + 0x01) & 0x01;
506 uint8_t radio_enable_ppi = HAL_SW_SWITCH_RADIO_ENABLE_PPI(prev_ppi_idx);
507
508 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_RXEN, radio_enable_ppi);
509 }
510
hal_radio_sw_switch_cleanup(void)511 static inline void hal_radio_sw_switch_cleanup(void)
512 {
513 hal_radio_sw_switch_disable();
514 nrf_dppi_channels_disable(NRF_DPPIC,
515 (BIT(HAL_SW_SWITCH_TIMER_CLEAR_PPI) |
516 BIT(HAL_SW_SWITCH_GROUP_TASK_ENABLE_PPI)));
517 nrf_dppi_group_disable(NRF_DPPIC, SW_SWITCH_TIMER_TASK_GROUP(0));
518 nrf_dppi_group_disable(NRF_DPPIC, SW_SWITCH_TIMER_TASK_GROUP(1));
519 }
520
521 #if defined(CONFIG_BT_CTLR_PHY_CODED)
hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en,uint8_t ppi_dis,uint8_t cc_s2,uint8_t group_index)522 static inline void hal_radio_sw_switch_coded_tx_config_set(uint8_t ppi_en,
523 uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index)
524 {
525 /* Publish the SW Switch Timer Compare event for S2 timing
526 * to the PPI that will be used to trigger Radio enable.
527 */
528 HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(cc_s2) =
529 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(ppi_en);
530
531 /* The Radio Enable Task is already subscribed to the channel. */
532
533 /* Wire the Group task disable to the S2 EVENTS_COMPARE. */
534 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(cc_s2) =
535 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(ppi_dis);
536
537 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(group_index,
538 ppi_dis);
539
540 /* Capture CC to cancel the timer that has assumed
541 * S8 reception, if packet will be received in S2.
542 */
543 HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_REGISTER_EVT =
544 HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI_EVT;
545 nrf_timer_subscribe_set(SW_SWITCH_TIMER,
546 nrf_timer_capture_task_get(cc_s2),
547 HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI);
548
549 nrf_dppi_channels_enable(NRF_DPPIC,
550 BIT(HAL_SW_SWITCH_TIMER_S8_DISABLE_PPI));
551 }
552
553 /* When hardware does not support Coded PHY we still allow the Controller
554 * implementation to accept Coded PHY flags, but the Controller will use 1M
555 * PHY on air. This is implementation specific feature.
556 */
557 #if defined(CONFIG_BT_CTLR_PHY_CODED) && defined(CONFIG_HAS_HW_NRF_RADIO_BLE_CODED)
hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,uint8_t ppi_dis,uint8_t cc_s2,uint8_t group_index)558 static inline void hal_radio_sw_switch_coded_config_clear(uint8_t ppi_en,
559 uint8_t ppi_dis, uint8_t cc_s2, uint8_t group_index)
560 {
561 /* Invalidate subscription of S2 timer Compare used when
562 * RXing on LE Coded PHY.
563 *
564 * Note: we do not un-subscribe the Radio enable task because
565 * we use the same PPI for both SW Switch Timer compare events.
566 */
567 HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(cc_s2) = 0U;
568 }
569 #endif /* CONFIG_BT_CTLR_PHY_CODED && CONFIG_HAS_HW_NRF_RADIO_BLE_CODED */
570
hal_radio_sw_switch_disable_group_clear(uint8_t ppi_dis,uint8_t cc_reg,uint8_t group_index)571 static inline void hal_radio_sw_switch_disable_group_clear(uint8_t ppi_dis, uint8_t cc_reg,
572 uint8_t group_index)
573 {
574 /* Wire the Group[group_index] task disable to the default
575 * SW Switch Timer EVENTS_COMPARE.
576 */
577 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(
578 cc_reg) =
579 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
580 ppi_dis);
581 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(
582 group_index, ppi_dis);
583 }
584 #endif /* defined(CONFIG_BT_CTLR_PHY_CODED) */
585
hal_radio_sw_switch_ppi_group_setup(void)586 static inline void hal_radio_sw_switch_ppi_group_setup(void)
587 {
588 /* Include the appropriate PPI channels in the two PPI Groups, used for
589 * SW-based TIFS.
590 *
591 * Note that this needs to be done before any SUBSCRIBE task
592 * registers are written, therefore, we clear the task registers
593 * here.
594 */
595 nrf_dppi_subscribe_clear(NRF_DPPIC,
596 HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(0)));
597 nrf_dppi_subscribe_clear(NRF_DPPIC,
598 HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(0)));
599 nrf_dppi_subscribe_clear(NRF_DPPIC,
600 HAL_SW_DPPI_TASK_EN_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1)));
601 nrf_dppi_subscribe_clear(NRF_DPPIC,
602 HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1)));
603
604 nrf_dppi_task_trigger(NRF_DPPIC,
605 HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(0)));
606 nrf_dppi_task_trigger(NRF_DPPIC,
607 HAL_SW_DPPI_TASK_DIS_FROM_IDX(SW_SWITCH_TIMER_TASK_GROUP(1)));
608
609 /* Include the appropriate PPI channels in the two PPI Groups. */
610 #if defined(CONFIG_BT_CTLR_PHY_CODED)
611 nrf_dppi_group_clear(NRF_DPPIC,
612 SW_SWITCH_TIMER_TASK_GROUP(0));
613 nrf_dppi_channels_include_in_group(NRF_DPPIC,
614 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)) |
615 BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(0)) |
616 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0)),
617 SW_SWITCH_TIMER_TASK_GROUP(0));
618 nrf_dppi_group_clear(NRF_DPPIC,
619 SW_SWITCH_TIMER_TASK_GROUP(1));
620 nrf_dppi_channels_include_in_group(NRF_DPPIC,
621 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)) |
622 BIT(HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI(1)) |
623 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1)),
624 SW_SWITCH_TIMER_TASK_GROUP(1));
625
626 /* NOTE: HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE is equal to
627 * HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE.
628 */
629 BUILD_ASSERT(
630 !IS_ENABLED(CONFIG_BT_CTLR_PHY_CODED) ||
631 (HAL_SW_SWITCH_RADIO_ENABLE_S2_PPI_BASE ==
632 HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE),
633 "Radio enable and Group disable not on the same PPI channels.");
634
635 #else /* !CONFIG_BT_CTLR_PHY_CODED */
636 nrf_dppi_group_clear(NRF_DPPIC,
637 SW_SWITCH_TIMER_TASK_GROUP(0));
638 nrf_dppi_channels_include_in_group(NRF_DPPIC,
639 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0)) |
640 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(0)),
641 SW_SWITCH_TIMER_TASK_GROUP(0));
642 nrf_dppi_group_clear(NRF_DPPIC,
643 SW_SWITCH_TIMER_TASK_GROUP(1));
644 nrf_dppi_channels_include_in_group(NRF_DPPIC,
645 BIT(HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1)) |
646 BIT(HAL_SW_SWITCH_RADIO_ENABLE_PPI(1)),
647 SW_SWITCH_TIMER_TASK_GROUP(1));
648 #endif /* !CONFIG_BT_CTLR_PHY_CODED */
649
650 /* Sanity build-time check that RADIO Enable and Group Disable
651 * tasks are going to be subscribed on the same PPIs.
652 */
653 BUILD_ASSERT(
654 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_BASE ==
655 HAL_SW_SWITCH_RADIO_ENABLE_PPI_BASE,
656 "Radio enable and Group disable not on the same PPI channels.");
657
658 /* Address nRF5340 Engineering A Errata 16 */
659 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_TXEN);
660 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_RXEN);
661 }
662
hal_radio_group_task_disable_ppi_setup(void)663 static inline void hal_radio_group_task_disable_ppi_setup(void)
664 {
665
666 /* Wire SW SWITCH TIMER EVENTS COMPARE event <cc index-0> to
667 * PPI Group TASK [<index-0>] DISABLE task, over PPI<index-0>.
668 */
669 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(
670 SW_SWITCH_TIMER_EVTS_COMP(0)) =
671 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
672 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0));
673 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(0,
674 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(0));
675
676 /* Wire SW SWITCH TIMER event <compare index-1> to
677 * PPI Group[<index-1>] Disable Task, over PPI<index-1>.
678 */
679 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_EVT(
680 SW_SWITCH_TIMER_EVTS_COMP(1)) =
681 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_EVT(
682 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1));
683 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI_REGISTER_TASK(1,
684 HAL_SW_SWITCH_GROUP_TASK_DISABLE_PPI(1));
685 }
686
687 #if defined(CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE)
688 /**
689 * @brief Setup additional EVENTS_COMPARE to compensate EVENTS_PHYEND delay.
690 *
691 * When EVENTS_PHYEND event is used to mark actual end of PDU, CTEINLINE is enabled but received
692 * PDU does not include CTE after CRC, the EVENTS_PHYEND will be generated with a short delay.
693 * That influences maintenance of TISF by software switch. To compensate the delay additional
694 * EVENTS_COMPARE events is set with TIFS value subtracted by the delay. This EVENT_COMPARE
695 * event will timeout before regular EVENTS_COMPARE and start radio switching procedure.
696 * In case there is a CTEInfo in the received PDU, an EVENTS_CTEPRESENT will be generated by
697 * Radio peripheral. The EVENTS_CTEPRESENT event is wired to cancel EVENTS_COMPARE setup for
698 * handling delayed EVENTS_PHYEND.
699 *
700 * Disable of the group of PPIs responsible for handling of software based switch is done by
701 * timeout of regular EVENTS_PHYEND event. The EVENTS_PHYEND delay is short enough (16 us) that
702 * the same EVENT COMPARE may be used to trigger disable task for the software switch group.
703 * In case the EVENTS_COMPARE for delayed EVENTS_PHYEND event timeouts, the group will be disabled
704 * within the Radio TX rampup period.
705 *
706 * CTEINLINE is enabled only for reception of PDUs that may include Constant Tone Extension.
707 * Delayed PHYEND event may occur only at end of received PDU, hence next task that is
708 * triggered by compensated EVENTS_COMPARE is Radio TASKS_TXEN.
709 *
710 * @param phyend_delay_cc Index of EVENTS_COMPARE event to be set for delayed EVENTS_PHYEND event
711 * @param radio_enable_ppi Index of PPI to wire EVENTS_PHYEND event to Radio enable TX task.
712 */
713 static inline void
hal_radio_sw_switch_phyend_delay_compensation_config_set(uint8_t radio_enable_ppi,uint8_t phyend_delay_cc)714 hal_radio_sw_switch_phyend_delay_compensation_config_set(uint8_t radio_enable_ppi,
715 uint8_t phyend_delay_cc)
716 {
717 /* Wire EVENTS_COMPARE[<phyend_delay_cc_offs>] event to Radio TASKS_TXEN */
718 HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(phyend_delay_cc) =
719 HAL_SW_SWITCH_RADIO_ENABLE_PPI_EVT(radio_enable_ppi);
720
721 /* The Radio Enable Task is already subscribed to the channel.
722 * There is no need to call channel enable again here.
723 */
724
725 /* Wire Radio CTEPRESENT event to cancel EVENTS_COMPARE[<cc_offs>] timer */
726 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_REGISTER_EVT =
727 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI_EVT;
728 nrf_timer_subscribe_set(SW_SWITCH_TIMER,
729 nrf_timer_capture_task_get(phyend_delay_cc),
730 HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI);
731
732 /* Enable CTEPRESENT event to disable EVENTS_COMPARE[<cc_offs>] PPI channel */
733 nrf_dppi_channels_enable(NRF_DPPIC,
734 BIT(HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI));
735 }
736
737 /**
738 * @brief Clear additional EVENTS_COMAPRE responsible for compensation EVENTS_PHYEND delay.
739 *
740 * Disables PPI responsible for cancel of EVENTS_COMPARE set for delayed EVENTS_PHYEND.
741 * Removes wiring of delayed EVENTS_COMPARE event to enable Radio TX task.
742 *
743 * @param phyend_delay_cc Index of EVENTS_COMPARE event to be cleared
744 * @param radio_enable_ppi Index of PPI to wire EVENTS_PHYEND event to Radio enable TX task.
745 */
746 static inline void
hal_radio_sw_switch_phyend_delay_compensation_config_clear(uint8_t radio_enable_ppi,uint8_t phyend_delay_cc)747 hal_radio_sw_switch_phyend_delay_compensation_config_clear(uint8_t radio_enable_ppi,
748 uint8_t phyend_delay_cc)
749 {
750 /* Invalidate PPI used for compensation of delayed EVETNS_PHYEND.
751 *
752 * Note: we do not un-subscribe the Radio enable task because
753 * we use the same PPI for both SW Switch Timer compare events.
754 */
755 HAL_SW_SWITCH_RADIO_ENABLE_PPI_REGISTER_EVT(phyend_delay_cc) = NRF_PPI_NONE;
756
757 nrf_timer_subscribe_clear(SW_SWITCH_TIMER,
758 nrf_timer_capture_task_get(phyend_delay_cc));
759
760 /* Disable CTEPRESENT event to disable EVENTS_COMPARE[<phyend_delay_cc_offs>] PPI channel */
761 nrf_dppi_channels_disable(NRF_DPPIC,
762 BIT(HAL_SW_SWITCH_TIMER_PHYEND_DELAY_COMPENSATION_DISABLE_PPI));
763 }
764 #endif /* CONFIG_BT_CTLR_DF_PHYEND_OFFSET_COMPENSATION_ENABLE */
765
766 #endif /* !CONFIG_BT_CTLR_TIFS_HW */
767