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