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 #if defined(DPPI_PRESENT)
40
41 #include "nrf_802154_trx_ppi_api.h"
42
43 #include "nrf_802154_debug_log.h"
44 #include "nrf_802154_peripherals.h"
45
46 #include "hal/nrf_dppi.h"
47 #include "hal/nrf_egu.h"
48 #include "hal/nrf_radio.h"
49 #include "hal/nrf_timer.h"
50
51 #define EGU_EVENT NRF_802154_EGU_RAMP_UP_EVENT
52 #define EGU_TASK NRF_802154_EGU_RAMP_UP_TASK
53
54 #define DPPI_CHGRP_RAMP_UP NRF_DPPI_CHANNEL_GROUP0 ///< PPI group used to disable self-disabling PPIs
55 #define DPPI_CHGRP_RAMP_UP_DIS_TASK NRF_DPPI_TASK_CHG0_DIS ///< PPI task used to disable self-disabling PPIs
56
57 #define PPI_DISABLED_EGU NRF_802154_DPPI_RADIO_DISABLED
58 #define PPI_EGU_RAMP_UP NRF_802154_DPPI_EGU_TO_RADIO_RAMP_UP
59 #define PPI_TIMER_TX_ACK NRF_802154_DPPI_TIMER_COMPARE_TO_RADIO_TXEN
60 #define PPI_RADIO_SYNC_EGU_SYNC NRF_802154_DPPI_RADIO_SYNC_TO_EGU_SYNC
61
nrf_802154_trx_ppi_for_enable(void)62 void nrf_802154_trx_ppi_for_enable(void)
63 {
64 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_DISABLED, PPI_DISABLED_EGU);
65 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_READY, NRF_802154_DPPI_RADIO_READY);
66 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS, NRF_802154_DPPI_RADIO_ADDRESS);
67 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_END, NRF_802154_DPPI_RADIO_END);
68 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_PHYEND, NRF_802154_DPPI_RADIO_PHYEND);
69 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE, NRF_802154_DPPI_RADIO_CCAIDLE);
70 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY, NRF_802154_DPPI_RADIO_CCABUSY);
71
72 nrf_dppi_channels_enable(NRF_802154_DPPIC_INSTANCE,
73 (1UL << NRF_802154_DPPI_RADIO_CCABUSY) |
74 (1UL << PPI_DISABLED_EGU) |
75 (1UL << NRF_802154_DPPI_RADIO_READY) |
76 (1UL << NRF_802154_DPPI_RADIO_ADDRESS) |
77 (1UL << NRF_802154_DPPI_RADIO_END) |
78 (1UL << NRF_802154_DPPI_RADIO_PHYEND) |
79 (1UL << NRF_802154_DPPI_RADIO_CCAIDLE) |
80 (1UL << NRF_802154_DPPI_RADIO_HW_TRIGGER));
81 }
82
nrf_802154_trx_ppi_for_disable(void)83 void nrf_802154_trx_ppi_for_disable(void)
84 {
85 nrf_dppi_channels_disable(NRF_802154_DPPIC_INSTANCE,
86 (1UL << NRF_802154_DPPI_RADIO_CCABUSY) |
87 (1UL << PPI_DISABLED_EGU) |
88 (1UL << NRF_802154_DPPI_RADIO_READY) |
89 (1UL << NRF_802154_DPPI_RADIO_ADDRESS) |
90 (1UL << NRF_802154_DPPI_RADIO_END) |
91 (1UL << NRF_802154_DPPI_RADIO_PHYEND) |
92 (1UL << NRF_802154_DPPI_RADIO_CCAIDLE) |
93 (1UL << NRF_802154_DPPI_RADIO_HW_TRIGGER));
94
95 #if NRF_802154_TEST_MODES_ENABLED
96 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY);
97 #endif // NRF_802154_TEST_MODES_ENABLED
98 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE);
99 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND);
100 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_END);
101 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
102 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
103 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
104 }
105
nrf_802154_trx_ppi_for_ramp_up_channel_id_get(void)106 uint8_t nrf_802154_trx_ppi_for_ramp_up_channel_id_get(void)
107 {
108 return NRF_802154_DPPI_RADIO_HW_TRIGGER;
109 }
110
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)111 void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task,
112 nrf_802154_trx_ramp_up_trigger_mode_t trigg_mode,
113 bool start_timer)
114 {
115 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
116
117 // Clr event EGU (needed for nrf_802154_trx_ppi_for_ramp_up_was_triggered)
118 nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_EVENT);
119
120 nrf_dppi_channels_include_in_group(NRF_802154_DPPIC_INSTANCE,
121 1UL << PPI_EGU_RAMP_UP,
122 DPPI_CHGRP_RAMP_UP);
123
124 nrf_radio_subscribe_set(NRF_RADIO, ramp_up_task, PPI_EGU_RAMP_UP);
125 nrf_dppi_subscribe_set(NRF_802154_DPPIC_INSTANCE, DPPI_CHGRP_RAMP_UP_DIS_TASK, PPI_EGU_RAMP_UP);
126
127 if (start_timer)
128 {
129 nrf_timer_subscribe_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_START, PPI_DISABLED_EGU);
130 }
131
132 nrf_egu_publish_set(NRF_802154_EGU_INSTANCE, EGU_EVENT, PPI_EGU_RAMP_UP);
133
134 nrf_egu_subscribe_set(NRF_802154_EGU_INSTANCE, EGU_TASK, PPI_DISABLED_EGU);
135
136 nrf_dppi_channels_enable(NRF_802154_DPPIC_INSTANCE,
137 (1UL << PPI_EGU_RAMP_UP));
138
139 if (trigg_mode == TRX_RAMP_UP_HW_TRIGGER)
140 {
141 nrf_radio_subscribe_set(NRF_RADIO,
142 NRF_RADIO_TASK_DISABLE,
143 NRF_802154_DPPI_RADIO_HW_TRIGGER);
144 }
145
146 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
147 }
148
nrf_802154_trx_ppi_for_extra_cca_attempts_set(void)149 void nrf_802154_trx_ppi_for_extra_cca_attempts_set(void)
150 {
151 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
152
153 // Assume that NRF_802154_DPPI_RADIO_CCABUSY is enabled and NRF_RADIO_EVENT_CCABUSY publishes to it
154 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_CCASTART, NRF_802154_DPPI_RADIO_CCABUSY);
155
156 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
157 }
158
nrf_802154_trx_ppi_for_ramp_up_reconfigure(void)159 void nrf_802154_trx_ppi_for_ramp_up_reconfigure(void)
160 {
161 // Intentionally empty
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 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
167
168 nrf_dppi_channels_disable(NRF_802154_DPPIC_INSTANCE,
169 (1UL << PPI_EGU_RAMP_UP));
170
171 nrf_egu_publish_clear(NRF_802154_EGU_INSTANCE, EGU_EVENT);
172 nrf_radio_subscribe_clear(NRF_RADIO, ramp_up_task);
173 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
174 nrf_dppi_subscribe_clear(NRF_802154_DPPIC_INSTANCE, DPPI_CHGRP_RAMP_UP_DIS_TASK);
175 nrf_dppi_channels_remove_from_group(NRF_802154_DPPIC_INSTANCE,
176 1UL << PPI_EGU_RAMP_UP,
177 DPPI_CHGRP_RAMP_UP);
178
179 if (start_timer)
180 {
181 nrf_timer_subscribe_clear(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_START);
182 }
183
184 nrf_egu_subscribe_clear(NRF_802154_EGU_INSTANCE, EGU_TASK);
185
186 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
187 }
188
nrf_802154_trx_ppi_for_extra_cca_attempts_clear(void)189 void nrf_802154_trx_ppi_for_extra_cca_attempts_clear(void)
190 {
191 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
192
193 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_CCASTART);
194
195 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
196 }
197
nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait(void)198 void nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait(void)
199 {
200 __ASM("nop");
201 __ASM("nop");
202 __ASM("nop");
203 __ASM("nop");
204 __ASM("nop");
205 __ASM("nop");
206 }
207
nrf_802154_trx_ppi_for_ramp_up_was_triggered(void)208 bool nrf_802154_trx_ppi_for_ramp_up_was_triggered(void)
209 {
210 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
211
212 if (nrf_radio_state_get(NRF_RADIO) != NRF_RADIO_STATE_DISABLED)
213 {
214 // If RADIO state is not DISABLED, it means that RADIO is still ramping down or already
215 // started ramping up.
216 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
217 return true;
218 }
219
220 // Wait for PPIs
221 nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait();
222
223 if (nrf_egu_event_check(NRF_802154_EGU_INSTANCE, EGU_EVENT))
224 {
225 // If EGU event is set, procedure is running.
226 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
227 return true;
228 }
229
230 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
231 return false;
232 }
233
nrf_802154_trx_ppi_for_ack_tx_set(void)234 void nrf_802154_trx_ppi_for_ack_tx_set(void)
235 {
236 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
237
238 // TIMER_COMPARE1 ----> RADIO_TXEN
239 nrf_radio_subscribe_set(NRF_RADIO, NRF_RADIO_TASK_TXEN, PPI_TIMER_TX_ACK);
240 nrf_timer_publish_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE1, PPI_TIMER_TX_ACK);
241
242 nrf_dppi_channels_enable(NRF_802154_DPPIC_INSTANCE, (1UL << PPI_TIMER_TX_ACK));
243
244 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
245 }
246
nrf_802154_trx_ppi_for_ack_tx_clear(void)247 void nrf_802154_trx_ppi_for_ack_tx_clear(void)
248 {
249 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
250
251 nrf_dppi_channels_disable(NRF_802154_DPPIC_INSTANCE, (1UL << PPI_TIMER_TX_ACK));
252
253 nrf_radio_subscribe_clear(NRF_RADIO, NRF_RADIO_TASK_TXEN);
254 nrf_timer_publish_clear(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE1);
255
256 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
257 }
258
nrf_802154_trx_ppi_for_fem_set(void)259 void nrf_802154_trx_ppi_for_fem_set(void)
260 {
261 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
262
263 nrf_timer_subscribe_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_START, PPI_DISABLED_EGU);
264
265 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
266 }
267
nrf_802154_trx_ppi_for_fem_clear(void)268 void nrf_802154_trx_ppi_for_fem_clear(void)
269 {
270 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
271
272 nrf_timer_subscribe_clear(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_START);
273
274 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
275 }
276
nrf_802154_trx_ppi_group_for_abort_get(void)277 uint32_t nrf_802154_trx_ppi_group_for_abort_get(void)
278 {
279 // TODO: Implement it when external event (like coex) can abort radio operation
280 return 0;
281 }
282
283 #if defined(RADIO_INTENSET_SYNC_Msk)
nrf_802154_trx_ppi_for_radio_sync_set(nrf_egu_task_t task)284 void nrf_802154_trx_ppi_for_radio_sync_set(nrf_egu_task_t task)
285 {
286 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
287
288 nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_SYNC, PPI_RADIO_SYNC_EGU_SYNC);
289 nrf_egu_subscribe_set(NRF_802154_EGU_INSTANCE, task, PPI_RADIO_SYNC_EGU_SYNC);
290 nrf_dppi_channels_enable(NRF_802154_DPPIC_INSTANCE, (1UL << PPI_RADIO_SYNC_EGU_SYNC));
291
292 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
293 }
294
nrf_802154_trx_ppi_for_radio_sync_clear(nrf_egu_task_t task)295 void nrf_802154_trx_ppi_for_radio_sync_clear(nrf_egu_task_t task)
296 {
297 nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
298
299 nrf_dppi_channels_disable(NRF_802154_DPPIC_INSTANCE, (1UL << PPI_RADIO_SYNC_EGU_SYNC));
300 nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_SYNC);
301 nrf_egu_subscribe_clear(NRF_802154_EGU_INSTANCE, task);
302
303 nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
304 }
305
306 #endif
307
308 #endif // defined(DPPI_PRESENT)
309