1 /*
2 * Copyright (c) 2020, Nordic Semiconductor ASA
3 * All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-3-Clause
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright notice, this
11 * list of conditions and the following disclaimer.
12 *
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
18 * contributors may be used to endorse or promote products derived from this
19 * software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
32 *
33 */
34
35 #define NRF_802154_MODULE_ID NRF_802154_DRV_MODULE_ID_TRX_PPI
36
37 #include "nrfx.h"
38
39 #ifdef NRF52_SERIES
40
41 #include "nrf_802154_trx_ppi_api.h"
42
43 #include <stdbool.h>
44
45 #include "nrf_802154_debug_log.h"
46 #include "nrf_802154_peripherals.h"
47
48 #include "protocol/mpsl_fem_protocol_api.h"
49
50 #include "hal/nrf_egu.h"
51 #include "hal/nrf_ppi.h"
52 #include "hal/nrf_radio.h"
53 #include "hal/nrf_timer.h"
54
55 #define EGU_EVENT NRF_802154_EGU_RAMP_UP_EVENT
56 #define EGU_TASK NRF_802154_EGU_RAMP_UP_TASK
57
58 #define PPI_CHGRP_RAMP_UP NRF_802154_PPI_CORE_GROUP ///< PPI group used to disable self-disabling PPIs
59 #define PPI_CHGRP_RAMP_UP_DIS_TASK NRF_PPI_TASK_CHG0_DIS ///< PPI task used to disable self-disabling PPIs
60
61 #define PPI_CHGRP_ABORT NRF_802154_PPI_ABORT_GROUP ///< PPI group used to disable PPIs when async event aborting radio operation is propagated through the system
62
63 #define PPI_DISABLED_EGU NRF_802154_PPI_RADIO_DISABLED_TO_EGU ///< PPI that connects RADIO DISABLED event with EGU task
64 #define PPI_RAMP_UP_TRG_EGU NRF_802154_PPI_RADIO_RAMP_UP_TRIGG ///< PPI that connects ramp up trigger event with EGU task
65 #define PPI_EGU_RAMP_UP NRF_802154_PPI_EGU_TO_RADIO_RAMP_UP ///< PPI that connects EGU event with RADIO TXEN or RXEN task
66 #define PPI_EGU_TIMER_START NRF_802154_PPI_EGU_TO_TIMER_START ///< PPI that connects EGU event with TIMER START task
67 #define PPI_TIMER_TX_ACK NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN ///< PPI that connects TIMER COMPARE event with RADIO TXEN task
68 #define PPI_RADIO_SYNC_EGU_SYNC NRF_802154_PPI_RADIO_SYNC_TO_EGU_SYNC ///< PPI that connects RADIO SYNC event with EGU task for SYNC channel
69
nrf_802154_trx_ppi_for_enable(void)70 void nrf_802154_trx_ppi_for_enable(void)
71 {
72 // Intentionally empty.
73 }
74
nrf_802154_trx_ppi_for_disable(void)75 void nrf_802154_trx_ppi_for_disable(void)
76 {
77 // Intentionally empty.
78 }
79
nrf_802154_trx_ppi_for_ramp_up_channel_id_get(void)80 uint8_t nrf_802154_trx_ppi_for_ramp_up_channel_id_get(void)
81 {
82 return PPI_RAMP_UP_TRG_EGU;
83 }
84
nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task,nrf_802154_trx_ramp_up_trigger_mode_t trigg_mode,bool start_timer)85 void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task,
86 nrf_802154_trx_ramp_up_trigger_mode_t trigg_mode,
87 bool start_timer)
88 {
89 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
90
91 // Clr event EGU (needed for nrf_802154_trx_ppi_for_ramp_up_was_triggered)
92 nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_EVENT);
93
94 uint32_t ppi_mask = (1UL << PPI_EGU_RAMP_UP) | (1UL << PPI_RAMP_UP_TRG_EGU);
95
96 nrf_ppi_channel_and_fork_endpoint_setup(NRF_PPI,
97 PPI_EGU_RAMP_UP,
98 nrf_egu_event_address_get(
99 NRF_802154_EGU_INSTANCE,
100 EGU_EVENT),
101 nrf_radio_task_address_get(NRF_RADIO, ramp_up_task),
102 nrf_ppi_task_address_get(NRF_PPI,
103 PPI_CHGRP_RAMP_UP_DIS_TASK));
104
105 if (start_timer)
106 {
107 nrf_ppi_channel_endpoint_setup(NRF_PPI,
108 PPI_EGU_TIMER_START,
109 nrf_egu_event_address_get(NRF_802154_EGU_INSTANCE,
110 EGU_EVENT),
111 nrf_timer_task_address_get(NRF_802154_TIMER_INSTANCE,
112 NRF_TIMER_TASK_START));
113
114 ppi_mask |= (1UL << PPI_EGU_TIMER_START);
115 }
116
117 if (trigg_mode == TRX_RAMP_UP_SW_TRIGGER)
118 {
119 nrf_ppi_channel_endpoint_setup(NRF_PPI,
120 PPI_RAMP_UP_TRG_EGU,
121 nrf_radio_event_address_get(NRF_RADIO,
122 NRF_RADIO_EVENT_DISABLED),
123 nrf_egu_task_address_get(NRF_802154_EGU_INSTANCE, EGU_TASK));
124 }
125 else
126 {
127 nrf_ppi_task_endpoint_setup(NRF_PPI,
128 PPI_RAMP_UP_TRG_EGU,
129 nrf_egu_task_address_get(NRF_802154_EGU_INSTANCE, EGU_TASK));
130 }
131
132 nrf_ppi_channel_include_in_group(NRF_PPI, PPI_EGU_RAMP_UP, PPI_CHGRP_RAMP_UP);
133
134 nrf_ppi_channels_enable(NRF_PPI, ppi_mask);
135
136 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
137 }
138
nrf_802154_trx_ppi_for_extra_cca_attempts_set(void)139 void nrf_802154_trx_ppi_for_extra_cca_attempts_set(void)
140 {
141 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
142
143 nrf_ppi_channel_endpoint_setup(NRF_PPI,
144 NRF_802154_PPI_RADIO_CCABUSY_TO_RADIO_CCASTART,
145 nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY),
146 nrf_radio_task_address_get(NRF_RADIO, NRF_RADIO_TASK_CCASTART));
147
148 nrf_ppi_channels_enable(NRF_PPI, 1UL << NRF_802154_PPI_RADIO_CCABUSY_TO_RADIO_CCASTART);
149
150 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
151 }
152
nrf_802154_trx_ppi_for_ramp_up_reconfigure(void)153 void nrf_802154_trx_ppi_for_ramp_up_reconfigure(void)
154 {
155 nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_EVENT);
156
157 nrf_ppi_channel_endpoint_setup(NRF_PPI,
158 PPI_DISABLED_EGU,
159 nrf_radio_event_address_get(NRF_RADIO,
160 NRF_RADIO_EVENT_DISABLED),
161 nrf_egu_task_address_get(NRF_802154_EGU_INSTANCE, EGU_TASK));
162 }
163
nrf_802154_trx_ppi_for_ramp_up_clear(nrf_radio_task_t ramp_up_task,bool start_timer)164 void nrf_802154_trx_ppi_for_ramp_up_clear(nrf_radio_task_t ramp_up_task, bool start_timer)
165 {
166 (void)ramp_up_task;
167 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
168
169 uint32_t ppi_mask = (1UL << PPI_EGU_RAMP_UP) |
170 (1UL << PPI_RAMP_UP_TRG_EGU);
171
172 if (start_timer)
173 {
174 ppi_mask |= (1UL << PPI_EGU_TIMER_START);
175 }
176
177 nrf_ppi_channels_disable(NRF_PPI, ppi_mask);
178 nrf_ppi_channel_and_fork_endpoint_setup(NRF_PPI, PPI_EGU_RAMP_UP, 0, 0, 0);
179 nrf_ppi_channel_endpoint_setup(NRF_PPI, PPI_RAMP_UP_TRG_EGU, 0, 0);
180
181 if (start_timer)
182 {
183 nrf_ppi_channel_endpoint_setup(NRF_PPI, PPI_EGU_TIMER_START, 0, 0);
184 }
185
186 nrf_ppi_channel_remove_from_group(NRF_PPI, PPI_EGU_RAMP_UP, PPI_CHGRP_RAMP_UP);
187
188 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
189 }
190
nrf_802154_trx_ppi_for_extra_cca_attempts_clear(void)191 void nrf_802154_trx_ppi_for_extra_cca_attempts_clear(void)
192 {
193 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
194
195 nrf_ppi_channel_disable(NRF_PPI, NRF_802154_PPI_RADIO_CCABUSY_TO_RADIO_CCASTART);
196 nrf_ppi_channel_endpoint_setup(NRF_PPI, NRF_802154_PPI_RADIO_CCABUSY_TO_RADIO_CCASTART, 0, 0);
197
198 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
199 }
200
nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait(void)201 void nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait(void)
202 {
203 __ASM("nop");
204 __ASM("nop");
205 __ASM("nop");
206 __ASM("nop");
207 __ASM("nop");
208 __ASM("nop");
209 }
210
nrf_802154_trx_ppi_for_ramp_up_was_triggered(void)211 bool nrf_802154_trx_ppi_for_ramp_up_was_triggered(void)
212 {
213 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
214
215 if (nrf_radio_state_get(NRF_RADIO) != NRF_RADIO_STATE_DISABLED)
216 {
217 // If RADIO state is not DISABLED, it means that RADIO is still ramping down or already
218 // started ramping up.
219 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
220 return true;
221 }
222
223 // Wait for PPIs
224 nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait();
225
226 if (nrf_egu_event_check(NRF_802154_EGU_INSTANCE, EGU_EVENT))
227 {
228 // If EGU event is set, procedure is running.
229 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
230 return true;
231 }
232
233 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
234 return false;
235 }
236
nrf_802154_trx_ppi_for_ack_tx_set(void)237 void nrf_802154_trx_ppi_for_ack_tx_set(void)
238 {
239 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
240
241 nrf_ppi_channel_endpoint_setup(NRF_PPI,
242 PPI_TIMER_TX_ACK,
243 nrf_timer_event_address_get(NRF_802154_TIMER_INSTANCE,
244 NRF_TIMER_EVENT_COMPARE1),
245 nrf_radio_task_address_get(NRF_RADIO,
246 NRF_RADIO_TASK_TXEN));
247 nrf_ppi_channel_enable(NRF_PPI, PPI_TIMER_TX_ACK);
248
249 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
250 }
251
nrf_802154_trx_ppi_for_ack_tx_clear(void)252 void nrf_802154_trx_ppi_for_ack_tx_clear(void)
253 {
254 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
255
256 nrf_ppi_channel_disable(NRF_PPI, PPI_TIMER_TX_ACK);
257 nrf_ppi_channel_endpoint_setup(NRF_PPI, PPI_TIMER_TX_ACK, 0, 0);
258
259 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
260 }
261
nrf_802154_trx_ppi_for_fem_set(void)262 void nrf_802154_trx_ppi_for_fem_set(void)
263 {
264 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
265
266 uint32_t event_addr = nrf_egu_event_address_get(NRF_802154_EGU_INSTANCE,
267 EGU_EVENT);
268 uint32_t task_addr = nrf_timer_task_address_get(NRF_802154_TIMER_INSTANCE,
269 NRF_TIMER_TASK_START);
270
271 nrf_ppi_channel_endpoint_setup(NRF_PPI, PPI_EGU_TIMER_START, event_addr, task_addr);
272 nrf_ppi_channel_enable(NRF_PPI, PPI_EGU_TIMER_START);
273
274 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
275 }
276
nrf_802154_trx_ppi_for_fem_clear(void)277 void nrf_802154_trx_ppi_for_fem_clear(void)
278 {
279 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
280
281 nrf_ppi_channel_disable(NRF_PPI, PPI_EGU_TIMER_START);
282 nrf_ppi_channel_endpoint_setup(NRF_PPI, PPI_EGU_TIMER_START, 0, 0);
283
284 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
285 }
286
nrf_802154_trx_ppi_group_for_abort_get(void)287 uint32_t nrf_802154_trx_ppi_group_for_abort_get(void)
288 {
289 return (uint32_t)PPI_CHGRP_ABORT;
290 }
291
292 #if defined(RADIO_INTENSET_SYNC_Msk)
nrf_802154_trx_ppi_for_radio_sync_set(nrf_egu_task_t task)293 void nrf_802154_trx_ppi_for_radio_sync_set(nrf_egu_task_t task)
294 {
295 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
296
297 nrf_ppi_channel_endpoint_setup(NRF_PPI,
298 PPI_RADIO_SYNC_EGU_SYNC,
299 nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_SYNC),
300 nrf_egu_task_address_get(NRF_802154_EGU_INSTANCE, task));
301 nrf_ppi_channel_enable(NRF_PPI, PPI_RADIO_SYNC_EGU_SYNC);
302
303 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
304 }
305
nrf_802154_trx_ppi_for_radio_sync_clear(nrf_egu_task_t task)306 void nrf_802154_trx_ppi_for_radio_sync_clear(nrf_egu_task_t task)
307 {
308 (void)task;
309 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
310
311 nrf_ppi_channel_disable(NRF_PPI, PPI_RADIO_SYNC_EGU_SYNC);
312 nrf_ppi_channel_endpoint_setup(NRF_PPI, PPI_RADIO_SYNC_EGU_SYNC, 0, 0);
313
314 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
315 }
316
317 #endif
318
319 #endif // NRF52_SERIES
320