1 /*
2  * Copyright (c) 2019, 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
36 
37 #include "nrf_802154_trx.h"
38 
39 #include "nrf_802154_assert.h"
40 #include <string.h>
41 
42 #include "nrf_802154_config.h"
43 #include "nrf_802154_const.h"
44 #include "nrf_802154_peripherals.h"
45 #include "nrf_802154_pib.h"
46 #include "nrf_802154_rssi.h"
47 #include "nrf_802154_swi.h"
48 #include "nrf_802154_trx_ppi_api.h"
49 #include "nrf_802154_utils.h"
50 
51 #include "hal/nrf_egu.h"
52 #include "hal/nrf_radio.h"
53 #include "hal/nrf_timer.h"
54 #if defined(NRF53_SERIES)
55 #include "hal/nrf_vreqctrl.h"
56 #endif
57 
58 #include "nrf_802154_procedures_duration.h"
59 #include "nrf_802154_critical_section.h"
60 #include "mpsl_fem_config_common.h"
61 #include "mpsl_tx_power.h"
62 #include "platform/nrf_802154_irq.h"
63 #include "protocol/mpsl_fem_protocol_api.h"
64 
65 #include "nrf_802154_sl_ant_div.h"
66 
67 #ifdef NRF_802154_USE_INTERNAL_INCLUDES
68 #include "nrf_802154_trx_internal.h"
69 #endif
70 
71 #define EGU_SYNC_EVENT        NRFX_CONCAT_2(NRF_EGU_EVENT_TRIGGERED, NRF_802154_EGU_SYNC_CHANNEL_NO)
72 #define EGU_SYNC_TASK         NRFX_CONCAT_2(NRF_EGU_TASK_TRIGGER, NRF_802154_EGU_SYNC_CHANNEL_NO)
73 #define EGU_SYNC_INTMASK      NRFX_CONCAT_2(NRF_EGU_INT_TRIGGERED, NRF_802154_EGU_SYNC_CHANNEL_NO)
74 
75 #define RADIO_BASE            ((uintptr_t)NRF_RADIO)
76 
77 #if defined(DPPI_PRESENT)
78 #define FICR_BASE             NRF_FICR_NS_BASE
79 #else
80 #define PPI_CCAIDLE_FEM       NRF_802154_PPI_RADIO_CCAIDLE_TO_FEM_GPIOTE ///< PPI that connects RADIO CCAIDLE event with GPIOTE tasks used by FEM
81 #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
82 #endif
83 
84 #define SHORT_ADDRESS_BCSTART NRF_RADIO_SHORT_ADDRESS_BCSTART_MASK
85 
86 /// Value set to SHORTS register when no shorts should be enabled.
87 #define SHORTS_IDLE           0
88 
89 /// Value set to SHORTS register for RX operation.
90 #if !defined(NRF52_SERIES)
91 #define SHORTS_RX             (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \
92                                NRF_RADIO_SHORT_PHYEND_DISABLE_MASK |    \
93                                SHORT_ADDRESS_BCSTART)
94 #else
95 #define SHORTS_RX             (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \
96                                NRF_RADIO_SHORT_END_DISABLE_MASK |       \
97                                SHORT_ADDRESS_BCSTART)
98 #endif
99 
100 #define SHORTS_RX_FREE_BUFFER (NRF_RADIO_SHORT_RXREADY_START_MASK)
101 
102 #define SHORTS_TX_ACK         (NRF_RADIO_SHORT_TXREADY_START_MASK | \
103                                NRF_RADIO_SHORT_PHYEND_DISABLE_MASK)
104 
105 #define SHORTS_MULTI_CCA_TX   (NRF_RADIO_SHORT_RXREADY_CCASTART_MASK | \
106                                NRF_RADIO_SHORT_CCAIDLE_TXEN_MASK |     \
107                                NRF_RADIO_SHORT_TXREADY_START_MASK |    \
108                                NRF_RADIO_SHORT_PHYEND_DISABLE_MASK)
109 
110 #define SHORTS_CCA_TX         (NRF_RADIO_SHORT_RXREADY_CCASTART_MASK | \
111                                NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK |  \
112                                NRF_RADIO_SHORT_CCAIDLE_TXEN_MASK |     \
113                                NRF_RADIO_SHORT_TXREADY_START_MASK |    \
114                                NRF_RADIO_SHORT_PHYEND_DISABLE_MASK)
115 
116 #define SHORTS_TX             (NRF_RADIO_SHORT_TXREADY_START_MASK | \
117                                NRF_RADIO_SHORT_PHYEND_DISABLE_MASK)
118 
119 #if !defined(NRF52_SERIES)
120 #define SHORTS_RX_ACK         (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \
121                                NRF_RADIO_SHORT_PHYEND_DISABLE_MASK)
122 #else
123 #define SHORTS_RX_ACK         (NRF_RADIO_SHORT_ADDRESS_RSSISTART_MASK | \
124                                NRF_RADIO_SHORT_END_DISABLE_MASK)
125 
126 #endif
127 
128 #define SHORTS_MOD_CARRIER  (NRF_RADIO_SHORT_TXREADY_START_MASK | \
129                              NRF_RADIO_SHORT_PHYEND_START_MASK)
130 
131 #define SHORTS_ED           (NRF_RADIO_SHORT_READY_EDSTART_MASK)
132 
133 #define SHORTS_CCA          (NRF_RADIO_SHORT_RXREADY_CCASTART_MASK | \
134                              NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK)
135 
136 #define CRC_LENGTH          2                                    ///< Length of CRC in 802.15.4 frames [bytes]
137 #define CRC_POLYNOMIAL      0x011021                             ///< Polynomial used for CRC calculation in 802.15.4 frames
138 
139 #define TXRU_TIME           40                                   ///< Transmitter ramp up time [us]
140 #define EVENT_LAT           23                                   ///< END event latency [us]
141 
142 #if !defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
143 #define MAX_RAMPDOWN_CYCLES (50 * (SystemCoreClock / 1000000UL)) ///< Maximum number of busy wait loop cycles that radio ramp-down is allowed to take
144 #else
145 #define MAX_RAMPDOWN_CYCLES 20
146 #endif
147 #define RSSI_SETTLE_TIME_US 15           ///< Time required for RSSI measurements to become valid after signal level change.
148 
149 #if NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
150 void nrf_802154_radio_irq_handler(void); ///< Prototype required by internal RADIO IRQ handler
151 #endif  // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
152 
153 #ifndef NRF_802154_TRX_ENABLE_INTERNAL
154 #define NRF_802154_TRX_ENABLE_INTERNAL() \
155     do                                   \
156     {                                    \
157     }                                    \
158     while (0)
159 #endif
160 
161 #ifndef NRF_802154_TRX_RADIO_RESET_INTERNAL
162 #define NRF_802154_TRX_RADIO_RESET_INTERNAL() \
163     do                                        \
164     {                                         \
165     }                                         \
166     while (0)
167 #endif
168 
169 #ifndef NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK
170 #define NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK 0
171 #endif
172 
173 #if !defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
174 /// System Clock Frequency (Core Clock) provided by nrfx.
175 extern uint32_t SystemCoreClock;
176 
177 #endif
178 
179 #if defined(NRF54L_SERIES)
180 /// Flag that informs if the disable operation had to be repeated forcefully since the last trx enable.
181 static volatile bool g_nrf_802154_trx_disable_repeat_was_needed;
182 /// Increments whenever repeating disable operation forcefully happens.
183 static uint16_t g_nrf_802154_trx_disable_repeat_counter;
184 
185 #endif
186 
187 /// Common parameters for the FEM handling.
188 static const mpsl_fem_event_t m_activate_rx_cc0 =
189 {
190     .type        = MPSL_FEM_EVENT_TYPE_TIMER,
191     .event.timer =
192     {
193         .p_timer_instance     = NRF_802154_TIMER_INSTANCE,
194         .compare_channel_mask = ((1 << NRF_TIMER_CC_CHANNEL0) | (1 << NRF_TIMER_CC_CHANNEL2)),
195         .counter_period       = {
196             .end = RX_RAMP_UP_TIME
197         },
198     },
199 };
200 
201 static const mpsl_fem_event_t m_activate_tx_cc0 =
202 {
203     .type        = MPSL_FEM_EVENT_TYPE_TIMER,
204     .event.timer =
205     {
206         .p_timer_instance     = NRF_802154_TIMER_INSTANCE,
207         .compare_channel_mask = ((1 << NRF_TIMER_CC_CHANNEL0) | (1 << NRF_TIMER_CC_CHANNEL2)),
208         .counter_period       = {
209             .end = TX_RAMP_UP_TIME
210         },
211     },
212 };
213 
214 static const mpsl_fem_event_t m_ccaidle =
215 {
216     .type = MPSL_FEM_EVENT_TYPE_GENERIC,
217 #if defined(DPPI_PRESENT)
218     .event.generic.event = NRF_802154_DPPI_RADIO_CCAIDLE
219 #else
220     .override_ppi        = true,
221     .ppi_ch_id           = PPI_CCAIDLE_FEM,
222     .event.generic.event = ((uint32_t)RADIO_BASE + (uint32_t)NRF_RADIO_EVENT_CCAIDLE)
223 #endif
224 };
225 
226 /**@brief Fal event used by @ref nrf_802154_trx_transmit_ack and @ref txack_finish */
227 static mpsl_fem_event_t m_activate_tx_cc0_timeshifted;
228 
229 static volatile trx_state_t m_trx_state;
230 
231 typedef struct
232 {
233     bool          psdu_being_received;    ///< If PSDU is currently being received.
234     bool          missing_receive_buffer; ///!< If trx entered receive state without receive buffer
235     bool          rxstarted_notif_en;
236     bool          ccastarted_notif_en;
237     bool          tx_started;             ///< If the requested transmission has started.
238     bool          rssi_started;
239     volatile bool rssi_settled;
240 } nrf_802154_flags_t;
241 
242 static nrf_802154_flags_t m_flags; ///< Flags used to store the current driver state.
243 
244 /** @brief Value of TIMER internal counter from which the counting is resumed on RADIO.EVENTS_END event. */
245 static volatile uint32_t m_timer_value_on_radio_end_event;
246 static volatile bool     m_transmit_with_cca;
247 static volatile uint8_t  m_remaining_cca_attempts;
248 
249 static void timer_frequency_set_1mhz(void);
250 
251 static void rxframe_finish_disable_ppis(void);
252 static void rxack_finish_disable_ppis(void);
253 static void txframe_finish_disable_ppis(bool cca);
254 
255 static void go_idle_abort(void);
256 static void receive_frame_abort(void);
257 static void receive_ack_abort(void);
258 static void transmit_frame_abort(void);
259 static void transmit_ack_abort(void);
260 static void standalone_cca_abort(void);
261 
262 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
263 static void continuous_carrier_abort(void);
264 static void modulated_carrier_abort(void);
265 
266 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
267 static void energy_detection_abort(void);
268 
269 /** Clear flags describing frame being received. */
rx_flags_clear(void)270 static void rx_flags_clear(void)
271 {
272     m_flags.missing_receive_buffer = false;
273     m_flags.psdu_being_received    = false;
274 }
275 
276 static void * volatile mp_receive_buffer;
277 
278 /** Force the TIMER to be stopped and count from 0. */
timer_stop_and_clear(void)279 static inline void timer_stop_and_clear(void)
280 {
281 #ifdef NRF52_SERIES
282     // Anomaly 78: use SHUTDOWN instead of STOP.
283     nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN);
284 #else
285     nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_STOP);
286     nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_CLEAR);
287 #endif
288 }
289 
txpower_set(int8_t txpower)290 static void txpower_set(int8_t txpower)
291 {
292 #ifdef NRF53_SERIES
293     bool radio_high_voltage_enable = false;
294 
295     if (txpower > 0)
296     {
297         /* To get higher than 0dBm raise operating voltage of the radio, giving 3dBm power boost */
298         radio_high_voltage_enable = true;
299     }
300     nrf_vreqctrl_radio_high_voltage_set(NRF_VREQCTRL_NS, radio_high_voltage_enable);
301 #endif
302     uint32_t reg = mpsl_tx_power_dbm_to_radio_register_convert(txpower);
303 
304     nrf_radio_txpower_set(NRF_RADIO, reg);
305 }
306 
307 /** Initialize TIMER peripheral used by the driver. */
nrf_timer_init(void)308 static void nrf_timer_init(void)
309 {
310     timer_stop_and_clear();
311     nrf_timer_mode_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_MODE_TIMER);
312     nrf_timer_bit_width_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_BIT_WIDTH_32);
313     timer_frequency_set_1mhz();
314 }
315 
316 #if defined(NRF53_SERIES)
317 /** Implement the YOPAN-158 workaround. */
yopan_158_workaround(void)318 static void yopan_158_workaround(void)
319 {
320 #define RADIO_ADDRESS_MASK        0xFFFFF000UL
321 #define FICR_TRIM_REGISTERS_COUNT 32UL
322     /* This is a workaround for an issue reported in YOPAN-158.
323      *
324      * After RADIO peripheral reset with RADIO.POWER register the trim-values, loaded from FICR at
325      * network core boot time by MDK, are lost. The trim-values are not preserved and re-applied by
326      * hardware.
327      *
328      * Only selected trim-values are restored, those that apply to RADIO peripheral. The check
329      * is done based on destination address.
330      */
331 
332     /* Copy all the trimming values from FICR into the target addresses. Trim until one ADDR
333        is not initialized. */
334     for (uint32_t index = 0; index < FICR_TRIM_REGISTERS_COUNT; index++)
335     {
336         if (((volatile uint32_t *)((volatile uintptr_t)NRF_FICR_NS->TRIMCNF[index].ADDR &
337                                    (uintptr_t)RADIO_ADDRESS_MASK) == (uint32_t *)NRF_RADIO))
338         {
339             *((volatile uint32_t *)NRF_FICR_NS->TRIMCNF[index].ADDR) =
340                 NRF_FICR_NS->TRIMCNF[index].DATA;
341         }
342     }
343 }
344 
345 #endif /* NRF53_SERIES */
346 
347 /** Sets the frequency of 1 MHz for NRF_802154_TIMER_INSTANCE. */
timer_frequency_set_1mhz(void)348 static void timer_frequency_set_1mhz(void)
349 {
350     uint32_t base_frequency = NRF_TIMER_BASE_FREQUENCY_GET(NRF_802154_TIMER_INSTANCE);
351     uint32_t prescaler      = NRF_TIMER_PRESCALER_CALCULATE(base_frequency, 1000000);
352 
353     nrf_timer_prescaler_set(NRF_802154_TIMER_INSTANCE, prescaler);
354 }
355 
356 /** Disables the radio no matter its state. */
radio_force_disable(void)357 static void radio_force_disable(void)
358 {
359     /* Radio cannot be disabled if EVENT_DISABLED is set. Clear it first. */
360     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
361     nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
362 }
363 
364 /** Robustly disable the radio peripheral based on the radio state. */
radio_robust_disable(void)365 static void radio_robust_disable(void)
366 {
367     nrf_radio_state_t radio_state = nrf_radio_state_get(NRF_RADIO);
368 
369     if ((radio_state == NRF_RADIO_STATE_RXDISABLE) || (radio_state == NRF_RADIO_STATE_TXDISABLE))
370     {
371         /* RADIO is in an unstable state that should resolve to DISABLED. Do nothing. */
372     }
373     else
374     {
375         /* RADIO is in a stable state and needs to be transitioned to DISABLED manually. */
376         radio_force_disable();
377     }
378 }
379 
wait_until_radio_is_disabled(void)380 static inline void wait_until_radio_is_disabled(void)
381 {
382     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
383 
384     bool radio_is_disabled = false;
385     bool repeat            = false;
386 
387 #if defined(NRF54L_SERIES)
388     g_nrf_802154_trx_disable_repeat_was_needed = false;
389 #endif
390 
391     do
392     {
393         /* RADIO should enter DISABLED state after no longer than RX ramp-down time or TX ramp-down
394          * time, depending on its initial state before TASK_DISABLE was triggered. The loop below busy
395          * waits for the state transition to complete. To prevent the CPU from spinning in an endless
396          * loop, the maximum allowed number of loop cycles is limited. The limit's intention is not to
397          * approximate the expected maximum time the transition might actually take, which is generally
398          * very short, but to act as a safeguard against obviously incorrect and unexpected behaviors.
399          * In practice, in most cases the radio will have already changed state to DISABLED before this
400          * function starts. In the remaining cases several cycles of the loop should be sufficient for
401          * the transition to complete.
402          */
403         for (uint32_t i = 0; i < MAX_RAMPDOWN_CYCLES; i++)
404         {
405             if (nrf_radio_state_get(NRF_RADIO) == NRF_RADIO_STATE_DISABLED)
406             {
407                 radio_is_disabled = true;
408                 break;
409             }
410     #if defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
411             nrf_802154_delay_us(1);
412             /* In this simulated board, and in general in the POSIX ARCH,
413              * code takes 0 simulated time to execute.
414              * Let's hold for 1 microsecond to allow the RADIO HW to clear the state
415              */
416     #endif
417         }
418 
419 #ifdef NRF54L_SERIES
420         if (!radio_is_disabled && !repeat)
421         {
422             /* Radio still not in disabled state.
423              * Manually disable the radio and repeat the loop once as a last resort.
424              */
425             radio_force_disable();
426             repeat = true;
427             g_nrf_802154_trx_disable_repeat_was_needed = true;
428             g_nrf_802154_trx_disable_repeat_counter++;
429         }
430         else
431         {
432             break;
433         }
434 #endif
435     }
436     while (repeat);
437 
438     NRF_802154_ASSERT(radio_is_disabled);
439     (void)radio_is_disabled;
440 
441     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
442 }
443 
444 #if !defined(RADIO_POWER_POWER_Msk)
radio_reset_without_power_reg(void)445 static inline void radio_reset_without_power_reg(void)
446 {
447     /* SUBSCRIBE registers */
448     NRF_RADIO->SUBSCRIBE_TXEN      = 0;
449     NRF_RADIO->SUBSCRIBE_RXEN      = 0;
450     NRF_RADIO->SUBSCRIBE_START     = 0;
451     NRF_RADIO->SUBSCRIBE_STOP      = 0;
452     NRF_RADIO->SUBSCRIBE_DISABLE   = 0;
453     NRF_RADIO->SUBSCRIBE_RSSISTART = 0;
454     NRF_RADIO->SUBSCRIBE_BCSTART   = 0;
455     NRF_RADIO->SUBSCRIBE_BCSTOP    = 0;
456     NRF_RADIO->SUBSCRIBE_EDSTART   = 0;
457     NRF_RADIO->SUBSCRIBE_EDSTOP    = 0;
458     NRF_RADIO->SUBSCRIBE_CCASTART  = 0;
459     NRF_RADIO->SUBSCRIBE_CCASTOP   = 0;
460 
461     /* EVENT registers */
462     NRF_RADIO->EVENTS_READY      = 0;
463     NRF_RADIO->EVENTS_ADDRESS    = 0;
464     NRF_RADIO->EVENTS_PAYLOAD    = 0;
465     NRF_RADIO->EVENTS_END        = 0;
466     NRF_RADIO->EVENTS_DISABLED   = 0;
467     NRF_RADIO->EVENTS_DEVMATCH   = 0;
468     NRF_RADIO->EVENTS_DEVMISS    = 0;
469     NRF_RADIO->EVENTS_BCMATCH    = 0;
470     NRF_RADIO->EVENTS_CRCOK      = 0;
471     NRF_RADIO->EVENTS_CRCERROR   = 0;
472     NRF_RADIO->EVENTS_FRAMESTART = 0;
473     NRF_RADIO->EVENTS_EDEND      = 0;
474     NRF_RADIO->EVENTS_EDSTOPPED  = 0;
475     NRF_RADIO->EVENTS_CCAIDLE    = 0;
476     NRF_RADIO->EVENTS_CCABUSY    = 0;
477     NRF_RADIO->EVENTS_CCASTOPPED = 0;
478     NRF_RADIO->EVENTS_RATEBOOST  = 0;
479     NRF_RADIO->EVENTS_TXREADY    = 0;
480     NRF_RADIO->EVENTS_RXREADY    = 0;
481     NRF_RADIO->EVENTS_MHRMATCH   = 0;
482     NRF_RADIO->EVENTS_PHYEND     = 0;
483     NRF_RADIO->EVENTS_CTEPRESENT = 0;
484 
485     /* PUBLISH registers */
486     NRF_RADIO->PUBLISH_READY      = 0;
487     NRF_RADIO->PUBLISH_ADDRESS    = 0;
488     NRF_RADIO->PUBLISH_PAYLOAD    = 0;
489     NRF_RADIO->PUBLISH_END        = 0;
490     NRF_RADIO->PUBLISH_DISABLED   = 0;
491     NRF_RADIO->PUBLISH_DEVMATCH   = 0;
492     NRF_RADIO->PUBLISH_DEVMISS    = 0;
493     NRF_RADIO->PUBLISH_BCMATCH    = 0;
494     NRF_RADIO->PUBLISH_CRCOK      = 0;
495     NRF_RADIO->PUBLISH_CRCERROR   = 0;
496     NRF_RADIO->PUBLISH_FRAMESTART = 0;
497     NRF_RADIO->PUBLISH_EDEND      = 0;
498     NRF_RADIO->PUBLISH_EDSTOPPED  = 0;
499     NRF_RADIO->PUBLISH_CCAIDLE    = 0;
500     NRF_RADIO->PUBLISH_CCABUSY    = 0;
501     NRF_RADIO->PUBLISH_CCASTOPPED = 0;
502     NRF_RADIO->PUBLISH_RATEBOOST  = 0;
503     NRF_RADIO->PUBLISH_TXREADY    = 0;
504     NRF_RADIO->PUBLISH_RXREADY    = 0;
505     NRF_RADIO->PUBLISH_MHRMATCH   = 0;
506     NRF_RADIO->PUBLISH_PHYEND     = 0;
507     NRF_RADIO->PUBLISH_CTEPRESENT = 0;
508 
509     /* INTEN registers */
510     NRF_RADIO->INTENSET00 = 0;
511     NRF_RADIO->INTENCLR00 = 0xffffffff;
512 
513 #if !defined(NRF54H20_ENGA_XXAA)
514     NRF_RADIO->TASKS_SOFTRESET = 1;
515 #else /* defined(NRF54H20_ENGA_XXAA) */
516     NRF_RADIO->TASKS_TXEN       = 0;
517     NRF_RADIO->TASKS_RXEN       = 0;
518     NRF_RADIO->TASKS_START      = 0;
519     NRF_RADIO->TASKS_STOP       = 0;
520     NRF_RADIO->TASKS_DISABLE    = 0;
521     NRF_RADIO->TASKS_RSSISTART  = 0;
522     NRF_RADIO->TASKS_BCSTART    = 0;
523     NRF_RADIO->TASKS_BCSTOP     = 0;
524     NRF_RADIO->TASKS_EDSTART    = 0;
525     NRF_RADIO->TASKS_EDSTOP     = 0;
526     NRF_RADIO->TASKS_CCASTART   = 0;
527     NRF_RADIO->TASKS_CCASTOP    = 0;
528     NRF_RADIO->SHORTS           = 0;
529     NRF_RADIO->PACKETPTR        = 0;
530     NRF_RADIO->FREQUENCY        = 0;
531     NRF_RADIO->TXPOWER          = 0;
532     NRF_RADIO->MODE             = 0;
533     NRF_RADIO->PCNF0            = 0;
534     NRF_RADIO->PCNF1            = 0;
535     NRF_RADIO->BASE0            = 0;
536     NRF_RADIO->BASE1            = 0;
537     NRF_RADIO->PREFIX0          = 0;
538     NRF_RADIO->PREFIX1          = 0;
539     NRF_RADIO->TXADDRESS        = 0;
540     NRF_RADIO->RXADDRESSES      = 0;
541     NRF_RADIO->CRCCNF           = 0;
542     NRF_RADIO->CRCPOLY          = 0;
543     NRF_RADIO->CRCINIT          = 0;
544     NRF_RADIO->TIFS             = 0;
545     NRF_RADIO->DATAWHITEIV      = 0;
546     NRF_RADIO->BCC              = 0;
547     NRF_RADIO->DACNF            = 0;
548     NRF_RADIO->MHRMATCHCONF     = 0;
549     NRF_RADIO->MHRMATCHMASK     = 0;
550     NRF_RADIO->SFD              = 0xA7;
551     NRF_RADIO->EDCTRL           = RADIO_EDCTRL_ResetValue;
552     NRF_RADIO->CCACTRL          = 0x52D0000;
553     NRF_RADIO->DFEMODE          = 0;
554     NRF_RADIO->CTEINLINECONF    = 0x2800;
555     NRF_RADIO->DFECTRL1         = 0x23282;
556     NRF_RADIO->DFECTRL2         = 0;
557     NRF_RADIO->SWITCHPATTERN    = 0;
558     NRF_RADIO->CLEARPATTERN     = 0;
559     NRF_RADIO->DFEPACKET.PTR    = 0;
560     NRF_RADIO->DFEPACKET.MAXCNT = 0x1000;
561 
562     for (uint8_t i = 0; i < 8; i++)
563     {
564         NRF_RADIO->DAB[i]          = 0;
565         NRF_RADIO->DAP[i]          = 0;
566         NRF_RADIO->PSEL.DFEGPIO[i] = 0xFFFFFFFF;
567     }
568 #endif /* !defined(NRF54H20_ENGA_XXAA) */
569 }
570 
571 #endif /* !defined(RADIO_POWER_POWER_Msk) */
572 
573 /** Reset radio peripheral. */
nrf_radio_reset(void)574 static void nrf_radio_reset(void)
575 {
576     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
577 
578 #if defined(RADIO_POWER_POWER_Msk)
579     nrf_radio_power_set(NRF_RADIO, false);
580     nrf_radio_power_set(NRF_RADIO, true);
581 #else
582     radio_reset_without_power_reg();
583 #endif
584 
585     NRF_802154_TRX_RADIO_RESET_INTERNAL();
586 
587 #if defined(NRF53_SERIES)
588     yopan_158_workaround();
589 #endif /* NRF53_SERIES */
590 
591     nrf_802154_log_global_event(NRF_802154_LOG_VERBOSITY_LOW,
592                                 NRF_802154_LOG_GLOBAL_EVENT_ID_RADIO_RESET,
593                                 0U);
594 
595     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
596 }
597 
channel_set(uint8_t channel)598 static void channel_set(uint8_t channel)
599 {
600     NRF_802154_ASSERT(channel >= 11U && channel <= 26U);
601 
602     nrf_radio_frequency_set(NRF_RADIO, 2405U + 5U * (channel - 11U));
603 }
604 
cca_configuration_update(void)605 static void cca_configuration_update(void)
606 {
607     nrf_802154_cca_cfg_t cca_cfg;
608 
609     nrf_802154_pib_cca_cfg_get(&cca_cfg);
610     nrf_radio_cca_configure(NRF_RADIO,
611                             cca_cfg.mode,
612                             nrf_802154_rssi_cca_ed_threshold_corrected_get(cca_cfg.ed_threshold),
613                             cca_cfg.corr_threshold,
614                             cca_cfg.corr_limit);
615 }
616 
617 /** Initialize interrupts for radio peripheral. */
irq_init(void)618 static void irq_init(void)
619 {
620 #if NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
621     nrf_802154_irq_init(nrfx_get_irq_number(NRF_RADIO),
622                         NRF_802154_IRQ_PRIORITY,
623                         nrf_802154_radio_irq_handler);
624 #endif
625     nrf_802154_irq_enable(nrfx_get_irq_number(NRF_RADIO));
626 }
627 
trigger_disable_to_start_rampup(void)628 static void trigger_disable_to_start_rampup(void)
629 {
630     if (!nrf_802154_trx_ppi_for_ramp_up_was_triggered())
631     {
632         nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_DISABLE);
633         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
634     }
635 }
636 
637 /** Configure FEM to set LNA at appropriate time. */
fem_for_lna_set(void)638 static void fem_for_lna_set(void)
639 {
640     if (mpsl_fem_lna_configuration_set(&m_activate_rx_cc0, NULL) == 0)
641     {
642         nrf_timer_shorts_enable(m_activate_rx_cc0.event.timer.p_timer_instance,
643                                 NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
644 
645         nrf_802154_trx_ppi_for_fem_set();
646     }
647 }
648 
649 /** Reset FEM configuration for LNA. */
fem_for_lna_reset(void)650 static void fem_for_lna_reset(void)
651 {
652     mpsl_fem_lna_configuration_clear();
653     timer_stop_and_clear();
654     nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
655     nrf_802154_trx_ppi_for_fem_clear();
656     /* There is no need to explicitly deactivate LNA pin during reset as mpsl_fem_abort_set is used
657      * to provide a deactivation mechanism on DISABLED event.
658      */
659 }
660 
661 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
662 
663 /** Configure FEM to set PA at appropriate time.
664  *
665  * @note This function must be called before ramp up PPIs are configured.
666  */
fem_for_pa_set(mpsl_fem_pa_power_control_t pa_power_control)667 static void fem_for_pa_set(mpsl_fem_pa_power_control_t pa_power_control)
668 {
669     (void)mpsl_fem_pa_power_control_set(pa_power_control);
670     if (mpsl_fem_pa_configuration_set(&m_activate_tx_cc0, NULL) == 0)
671     {
672         nrf_timer_shorts_enable(m_activate_tx_cc0.event.timer.p_timer_instance,
673                                 NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
674         nrf_802154_trx_ppi_for_fem_set();
675     }
676 }
677 
678 /** Reset FEM configuration for PA.
679  *
680  * @note This function must be called before ramp up PPIs are configured.
681  */
fem_for_pa_reset(void)682 static void fem_for_pa_reset(void)
683 {
684     mpsl_fem_pa_configuration_clear();
685     timer_stop_and_clear();
686     nrf_802154_trx_ppi_for_fem_clear();
687     mpsl_fem_deactivate_now(MPSL_FEM_PA);
688 }
689 
690 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
691 
692 /** Configure FEM for TX procedure.
693  *
694  * @note This function must be called before ramp up PPIs are configured.
695  */
fem_for_tx_set(bool cca,mpsl_fem_pa_power_control_t pa_power_control)696 static void fem_for_tx_set(bool cca, mpsl_fem_pa_power_control_t pa_power_control)
697 {
698     bool success;
699 
700     (void)mpsl_fem_pa_power_control_set(pa_power_control);
701 
702     if (cca)
703     {
704         bool pa_set  = false;
705         bool lna_set = false;
706 
707         if (mpsl_fem_lna_configuration_set(&m_activate_rx_cc0, &m_ccaidle) == 0)
708         {
709             lna_set = true;
710         }
711 
712         if (mpsl_fem_pa_configuration_set(&m_ccaidle, NULL) == 0)
713         {
714             pa_set = true;
715         }
716 
717         success = pa_set || lna_set;
718 
719     }
720     else
721     {
722         success = (mpsl_fem_pa_configuration_set(&m_activate_tx_cc0, NULL) == 0);
723     }
724 
725     if (success)
726     {
727         nrf_timer_shorts_enable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
728         nrf_802154_trx_ppi_for_fem_set();
729     }
730 }
731 
fem_for_tx_reset(bool cca)732 static void fem_for_tx_reset(bool cca)
733 {
734     nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
735 
736     if (cca)
737     {
738         mpsl_fem_lna_configuration_clear();
739         mpsl_fem_pa_configuration_clear();
740     }
741     else
742     {
743         mpsl_fem_pa_configuration_clear();
744     }
745 
746     nrf_802154_trx_ppi_for_fem_clear();
747     nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait();
748     timer_stop_and_clear();
749 }
750 
751 #if defined(NRF52840_XXAA) || \
752     defined(NRF52833_XXAA)
753 /** @brief Applies DEVICE-CONFIG-254.
754  *
755  * Shall be called after every RADIO peripheral reset.
756  */
device_config_254_apply_tx(void)757 static void device_config_254_apply_tx(void)
758 {
759     uint32_t ficr_reg1 = *(volatile uint32_t *)0x10000330UL;
760     uint32_t ficr_reg2 = *(volatile uint32_t *)0x10000334UL;
761     uint32_t ficr_reg3 = *(volatile uint32_t *)0x10000338UL;
762 
763     /* Check if the device is fixed by testing every FICR register's value separately. */
764     if (ficr_reg1 != 0xffffffffUL)
765     {
766         volatile uint32_t * p_radio_reg1 = (volatile uint32_t *)0x4000174cUL;
767 
768         *p_radio_reg1 = ficr_reg1;
769     }
770 
771     if (ficr_reg2 != 0xffffffffUL)
772     {
773         volatile uint32_t * p_radio_reg2 = (volatile uint32_t *)0x40001584UL;
774 
775         *p_radio_reg2 = ficr_reg2;
776     }
777 
778     if (ficr_reg3 != 0xffffffffUL)
779     {
780         volatile uint32_t * p_radio_reg3 = (volatile uint32_t *)0x40001588UL;
781 
782         *p_radio_reg3 = ficr_reg3;
783     }
784 }
785 
786 #endif
787 
788 /** @brief Applies ERRATA-117
789  *
790  * Shall be called after setting RADIO mode to NRF_RADIO_MODE_IEEE802154_250KBIT.
791  */
792 #if defined(NRF5340_XXAA) && !defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
errata_117_apply(void)793 static void errata_117_apply(void)
794 {
795     /* Register at 0x01FF0084. */
796     uint32_t ficr_reg = *(volatile uint32_t *)(FICR_BASE + 0x84UL);
797     /* Register at 0x41008588. */
798     volatile uint32_t * p_radio_reg = (volatile uint32_t *)(RADIO_BASE + 0x588UL);
799 
800     *p_radio_reg = ficr_reg;
801 }
802 
803 static uint32_t m_pa_mod_filter_latched    = 0;
804 static bool     m_pa_mod_filter_is_latched = false;
805 
806 /** @brief Applies modulation fix when PA is used.
807  *
808  * Shall be called after setting RADIO mode to NRF_RADIO_MODE_IEEE802154_250KBIT.
809  *
810  * @param[in]  enable   @c true if the appropriate register should be modified
811  *                      @c false if it should return to its previous, latched value
812  */
pa_modulation_fix_apply(bool enable)813 static void pa_modulation_fix_apply(bool enable)
814 {
815     volatile uint32_t * p_radio_reg = (volatile uint32_t *)(RADIO_BASE + 0x584UL);
816 
817     if (enable)
818     {
819         mpsl_fem_caps_t fem_caps = {};
820 
821         mpsl_fem_caps_get(&fem_caps);
822 
823         if ((fem_caps.flags & MPSL_FEM_CAPS_FLAG_PA_SETUP_REQUIRED) != 0)
824         {
825             m_pa_mod_filter_latched    = *(p_radio_reg);
826             m_pa_mod_filter_is_latched = true;
827             *(p_radio_reg)             = 0x40081B08;
828         }
829     }
830     else if (m_pa_mod_filter_is_latched)
831     {
832         *(p_radio_reg)             = m_pa_mod_filter_latched;
833         m_pa_mod_filter_is_latched = false;
834     }
835 }
836 
837 #endif
838 
nrf_802154_trx_module_reset(void)839 void nrf_802154_trx_module_reset(void)
840 {
841     m_trx_state                      = TRX_STATE_DISABLED;
842     m_timer_value_on_radio_end_event = 0;
843     m_transmit_with_cca              = false;
844     mp_receive_buffer                = NULL;
845 
846     memset(&m_flags, 0, sizeof(m_flags));
847 }
848 
nrf_802154_trx_init(void)849 void nrf_802154_trx_init(void)
850 {
851     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
852 
853     nrf_802154_trx_module_reset();
854 
855 #if defined(RADIO_INTENSET_SYNC_Msk)
856     nrf_802154_swi_init();
857 #endif
858 
859     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
860 }
861 
862 #if defined(NRF54H_SERIES)
radio_trims_apply(void)863 static void radio_trims_apply(void)
864 {
865 #if defined(NRF54H20_XXAA) && !defined(TEST)
866     /* HMPAN-103 */
867     if ((*(volatile uint32_t *)0x5302C8A0 == 0x80000000) ||
868         (*(volatile uint32_t *)0x5302C8A0 == 0x0058120E))
869     {
870         *(volatile uint32_t *)0x5302C8A0 = 0x0058090E;
871     }
872 
873     *(volatile uint32_t *)0x5302C8A4 = 0x00F8AA5F;
874     *(volatile uint32_t *)0x5302C7AC = 0x8672827A;
875     *(volatile uint32_t *)0x5302C7B0 = 0x7E768672;
876     *(volatile uint32_t *)0x5302C7B4 = 0x0406007E;
877 #endif
878 
879     nrf_radio_fast_ramp_up_enable_set(NRF_RADIO, true);
880 }
881 
882 #endif /* defined(NRF54H_SERIES) */
883 
nrf_802154_trx_enable(void)884 void nrf_802154_trx_enable(void)
885 {
886     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
887 
888     NRF_802154_ASSERT(m_trx_state == TRX_STATE_DISABLED);
889 
890 #if defined(NRF54L_SERIES)
891     g_nrf_802154_trx_disable_repeat_was_needed = false;
892 #endif
893 
894     nrf_timer_init();
895     nrf_radio_reset();
896 
897 #if defined(NRF52840_XXAA) || \
898     defined(NRF52833_XXAA)
899     // Apply DEVICE-CONFIG-254 if needed.
900     if (mpsl_fem_device_config_254_apply_get())
901     {
902         device_config_254_apply_tx();
903     }
904 #endif
905 
906     nrf_radio_packet_conf_t packet_conf;
907 
908     nrf_radio_mode_set(NRF_RADIO, NRF_RADIO_MODE_IEEE802154_250KBIT);
909 
910 #if defined(NRF54L_SERIES) && !defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
911     // Apply MLTPAN-6
912     *(volatile uint32_t *)(RADIO_BASE + 0x810UL) = 2;
913 #endif
914 
915 #if defined(NRF5340_XXAA) && !defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
916     // Apply ERRATA-117 after setting RADIO mode to NRF_RADIO_MODE_IEEE802154_250KBIT.
917     errata_117_apply();
918     pa_modulation_fix_apply(true);
919 #endif
920 
921     memset(&packet_conf, 0, sizeof(packet_conf));
922     packet_conf.lflen  = 8;
923     packet_conf.plen   = NRF_RADIO_PREAMBLE_LENGTH_32BIT_ZERO;
924     packet_conf.crcinc = true;
925     packet_conf.maxlen = MAX_PACKET_SIZE;
926     nrf_radio_packet_configure(NRF_RADIO, &packet_conf);
927 
928 #if defined(NRF54H_SERIES)
929     radio_trims_apply();
930 #endif
931 
932     NRF_802154_TRX_ENABLE_INTERNAL();
933 
934 #if defined(RADIO_MODECNF0_RU_Msk)
935     nrf_radio_modecnf0_set(NRF_RADIO, true, 0);
936 #endif
937 
938     // Configure CRC
939     nrf_radio_crc_configure(NRF_RADIO, CRC_LENGTH, NRF_RADIO_CRC_ADDR_IEEE802154, CRC_POLYNOMIAL);
940 
941     nrf_802154_trx_ppi_for_enable();
942 
943     // Configure CCA
944     cca_configuration_update();
945 
946     // Set channel
947     channel_set(nrf_802154_pib_channel_get());
948 
949     // Custom initialization operations
950     nrf_802154_custom_part_of_radio_init();
951 
952     irq_init();
953 
954     NRF_802154_ASSERT(nrf_radio_shorts_get(NRF_RADIO) == SHORTS_IDLE);
955 
956     mpsl_fem_enable();
957 #if defined(DPPI_PRESENT)
958     mpsl_fem_abort_set(NRF_802154_DPPI_RADIO_DISABLED,
959                        0U); /* The group parameter is ignored by FEM for SoCs with DPPIs */
960 #else
961     mpsl_fem_abort_set(nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_DISABLED),
962                        PPI_CHGRP_ABORT);
963 #endif
964 
965     m_trx_state = TRX_STATE_IDLE;
966 
967     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
968 }
969 
ppi_all_clear(void)970 static void ppi_all_clear(void)
971 {
972     switch (m_trx_state)
973     {
974         case TRX_STATE_IDLE:
975         case TRX_STATE_GOING_IDLE:
976         case TRX_STATE_RXFRAME_FINISHED:
977         case TRX_STATE_FINISHED:
978             // Intentionally empty. PPIs are not configured in this state.
979             break;
980 
981         case TRX_STATE_RXFRAME:
982             rxframe_finish_disable_ppis();
983             break;
984 
985         case TRX_STATE_RXACK:
986             rxack_finish_disable_ppis();
987             nrf_802154_trx_ppi_for_fem_clear();
988             break;
989 
990         case TRX_STATE_TXFRAME:
991             txframe_finish_disable_ppis(m_transmit_with_cca);
992             nrf_802154_trx_ppi_for_fem_clear();
993             break;
994 
995         case TRX_STATE_TXACK:
996             nrf_802154_trx_ppi_for_ack_tx_clear();
997             // FEM PPIs are not configured for this state. TIMER was started in TRX_STATE_RXFRAME
998             // and PPIs starting timer were cleared when exiting TRX_STATE_RXFRAME.
999             break;
1000 
1001         case TRX_STATE_STANDALONE_CCA:
1002             nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_RXEN, false);
1003             nrf_802154_trx_ppi_for_fem_clear();
1004             break;
1005 
1006 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
1007         case TRX_STATE_CONTINUOUS_CARRIER:
1008             nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_TXEN, false);
1009             nrf_802154_trx_ppi_for_fem_clear();
1010             break;
1011 
1012         case TRX_STATE_MODULATED_CARRIER:
1013             nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_TXEN, false);
1014             nrf_802154_trx_ppi_for_fem_clear();
1015             break;
1016 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
1017 
1018         case TRX_STATE_ENERGY_DETECTION:
1019             nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_RXEN, false);
1020             nrf_802154_trx_ppi_for_fem_clear();
1021             break;
1022 
1023         default:
1024             NRF_802154_ASSERT(false);
1025     }
1026     nrf_802154_trx_ppi_for_disable();
1027 }
1028 
fem_power_down_now(void)1029 static void fem_power_down_now(void)
1030 {
1031     mpsl_fem_deactivate_now(MPSL_FEM_ALL);
1032     mpsl_fem_disable();
1033 }
1034 
nrf_802154_trx_disable(void)1035 void nrf_802154_trx_disable(void)
1036 {
1037     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1038 
1039     if (m_trx_state != TRX_STATE_DISABLED)
1040     {
1041 #if defined(NRF5340_XXAA) && !defined(CONFIG_SOC_SERIES_BSIM_NRFXX)
1042         pa_modulation_fix_apply(false);
1043 #endif
1044 
1045 #if defined(RADIO_POWER_POWER_Msk)
1046         nrf_radio_power_set(NRF_RADIO, false);
1047 #endif
1048 
1049         /* While the RADIO is powered off deconfigure any PPIs used directly by trx module */
1050         ppi_all_clear();
1051 
1052 #if !defined(RADIO_POWER_POWER_Msk)
1053         radio_robust_disable();
1054         wait_until_radio_is_disabled();
1055         nrf_radio_reset();
1056 #endif
1057 
1058         nrf_802154_irq_clear_pending(nrfx_get_irq_number(NRF_RADIO));
1059 
1060 #if defined(RADIO_INTENSET_SYNC_Msk)
1061         nrf_egu_int_disable(NRF_802154_EGU_INSTANCE, EGU_SYNC_INTMASK);
1062         nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_SYNC_EVENT);
1063 #endif
1064 
1065         /* Stop & deconfigure timer */
1066         nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE,
1067                                  NRF_TIMER_SHORT_COMPARE0_STOP_MASK |
1068                                  NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
1069         timer_stop_and_clear();
1070 
1071 #if defined(RADIO_POWER_POWER_Msk)
1072         nrf_radio_power_set(NRF_RADIO, true);
1073 #endif
1074 
1075         mpsl_fem_lna_configuration_clear();
1076         mpsl_fem_pa_configuration_clear();
1077         mpsl_fem_abort_clear();
1078 
1079         if (m_trx_state != TRX_STATE_IDLE)
1080         {
1081             fem_power_down_now();
1082         }
1083 
1084         m_flags.psdu_being_received    = false;
1085         m_flags.missing_receive_buffer = false;
1086         m_flags.rssi_started           = false;
1087         m_flags.tx_started             = false;
1088 
1089         m_trx_state = TRX_STATE_DISABLED;
1090 
1091         nrf_802154_log_global_event(NRF_802154_LOG_VERBOSITY_LOW,
1092                                     NRF_802154_LOG_GLOBAL_EVENT_ID_RADIO_RESET,
1093                                     0U);
1094     }
1095     else
1096     {
1097         // Intentionally empty
1098     }
1099 
1100     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1101 }
1102 
rx_automatic_antenna_handle(void)1103 static void rx_automatic_antenna_handle(void)
1104 {
1105     switch (m_trx_state)
1106     {
1107         case TRX_STATE_RXFRAME:
1108         case TRX_STATE_RXFRAME_FINISHED:
1109             nrf_802154_sl_ant_div_rx_started_notify();
1110             break;
1111 
1112         case TRX_STATE_ENERGY_DETECTION:
1113             // Intentionally empty - notification is called from core when requesting energy detection.
1114             // This is done due to possibility of nrf_802154_trx_energy_detection being called multiple times
1115             // during one energy detection from the point of view of application, if the entire procedure does not
1116             // fit in single timeslot.
1117             break;
1118 
1119         case TRX_STATE_TXACK:
1120             nrf_802154_sl_ant_div_txack_notify();
1121             break;
1122 
1123         default:
1124             NRF_802154_ASSERT(false);
1125             break;
1126     }
1127 }
1128 
1129 /**
1130  * Updates the antenna for reception, according to antenna diversity configuration.
1131  */
rx_antenna_update(void)1132 static void rx_antenna_update(void)
1133 {
1134     bool                         result = true;
1135     nrf_802154_sl_ant_div_mode_t mode   = nrf_802154_sl_ant_div_cfg_mode_get(
1136         NRF_802154_SL_ANT_DIV_OP_RX);
1137 
1138     switch (mode)
1139     {
1140         case NRF_802154_SL_ANT_DIV_MODE_DISABLED:
1141             break;
1142 
1143         case NRF_802154_SL_ANT_DIV_MODE_MANUAL:
1144             result = nrf_802154_sl_ant_div_antenna_set(
1145                 nrf_802154_sl_ant_div_cfg_antenna_get(NRF_802154_SL_ANT_DIV_OP_RX));
1146             break;
1147 
1148         case NRF_802154_SL_ANT_DIV_MODE_AUTO:
1149             rx_automatic_antenna_handle();
1150             break;
1151 
1152         default:
1153             NRF_802154_ASSERT(false);
1154             break;
1155     }
1156 
1157     NRF_802154_ASSERT(result);
1158     (void)result;
1159 }
1160 
1161 /**
1162  * Updates the antenna for transmission, according to antenna diversity configuration.
1163  *
1164  * Antenna diversity for tx is not currently supported. If antenna diversity is not
1165  * in disabled state, default antenna will always be used for transmission.
1166  */
tx_antenna_update(void)1167 static void tx_antenna_update(void)
1168 {
1169     bool                         result = true;
1170     nrf_802154_sl_ant_div_mode_t mode   = nrf_802154_sl_ant_div_cfg_mode_get(
1171         NRF_802154_SL_ANT_DIV_OP_TX);
1172 
1173     switch (mode)
1174     {
1175         case NRF_802154_SL_ANT_DIV_MODE_DISABLED:
1176             /* Intentionally empty. */
1177             break;
1178 
1179         case NRF_802154_SL_ANT_DIV_MODE_MANUAL:
1180             result = nrf_802154_sl_ant_div_antenna_set(
1181                 nrf_802154_sl_ant_div_cfg_antenna_get(NRF_802154_SL_ANT_DIV_OP_TX));
1182             break;
1183 
1184         case NRF_802154_SL_ANT_DIV_MODE_AUTO:
1185         default:
1186             NRF_802154_ASSERT(false);
1187             break;
1188     }
1189 
1190     if (!result)
1191     {
1192         NRF_802154_ASSERT(false);
1193     }
1194 }
1195 
nrf_802154_trx_antenna_update(void)1196 void nrf_802154_trx_antenna_update(void)
1197 {
1198     NRF_802154_ASSERT(m_trx_state != TRX_STATE_DISABLED);
1199 
1200     switch (m_trx_state)
1201     {
1202         case TRX_STATE_RXFRAME:
1203         case TRX_STATE_RXFRAME_FINISHED:
1204         case TRX_STATE_ENERGY_DETECTION:
1205         case TRX_STATE_TXACK:
1206             rx_antenna_update();
1207             break;
1208 
1209         case TRX_STATE_STANDALONE_CCA:
1210         case TRX_STATE_RXACK:
1211         case TRX_STATE_TXFRAME:
1212 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
1213         case TRX_STATE_CONTINUOUS_CARRIER:
1214         case TRX_STATE_MODULATED_CARRIER:
1215 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
1216             tx_antenna_update();
1217             break;
1218 
1219         default:
1220             /* Intentionally empty */
1221             break;
1222     }
1223 }
1224 
nrf_802154_trx_channel_set(uint8_t channel)1225 void nrf_802154_trx_channel_set(uint8_t channel)
1226 {
1227     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1228 
1229     channel_set(channel);
1230 
1231     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1232 }
1233 
nrf_802154_trx_cca_configuration_update(void)1234 void nrf_802154_trx_cca_configuration_update(void)
1235 {
1236     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1237 
1238     cca_configuration_update();
1239 
1240     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1241 }
1242 
1243 /** Check if PSDU is currently being received.
1244  *
1245  * @returns True if radio is receiving PSDU, false otherwise.
1246  */
nrf_802154_trx_psdu_is_being_received(void)1247 bool nrf_802154_trx_psdu_is_being_received(void)
1248 {
1249     return m_flags.psdu_being_received;
1250 }
1251 
nrf_802154_trx_receive_is_buffer_missing(void)1252 bool nrf_802154_trx_receive_is_buffer_missing(void)
1253 {
1254     switch (m_trx_state)
1255     {
1256         case TRX_STATE_RXFRAME:
1257         /* no break */
1258         case TRX_STATE_RXACK:
1259             return m_flags.missing_receive_buffer;
1260 
1261         default:
1262             NRF_802154_ASSERT(!m_flags.missing_receive_buffer);
1263             return false;
1264     }
1265 }
1266 
receive_buffer_missing_buffer_set(void * p_receive_buffer)1267 static void receive_buffer_missing_buffer_set(void * p_receive_buffer)
1268 {
1269     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1270 
1271     uint32_t shorts = SHORTS_IDLE;
1272 
1273     switch (m_trx_state)
1274     {
1275         case TRX_STATE_RXFRAME:
1276             shorts = SHORTS_RX | SHORTS_RX_FREE_BUFFER;
1277             break;
1278 
1279         case TRX_STATE_RXACK:
1280             shorts = SHORTS_RX_ACK | SHORTS_RX_FREE_BUFFER;
1281             break;
1282 
1283         default:
1284             NRF_802154_ASSERT(false);
1285     }
1286 
1287     m_flags.missing_receive_buffer = false;
1288 
1289     nrf_radio_packetptr_set(NRF_RADIO, p_receive_buffer);
1290 
1291     nrf_radio_shorts_set(NRF_RADIO, shorts);
1292 
1293     if (nrf_radio_state_get(NRF_RADIO) == NRF_RADIO_STATE_RXIDLE)
1294     {
1295         nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_START);
1296     }
1297 
1298     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1299 }
1300 
nrf_802154_trx_receive_buffer_set(void * p_receive_buffer)1301 bool nrf_802154_trx_receive_buffer_set(void * p_receive_buffer)
1302 {
1303     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
1304 
1305     bool result = false;
1306 
1307     mp_receive_buffer = p_receive_buffer;
1308 
1309     if ((p_receive_buffer != NULL) && m_flags.missing_receive_buffer)
1310     {
1311         receive_buffer_missing_buffer_set(p_receive_buffer);
1312         result = true;
1313     }
1314 
1315     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
1316 
1317     return result;
1318 }
1319 
nrf_802154_trx_receive_frame(uint8_t bcc,nrf_802154_trx_ramp_up_trigger_mode_t rampup_trigg_mode,nrf_802154_trx_receive_notifications_t notifications_mask,const nrf_802154_fal_tx_power_split_t * p_ack_tx_power)1320 void nrf_802154_trx_receive_frame(uint8_t                                 bcc,
1321                                   nrf_802154_trx_ramp_up_trigger_mode_t   rampup_trigg_mode,
1322                                   nrf_802154_trx_receive_notifications_t  notifications_mask,
1323                                   const nrf_802154_fal_tx_power_split_t * p_ack_tx_power)
1324 {
1325     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1326 
1327     uint32_t ints_to_enable = 0U;
1328     uint32_t shorts         = SHORTS_RX;
1329 
1330     timer_stop_and_clear();
1331 
1332     m_trx_state = TRX_STATE_RXFRAME;
1333 
1334     // Clear filtering flag
1335     rx_flags_clear();
1336 
1337     m_flags.rxstarted_notif_en = (notifications_mask & TRX_RECEIVE_NOTIFICATION_STARTED) != 0U;
1338 
1339     // Clear the RSSI measurement flag.
1340     m_flags.rssi_started = false;
1341 
1342     m_flags.rssi_settled = false;
1343 
1344     txpower_set(p_ack_tx_power->radio_tx_power);
1345 
1346     if (mp_receive_buffer != NULL)
1347     {
1348         m_flags.missing_receive_buffer = false;
1349         nrf_radio_packetptr_set(NRF_RADIO, mp_receive_buffer);
1350         shorts |= SHORTS_RX_FREE_BUFFER;
1351     }
1352     else
1353     {
1354         m_flags.missing_receive_buffer = true;
1355     }
1356 
1357     // Set shorts
1358     nrf_radio_shorts_set(NRF_RADIO, shorts);
1359 
1360     // Set BCC
1361     NRF_802154_ASSERT(bcc != 0U);
1362     nrf_radio_bcc_set(NRF_RADIO, bcc * 8U);
1363 
1364     // Enable IRQs
1365     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCERROR);
1366     ints_to_enable |= NRF_RADIO_INT_CRCERROR_MASK;
1367     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH);
1368     ints_to_enable |= NRF_RADIO_INT_BCMATCH_MASK;
1369     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCOK);
1370     ints_to_enable |= NRF_RADIO_INT_CRCOK_MASK;
1371     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
1372     ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK;
1373 
1374     if (rampup_trigg_mode == TRX_RAMP_UP_HW_TRIGGER)
1375     {
1376         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
1377 #if !defined(NRF53_SERIES)
1378         ints_to_enable |= (NRF_RADIO_INT_READY_MASK | NRF_RADIO_INT_DISABLED_MASK);
1379 #else
1380         ints_to_enable |= NRF_RADIO_INT_READY_MASK;
1381 #endif
1382     }
1383 
1384     bool allow_sync_swi = false;
1385 
1386 #ifdef RADIO_INTENSET_SYNC_Msk
1387     if (((notifications_mask & TRX_RECEIVE_NOTIFICATION_PRESTARTED) != 0U) ||
1388         (NRF_802154_SL_ANT_DIV_MODE_DISABLED !=
1389          nrf_802154_sl_ant_div_cfg_mode_get(NRF_802154_SL_ANT_DIV_OP_RX)))
1390     {
1391         allow_sync_swi = true;
1392     }
1393 #endif
1394 
1395     if (allow_sync_swi)
1396     {
1397 #if !defined(RADIO_INTENSET_SYNC_Msk)
1398         NRF_802154_ASSERT(false);
1399 #else
1400         // The RADIO can't generate interrupt on EVENT_SYNC. Path to generate interrupt:
1401         // RADIO.EVENT_SYNC -> PPI_RADIO_SYNC_EGU_SYNC -> EGU.TASK_SYNC -> EGU.EVENT_SYNC ->
1402         // SWI_IRQHandler (in nrf_802154_swi.c), calls nrf_802154_trx_swi_irq_handler
1403         nrf_802154_trx_ppi_for_radio_sync_set(EGU_SYNC_TASK);
1404 
1405         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_SYNC);
1406         nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_SYNC_EVENT);
1407         nrf_egu_int_enable(NRF_802154_EGU_INSTANCE, EGU_SYNC_INTMASK);
1408 #endif
1409     }
1410 
1411     nrf_radio_int_enable(NRF_RADIO, ints_to_enable);
1412 
1413     // Set FEM
1414     uint32_t delta_time;
1415 
1416     if (mpsl_fem_lna_configuration_set(&m_activate_rx_cc0, NULL) == 0)
1417     {
1418         delta_time = nrf_timer_cc_get(NRF_802154_TIMER_INSTANCE,
1419                                       NRF_TIMER_CC_CHANNEL0);
1420     }
1421     else
1422     {
1423 #if !defined(NRF54L_SERIES)
1424         delta_time = 1;
1425 #else
1426         // Avoid value 1 due to MLTPAN-22 and MLTPAN-24
1427         delta_time = 2;
1428 #endif
1429         nrf_timer_cc_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0, delta_time);
1430     }
1431 
1432     // Set FEM PA gain for ACK transmission
1433     mpsl_fem_pa_power_control_set(p_ack_tx_power->fem_pa_power_control);
1434 
1435     m_timer_value_on_radio_end_event = delta_time;
1436 
1437     // Select antenna
1438     nrf_802154_trx_antenna_update();
1439 
1440     // Let the TIMER stop on last event required by a FEM
1441     nrf_timer_shorts_enable(NRF_802154_TIMER_INSTANCE,
1442                             NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
1443 
1444     // Set PPIs
1445     nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, rampup_trigg_mode, true);
1446 
1447     if (rampup_trigg_mode == TRX_RAMP_UP_SW_TRIGGER)
1448     {
1449         trigger_disable_to_start_rampup();
1450     }
1451 
1452     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1453 }
1454 
nrf_802154_trx_receive_ack(void)1455 void nrf_802154_trx_receive_ack(void)
1456 {
1457     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1458 
1459     uint32_t shorts         = SHORTS_RX_ACK;
1460     uint32_t ints_to_enable = 0U;
1461 
1462     m_trx_state = TRX_STATE_RXACK;
1463 
1464     if (mp_receive_buffer != NULL)
1465     {
1466         m_flags.missing_receive_buffer = false;
1467         nrf_radio_packetptr_set(NRF_RADIO, mp_receive_buffer);
1468         shorts |= SHORTS_RX_FREE_BUFFER;
1469     }
1470     else
1471     {
1472         m_flags.missing_receive_buffer = true;
1473     }
1474 
1475     nrf_radio_shorts_set(NRF_RADIO, shorts);
1476 
1477     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
1478     ints_to_enable |= NRF_RADIO_INT_ADDRESS_MASK;
1479     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCOK);
1480     ints_to_enable |= NRF_RADIO_INT_CRCOK_MASK;
1481     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCERROR);
1482     ints_to_enable |= NRF_RADIO_INT_CRCERROR_MASK;
1483 
1484     nrf_radio_int_enable(NRF_RADIO, ints_to_enable);
1485 
1486     fem_for_lna_set();
1487     nrf_802154_trx_antenna_update();
1488     nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, TRX_RAMP_UP_SW_TRIGGER, false);
1489 
1490     trigger_disable_to_start_rampup();
1491 
1492     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1493 }
1494 
nrf_802154_trx_rssi_measure(void)1495 bool nrf_802154_trx_rssi_measure(void)
1496 {
1497     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1498 
1499     bool result = false;
1500 
1501     if (m_trx_state == TRX_STATE_RXFRAME)
1502     {
1503         // When TRX is in RXFRAME the RADIO may be also ramping down after previous operation or still ramping up
1504         nrf_radio_state_t radio_state = nrf_radio_state_get(NRF_RADIO);
1505 
1506         if ((radio_state == RADIO_STATE_STATE_RxIdle) || (radio_state == RADIO_STATE_STATE_Rx))
1507         {
1508             if (!m_flags.rssi_settled)
1509             {
1510                 // This operation is requested first time after nrf_802154_trx_receive_frame has been called
1511                 // Radio is ramped up, but we need to wait RSSISETTLE time.
1512                 // Precisely, we need to wait NRF_RADIO_EVENT_RSSIEND between READY->START short worked
1513                 // and RSSI_START task is triggered. Due to limited resources we assume worst case and
1514                 // wait whole time when rssi_measure is requested first time after nrf_802154_trx_receive_frame.
1515                 nrf_802154_delay_us(RSSI_SETTLE_TIME_US);
1516                 m_flags.rssi_settled = true;
1517             }
1518 
1519 #if defined(RADIO_EVENTS_RSSIEND_EVENTS_RSSIEND_Msk)
1520             nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_RSSIEND);
1521 #endif
1522             nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_RSSISTART);
1523             m_flags.rssi_started = true;
1524 
1525             result = true;
1526         }
1527         else
1528         {
1529             // The RADIO may be:
1530             // - still ramping down after transmit
1531             // - ramping up for receive
1532             // - ramping down after frame is received (shorts)
1533         }
1534     }
1535 
1536     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1537 
1538     return result;
1539 }
1540 
nrf_802154_trx_rssi_measure_is_started(void)1541 bool nrf_802154_trx_rssi_measure_is_started(void)
1542 {
1543     return m_flags.rssi_started;
1544 }
1545 
nrf_802154_trx_rssi_last_sample_get(void)1546 uint8_t nrf_802154_trx_rssi_last_sample_get(void)
1547 {
1548     return nrf_radio_rssi_sample_get(NRF_RADIO);
1549 }
1550 
nrf_802154_trx_rssi_sample_is_available(void)1551 bool nrf_802154_trx_rssi_sample_is_available(void)
1552 {
1553 #if defined(RADIO_EVENTS_RSSIEND_EVENTS_RSSIEND_Msk)
1554     return nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_RSSIEND);
1555 #else
1556     return true;
1557 #endif
1558 }
1559 
nrf_802154_trx_transmit_frame(const void * p_transmit_buffer,nrf_802154_trx_ramp_up_trigger_mode_t rampup_trigg_mode,uint8_t cca_attempts,const nrf_802154_fal_tx_power_split_t * p_tx_power,nrf_802154_trx_transmit_notifications_t notifications_mask)1560 void nrf_802154_trx_transmit_frame(const void                            * p_transmit_buffer,
1561                                    nrf_802154_trx_ramp_up_trigger_mode_t   rampup_trigg_mode,
1562                                    uint8_t                                 cca_attempts,
1563                                    const nrf_802154_fal_tx_power_split_t * p_tx_power,
1564                                    nrf_802154_trx_transmit_notifications_t notifications_mask)
1565 {
1566     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1567 
1568     uint32_t ints_to_enable = 0U;
1569     bool     cca            = cca_attempts > 0;
1570 
1571     timer_stop_and_clear();
1572 
1573     m_trx_state              = TRX_STATE_TXFRAME;
1574     m_transmit_with_cca      = cca;
1575     m_remaining_cca_attempts = cca_attempts;
1576 
1577     m_flags.ccastarted_notif_en = false;
1578 
1579     txpower_set(p_tx_power->radio_tx_power);
1580 
1581     nrf_radio_packetptr_set(NRF_RADIO, p_transmit_buffer);
1582 
1583     // Set shorts
1584     if (cca_attempts > 1)
1585     {
1586         nrf_radio_shorts_set(NRF_RADIO, SHORTS_MULTI_CCA_TX);
1587         nrf_802154_trx_ppi_for_extra_cca_attempts_set();
1588     }
1589     else if (cca_attempts == 1)
1590     {
1591         nrf_radio_shorts_set(NRF_RADIO, SHORTS_CCA_TX);
1592     }
1593     else
1594     {
1595         nrf_radio_shorts_set(NRF_RADIO, SHORTS_TX);
1596     }
1597 
1598     // Enable IRQs
1599     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND);
1600     ints_to_enable |= NRF_RADIO_INT_PHYEND_MASK;
1601 
1602     if (rampup_trigg_mode == TRX_RAMP_UP_HW_TRIGGER)
1603     {
1604         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
1605 #if !defined(NRF53_SERIES)
1606         ints_to_enable |= (NRF_RADIO_INT_READY_MASK | NRF_RADIO_INT_DISABLED_MASK);
1607 #else
1608         ints_to_enable |= NRF_RADIO_INT_READY_MASK;
1609 #endif
1610     }
1611 
1612     if (cca)
1613     {
1614         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY);
1615 
1616         ints_to_enable |= NRF_RADIO_INT_CCABUSY_MASK;
1617 
1618         if ((notifications_mask & TRX_TRANSMIT_NOTIFICATION_CCAIDLE) != 0U)
1619         {
1620             nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE);
1621             ints_to_enable |= NRF_RADIO_INT_CCAIDLE_MASK;
1622         }
1623 
1624         if ((notifications_mask & TRX_TRANSMIT_NOTIFICATION_CCASTARTED) != 0U)
1625         {
1626             nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
1627             ints_to_enable             |= NRF_RADIO_INT_READY_MASK;
1628             m_flags.ccastarted_notif_en = true;
1629         }
1630     }
1631 
1632     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
1633     ints_to_enable    |= NRF_RADIO_INT_ADDRESS_MASK;
1634     m_flags.tx_started = false;
1635 
1636     nrf_radio_int_enable(NRF_RADIO, ints_to_enable);
1637 
1638     fem_for_tx_set(cca, p_tx_power->fem_pa_power_control);
1639     nrf_802154_trx_antenna_update();
1640     nrf_802154_trx_ppi_for_ramp_up_set(cca ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN,
1641                                        rampup_trigg_mode,
1642                                        false);
1643 
1644     if (rampup_trigg_mode == TRX_RAMP_UP_SW_TRIGGER)
1645     {
1646         trigger_disable_to_start_rampup();
1647     }
1648 
1649     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1650 }
1651 
nrf_802154_trx_transmit_ack(const void * p_transmit_buffer,uint32_t delay_us)1652 bool nrf_802154_trx_transmit_ack(const void * p_transmit_buffer, uint32_t delay_us)
1653 {
1654     /* Assumptions on peripherals
1655      * TIMER is running, is counting from value saved in m_timer_value_on_radio_end_event,
1656      * which trigered on END event, which happened EVENT_LAT us after frame on air receive was finished.
1657      * RADIO is DISABLED
1658      * PPIs are DISABLED
1659      */
1660 
1661     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1662 
1663     bool result = false;
1664 
1665     NRF_802154_ASSERT(m_trx_state == TRX_STATE_RXFRAME_FINISHED);
1666     NRF_802154_ASSERT(p_transmit_buffer != NULL);
1667 
1668     m_trx_state = TRX_STATE_TXACK;
1669 
1670     // Set TIMER's CC to the moment when ramp-up should occur.
1671     if (delay_us <= TXRU_TIME + EVENT_LAT)
1672     {
1673         timer_stop_and_clear();
1674         nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1675         return result;
1676     }
1677 
1678     uint32_t timer_cc_ramp_up_start = m_timer_value_on_radio_end_event + delay_us - TXRU_TIME -
1679                                       EVENT_LAT;
1680 
1681     nrf_timer_cc_set(NRF_802154_TIMER_INSTANCE,
1682                      NRF_TIMER_CC_CHANNEL1,
1683                      timer_cc_ramp_up_start);
1684 
1685     nrf_radio_packetptr_set(NRF_RADIO, p_transmit_buffer);
1686 
1687     // Set shorts
1688     nrf_radio_shorts_set(NRF_RADIO, SHORTS_TX_ACK);
1689 
1690     // Clear TXREADY event to detect if PPI worked
1691     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_TXREADY);
1692 
1693     // Set FEM
1694     // Note: the TIMER is running, ramp up will start in timer_cc_ramp_up_start tick
1695     // Assumption here is that FEM activation takes no more than TXRU_TIME.
1696     m_activate_tx_cc0_timeshifted = m_activate_tx_cc0;
1697 
1698     // Set the moment for FEM at which real transmission starts.
1699     m_activate_tx_cc0_timeshifted.event.timer.counter_period.end = timer_cc_ramp_up_start +
1700                                                                    TXRU_TIME;
1701 
1702     if (mpsl_fem_pa_configuration_set(&m_activate_tx_cc0_timeshifted, NULL) == 0)
1703     {
1704         // FEM scheduled its operations on timer, so the timer must be running until last
1705         // operation scheduled by the FEM (TIMER's CC0), which is later than radio ramp up
1706         nrf_timer_shorts_enable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
1707     }
1708     else
1709     {
1710         // FEM didn't schedule anything on timer, so the timer may be stopped when radio ramp-up
1711         // is triggered
1712         nrf_timer_shorts_enable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
1713     }
1714 
1715     // Select antenna
1716     nrf_802154_trx_antenna_update();
1717 
1718     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND);
1719     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
1720 
1721     // Set PPIs
1722     nrf_802154_trx_ppi_for_ack_tx_set();
1723 
1724     // Since this point the transmission is armed on TIMER's CC1
1725 
1726     // Detect if PPI will work in future or has just worked.
1727     nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_CAPTURE3);
1728     uint32_t timer_cc_now = nrf_timer_cc_get(NRF_802154_TIMER_INSTANCE,
1729                                              NRF_TIMER_CC_CHANNEL3);
1730     uint32_t timer_cc_fem_start = nrf_timer_cc_get(NRF_802154_TIMER_INSTANCE,
1731                                                    NRF_TIMER_CC_CHANNEL0);
1732 
1733     // When external PA uses a timer, it should be configured to a time later than ramp up time. In
1734     // such case, the timer stops with shorts on PA timer. But if external PA does not use a timer,
1735     // FEM time is set to a value in the past that was used by LNA. After the timer overflows,
1736     // the timer stops with a short on the past value used by LNA. We have to detect if the current
1737     // timer value is after the overflow.
1738     if ((timer_cc_now < timer_cc_ramp_up_start) &&
1739         ((timer_cc_fem_start >= timer_cc_ramp_up_start) || (timer_cc_now > timer_cc_fem_start)))
1740     {
1741         result = true;
1742     }
1743     else
1744     {
1745         nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait();
1746 
1747         if (nrf_radio_state_get(NRF_RADIO) == NRF_RADIO_STATE_TXRU)
1748         {
1749             result = true;
1750         }
1751         else if (nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_TXREADY))
1752         {
1753             result = true;
1754         }
1755         else
1756         {
1757             result = false;
1758         }
1759     }
1760 
1761     if (result)
1762     {
1763 #if !defined(NRF53_SERIES)
1764         uint32_t ints_to_enable = NRF_RADIO_INT_PHYEND_MASK |
1765                                   NRF_RADIO_INT_ADDRESS_MASK |
1766                                   NRF_RADIO_INT_DISABLED_MASK;
1767 
1768 #else
1769         uint32_t ints_to_enable = NRF_RADIO_INT_PHYEND_MASK |
1770                                   NRF_RADIO_INT_ADDRESS_MASK;
1771 
1772 #endif
1773 
1774         nrf_radio_int_enable(NRF_RADIO, ints_to_enable);
1775     }
1776     else
1777     {
1778 #if !NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK
1779         /* We were to late with setting up PPI_TIMER_ACK, ack transmission was not triggered and
1780          * will not be triggered in future.
1781          */
1782         nrf_802154_trx_ppi_for_ack_tx_clear();
1783 
1784         /* As the timer was running during operation, it is possible we were able to configure
1785          * FEM thus it may trigger in future or may started PA activation.
1786          */
1787         mpsl_fem_pa_configuration_clear();
1788         mpsl_fem_deactivate_now(MPSL_FEM_PA);
1789 
1790         timer_stop_and_clear();
1791 
1792         /* No callbacks will be called */
1793 #else // !NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK
1794         uint32_t ints_to_enable = NRF_RADIO_INT_PHYEND_MASK | NRF_RADIO_INT_ADDRESS_MASK;
1795 
1796         nrf_radio_int_enable(NRF_RADIO, ints_to_enable);
1797 
1798         nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_TXEN);
1799 
1800         result = true;
1801 #endif // !NRF_802154_TRX_TEST_MODE_ALLOW_LATE_TX_ACK
1802     }
1803 
1804     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1805 
1806     return result;
1807 }
1808 
rxframe_finish_disable_ppis(void)1809 static void rxframe_finish_disable_ppis(void)
1810 {
1811     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
1812 
1813     nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_RXEN, true);
1814 #if defined(RADIO_INTENSET_SYNC_Msk)
1815     nrf_802154_trx_ppi_for_radio_sync_clear(EGU_SYNC_TASK);
1816 #endif
1817 
1818     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
1819 }
1820 
rxframe_finish_disable_fem_activation(void)1821 static void rxframe_finish_disable_fem_activation(void)
1822 {
1823     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
1824 
1825     // Disable LNA activation
1826     mpsl_fem_lna_configuration_clear();
1827     // Disable short used by LNA activation
1828     nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE,
1829                              NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
1830 
1831     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
1832 }
1833 
rxframe_finish_disable_ints(void)1834 static void rxframe_finish_disable_ints(void)
1835 {
1836     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
1837 
1838     uint32_t ints_to_disable = NRF_RADIO_INT_READY_MASK |
1839                                NRF_RADIO_INT_ADDRESS_MASK |
1840                                NRF_RADIO_INT_CRCOK_MASK |
1841                                NRF_RADIO_INT_DISABLED_MASK;
1842 
1843     ints_to_disable |= NRF_RADIO_INT_CRCERROR_MASK;
1844     ints_to_disable |= NRF_RADIO_INT_BCMATCH_MASK;
1845     nrf_radio_int_disable(NRF_RADIO, ints_to_disable);
1846 
1847 #if defined(RADIO_INTENSET_SYNC_Msk)
1848     nrf_egu_int_disable(NRF_802154_EGU_INSTANCE, EGU_SYNC_INTMASK);
1849 #endif
1850 
1851     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
1852 }
1853 
rxframe_finish_psdu_is_not_being_received(void)1854 static void rxframe_finish_psdu_is_not_being_received(void)
1855 {
1856     m_flags.psdu_being_received = false;
1857 }
1858 
rxframe_finish(void)1859 static void rxframe_finish(void)
1860 {
1861     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
1862 
1863     /* Note that CRCOK/CRCERROR event is generated several cycles before END event.
1864      *
1865      * Below shown what is happening in the hardware
1866      *
1867      * TIMER is started by path:
1868      * RADIO.SHORT_PHYEND_DISABLE -> RADIO.TASKS_DISABLE -> RADIO.EVENTS_DISABLED ->
1869      *    PPI_DISABLED_EGU -> EGU.TASKS_TRIGGER -> EGU.EVENTS_TRIGGERED -> PPI_EGU_TIMER_START -> TIMER.TASKS_START
1870      *
1871      * FEM's LNA mode is disabled by path:
1872      * RADIO.SHORT_PHYEND_DISABLE -> RADIO.TASKS_DISABLE -> RADIO.EVENTS_DISABLED -> (FEM's PPI triggering disable LNA
1873      *                                                                                operation, see mpsl_fem_abort_set() )
1874      *
1875      * RADIO will not ramp up, as PPI_EGU_RAMP_UP channel is self-disabling, and
1876      * it was disabled when receive ramp-up was started.
1877      */
1878     wait_until_radio_is_disabled(); // This includes waiting since CRCOK/CRCERROR (several cycles) event until END
1879                                     // and then during RXDISABLE state (0.5us)
1880 
1881     nrf_802154_trx_ppi_for_ramp_up_propagation_delay_wait();
1882 
1883     /* Now it is guaranteed, that:
1884      * - FEM operation to disable LNA mode is triggered through FEM's PPIs
1885      * - TIMER is started again allowing operation of nrf_802154_trx_transmit_ack
1886      */
1887 
1888     rxframe_finish_disable_ppis();
1889     rxframe_finish_disable_fem_activation();
1890     rxframe_finish_psdu_is_not_being_received();
1891     rxframe_finish_disable_ints();
1892     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
1893     m_flags.missing_receive_buffer = false;
1894 
1895     /* Current state of peripherals:
1896      * RADIO is DISABLED
1897      * FEM is powered but LNA mode has just been turned off
1898      * TIMER is running, counting from the value stored in m_timer_value_on_radio_end_event
1899      * All PPIs used by receive operation are disabled, forks are cleared, PPI groups that were used are cleared
1900      * RADIO.SHORTS are cleared
1901      */
1902 
1903     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
1904 }
1905 
nrf_802154_trx_abort(void)1906 void nrf_802154_trx_abort(void)
1907 {
1908     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1909 
1910     switch (m_trx_state)
1911     {
1912         case TRX_STATE_DISABLED:
1913         case TRX_STATE_IDLE:
1914         case TRX_STATE_FINISHED:
1915             /* Nothing to do, intentionally empty */
1916             break;
1917 
1918         case TRX_STATE_GOING_IDLE:
1919             go_idle_abort();
1920             break;
1921 
1922         case TRX_STATE_RXFRAME:
1923             receive_frame_abort();
1924             break;
1925 
1926         case TRX_STATE_RXFRAME_FINISHED:
1927             timer_stop_and_clear();
1928             m_trx_state = TRX_STATE_FINISHED;
1929             break;
1930 
1931         case TRX_STATE_RXACK:
1932             receive_ack_abort();
1933             break;
1934 
1935         case TRX_STATE_TXFRAME:
1936             transmit_frame_abort();
1937             break;
1938 
1939         case TRX_STATE_TXACK:
1940             transmit_ack_abort();
1941             break;
1942 
1943         case TRX_STATE_STANDALONE_CCA:
1944             standalone_cca_abort();
1945             break;
1946 
1947 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
1948         case TRX_STATE_CONTINUOUS_CARRIER:
1949             continuous_carrier_abort();
1950             break;
1951 
1952         case TRX_STATE_MODULATED_CARRIER:
1953             modulated_carrier_abort();
1954             break;
1955 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
1956 
1957         case TRX_STATE_ENERGY_DETECTION:
1958             energy_detection_abort();
1959             break;
1960 
1961         default:
1962             NRF_802154_ASSERT(false);
1963     }
1964 
1965     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1966 }
1967 
nrf_802154_trx_state_get(void)1968 trx_state_t nrf_802154_trx_state_get(void)
1969 {
1970     return m_trx_state;
1971 }
1972 
nrf_802154_trx_ramp_up_ppi_channel_get(void)1973 uint32_t nrf_802154_trx_ramp_up_ppi_channel_get(void)
1974 {
1975     return nrf_802154_trx_ppi_for_ramp_up_channel_id_get();
1976 }
1977 
go_idle_from_state_finished(void)1978 static void go_idle_from_state_finished(void)
1979 {
1980     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
1981 
1982     m_trx_state = TRX_STATE_GOING_IDLE;
1983 
1984     radio_robust_disable();
1985 
1986     nrf_radio_int_enable(NRF_RADIO, NRF_RADIO_INT_DISABLED_MASK);
1987 
1988     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
1989 }
1990 
nrf_802154_trx_go_idle(void)1991 bool nrf_802154_trx_go_idle(void)
1992 {
1993     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1994 
1995     bool result = false;
1996 
1997     switch (m_trx_state)
1998     {
1999         case TRX_STATE_DISABLED:
2000             NRF_802154_ASSERT(false);
2001             break;
2002 
2003         case TRX_STATE_IDLE:
2004             /* There will be no callout */
2005             break;
2006 
2007         case TRX_STATE_GOING_IDLE:
2008             /* There will be callout */
2009             result = true;
2010             break;
2011 
2012         case TRX_STATE_RXFRAME_FINISHED:
2013             timer_stop_and_clear();
2014         /* Fallthrough */
2015 
2016         case TRX_STATE_FINISHED:
2017             go_idle_from_state_finished();
2018             result = true;
2019             break;
2020 
2021         default:
2022             NRF_802154_ASSERT(false);
2023     }
2024 
2025     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2026 
2027     return result;
2028 }
2029 
go_idle_abort(void)2030 static void go_idle_abort(void)
2031 {
2032     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2033 
2034     nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_DISABLED_MASK);
2035     m_trx_state = TRX_STATE_FINISHED;
2036 
2037     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2038 }
2039 
receive_frame_abort(void)2040 static void receive_frame_abort(void)
2041 {
2042     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2043 
2044     rxframe_finish_disable_ppis();
2045     rxframe_finish_disable_fem_activation();
2046     rxframe_finish_psdu_is_not_being_received();
2047     rxframe_finish_disable_ints();
2048     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2049 
2050     m_flags.missing_receive_buffer = false;
2051     radio_robust_disable();
2052     timer_stop_and_clear();
2053 
2054     m_trx_state = TRX_STATE_FINISHED;
2055 
2056     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2057 }
2058 
rxack_finish_disable_ppis(void)2059 static void rxack_finish_disable_ppis(void)
2060 {
2061     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2062 
2063     nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_RXEN, false);
2064 
2065     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2066 }
2067 
rxack_finish_disable_ints(void)2068 static void rxack_finish_disable_ints(void)
2069 {
2070     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2071 
2072     nrf_radio_int_disable(NRF_RADIO,
2073                           NRF_RADIO_INT_ADDRESS_MASK | NRF_RADIO_INT_CRCERROR_MASK |
2074                           NRF_RADIO_INT_CRCOK_MASK);
2075 
2076     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2077 }
2078 
rxack_finish_disable_fem_activation(void)2079 static void rxack_finish_disable_fem_activation(void)
2080 {
2081     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2082 
2083     // Disable LNA activation
2084     mpsl_fem_lna_configuration_clear();
2085 
2086     // Clear LNA PPIs
2087     nrf_802154_trx_ppi_for_fem_clear();
2088 
2089     // Disable short used by LNA activation
2090     nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE,
2091                              NRF_TIMER_SHORT_COMPARE0_STOP_MASK);
2092 
2093     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2094 }
2095 
rxack_finish(void)2096 static void rxack_finish(void)
2097 {
2098     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2099 
2100     rxack_finish_disable_ppis();
2101     rxack_finish_disable_ints();
2102     rxack_finish_disable_fem_activation();
2103     timer_stop_and_clear();
2104     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2105     m_flags.missing_receive_buffer = false;
2106 
2107     /* Current state of peripherals
2108      * RADIO is DISABLED
2109      * FEM is powered but LNA mode has just been turned off
2110      * TIMER is shutdown
2111      * PPIs used by receive operation are disabled, forks are cleared, PPI groups used are cleared
2112      * RADIO.SHORTS are cleared
2113      */
2114 
2115     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2116 }
2117 
receive_ack_abort(void)2118 static void receive_ack_abort(void)
2119 {
2120     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2121 
2122     rxack_finish_disable_ppis();
2123     rxack_finish_disable_ints();
2124     rxack_finish_disable_fem_activation();
2125     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2126     m_flags.missing_receive_buffer = false;
2127 
2128     radio_robust_disable();
2129     timer_stop_and_clear();
2130 
2131     m_trx_state = TRX_STATE_FINISHED;
2132 
2133     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2134 }
2135 
nrf_802154_trx_standalone_cca(void)2136 void nrf_802154_trx_standalone_cca(void)
2137 {
2138     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2139 
2140     NRF_802154_ASSERT((m_trx_state == TRX_STATE_IDLE) || (m_trx_state == TRX_STATE_FINISHED));
2141 
2142     m_trx_state = TRX_STATE_STANDALONE_CCA;
2143 
2144     // Set shorts
2145     nrf_radio_shorts_set(NRF_RADIO, SHORTS_CCA);
2146 
2147     // Enable IRQs
2148     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY);
2149     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE);
2150     nrf_radio_int_enable(NRF_RADIO, NRF_RADIO_INT_CCABUSY_MASK | NRF_RADIO_INT_CCAIDLE_MASK);
2151 
2152     // Set FEM
2153     fem_for_lna_set();
2154 
2155     // Select antenna
2156     nrf_802154_trx_antenna_update();
2157 
2158     // Set PPIs
2159     nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, TRX_RAMP_UP_SW_TRIGGER, false);
2160 
2161     trigger_disable_to_start_rampup();
2162 
2163     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2164 }
2165 
standalone_cca_finish(void)2166 static void standalone_cca_finish(void)
2167 {
2168     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2169 
2170     nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_RXEN, false);
2171 
2172     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2173 
2174     fem_for_lna_reset();
2175 
2176     nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_CCABUSY_MASK | NRF_RADIO_INT_CCAIDLE_MASK);
2177 
2178     nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_CCASTOP);
2179     radio_robust_disable();
2180 
2181     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2182 }
2183 
standalone_cca_abort(void)2184 static void standalone_cca_abort(void)
2185 {
2186     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2187 
2188     standalone_cca_finish();
2189 
2190     m_trx_state = TRX_STATE_FINISHED;
2191 
2192     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2193 }
2194 
2195 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
2196 
nrf_802154_trx_continuous_carrier(const nrf_802154_fal_tx_power_split_t * p_tx_power)2197 void nrf_802154_trx_continuous_carrier(const nrf_802154_fal_tx_power_split_t * p_tx_power)
2198 {
2199     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2200 
2201     NRF_802154_ASSERT((m_trx_state == TRX_STATE_IDLE) || (m_trx_state == TRX_STATE_FINISHED));
2202 
2203     m_trx_state = TRX_STATE_CONTINUOUS_CARRIER;
2204 
2205     // Set Tx Power
2206     txpower_set(p_tx_power->radio_tx_power);
2207 
2208     // Set FEM
2209     fem_for_pa_set(p_tx_power->fem_pa_power_control);
2210 
2211     // Select antenna
2212     nrf_802154_trx_antenna_update();
2213 
2214     // Set PPIs
2215     nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_TXEN, TRX_RAMP_UP_SW_TRIGGER, false);
2216 
2217     trigger_disable_to_start_rampup();
2218 
2219     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2220 }
2221 
nrf_802154_trx_continuous_carrier_restart(void)2222 void nrf_802154_trx_continuous_carrier_restart(void)
2223 {
2224     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2225 
2226     NRF_802154_ASSERT(m_trx_state == TRX_STATE_CONTINUOUS_CARRIER);
2227 
2228     // Continuous carrier PPIs are configured without self-disabling
2229     // Triggering RADIO.TASK_DISABLE causes ramp-down -> RADIO.EVENTS_DISABLED -> EGU.TASK -> EGU.EVENT ->
2230     // RADIO.TASK_TXEN -> ramp_up -> new continous carrier
2231     radio_robust_disable();
2232 
2233     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2234 }
2235 
continuous_carrier_abort(void)2236 static void continuous_carrier_abort(void)
2237 {
2238     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2239 
2240     nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_TXEN, false);
2241 
2242     fem_for_pa_reset();
2243 
2244     radio_robust_disable();
2245 
2246     m_trx_state = TRX_STATE_FINISHED;
2247 
2248     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2249 }
2250 
nrf_802154_trx_modulated_carrier(const void * p_transmit_buffer,const nrf_802154_fal_tx_power_split_t * p_tx_power)2251 void nrf_802154_trx_modulated_carrier(const void                            * p_transmit_buffer,
2252                                       const nrf_802154_fal_tx_power_split_t * p_tx_power)
2253 {
2254     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2255 
2256     NRF_802154_ASSERT((m_trx_state == TRX_STATE_IDLE) || (m_trx_state == TRX_STATE_FINISHED));
2257     NRF_802154_ASSERT(p_transmit_buffer != NULL);
2258 
2259     m_trx_state = TRX_STATE_MODULATED_CARRIER;
2260 
2261     // Set Tx Power
2262     txpower_set(p_tx_power->radio_tx_power);
2263 
2264     // Set Tx buffer
2265     nrf_radio_packetptr_set(NRF_RADIO, p_transmit_buffer);
2266 
2267     // Set shorts
2268     nrf_radio_shorts_set(NRF_RADIO, SHORTS_MOD_CARRIER);
2269 
2270     // Set FEM
2271     fem_for_pa_set(p_tx_power->fem_pa_power_control);
2272 
2273     // Select antenna
2274     nrf_802154_trx_antenna_update();
2275 
2276     // Set PPIs
2277     nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_TXEN, TRX_RAMP_UP_SW_TRIGGER, false);
2278 
2279     trigger_disable_to_start_rampup();
2280 
2281     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2282 }
2283 
nrf_802154_trx_modulated_carrier_restart(void)2284 void nrf_802154_trx_modulated_carrier_restart(void)
2285 {
2286     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2287 
2288     NRF_802154_ASSERT(m_trx_state == TRX_STATE_MODULATED_CARRIER);
2289 
2290     // Modulated carrier PPIs are configured without self-disabling
2291     // Triggering RADIO.TASK_DISABLE causes ramp-down -> RADIO.EVENTS_DISABLED -> EGU.TASK -> EGU.EVENT ->
2292     // RADIO.TASK_TXEN -> ramp_up -> new modulated carrier
2293     radio_robust_disable();
2294 
2295     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2296 }
2297 
modulated_carrier_abort()2298 static void modulated_carrier_abort()
2299 {
2300     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2301 
2302     nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_TXEN, false);
2303 
2304     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2305 
2306     fem_for_pa_reset();
2307 
2308     radio_robust_disable();
2309 
2310     m_trx_state = TRX_STATE_FINISHED;
2311 
2312     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2313 }
2314 
2315 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
2316 
nrf_802154_trx_energy_detection(uint32_t ed_count)2317 void nrf_802154_trx_energy_detection(uint32_t ed_count)
2318 {
2319     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2320 
2321     NRF_802154_ASSERT((m_trx_state == TRX_STATE_FINISHED) || (m_trx_state == TRX_STATE_IDLE));
2322 
2323     m_trx_state = TRX_STATE_ENERGY_DETECTION;
2324 
2325     ed_count--;
2326     /* Check that vd_count will fit into defined bits of register */
2327 #if defined(RADIO_EDCNT_EDCNT_Msk)
2328     NRF_802154_ASSERT( (ed_count & (~RADIO_EDCNT_EDCNT_Msk)) == 0U);
2329 #endif
2330 
2331     nrf_radio_ed_loop_count_set(NRF_RADIO, ed_count);
2332 
2333     // Set shorts
2334     nrf_radio_shorts_set(NRF_RADIO, SHORTS_ED);
2335 
2336     // Enable IRQs
2337     nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_EDEND);
2338     nrf_radio_int_enable(NRF_RADIO, NRF_RADIO_INT_EDEND_MASK);
2339 
2340     // Set FEM
2341     fem_for_lna_set();
2342 
2343     // Select antenna
2344     nrf_802154_trx_antenna_update();
2345 
2346     // Set PPIs
2347     nrf_802154_trx_ppi_for_ramp_up_set(NRF_RADIO_TASK_RXEN, TRX_RAMP_UP_SW_TRIGGER, false);
2348 
2349     trigger_disable_to_start_rampup();
2350 
2351     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2352 }
2353 
energy_detection_finish(void)2354 static void energy_detection_finish(void)
2355 {
2356     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2357 
2358     nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_RXEN, false);
2359     fem_for_lna_reset();
2360 
2361     nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_EDEND_MASK);
2362     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2363 
2364     nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_EDSTOP);
2365     radio_robust_disable();
2366 
2367     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2368 }
2369 
energy_detection_abort(void)2370 static void energy_detection_abort(void)
2371 {
2372     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2373 
2374     energy_detection_finish();
2375     m_trx_state = TRX_STATE_FINISHED;
2376 
2377     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2378 }
2379 
irq_handler_ready(void)2380 static void irq_handler_ready(void)
2381 {
2382     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2383 
2384     nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_READY_MASK);
2385 
2386     nrf_802154_trx_ppi_for_ramp_up_reconfigure();
2387 
2388     switch (m_trx_state)
2389     {
2390         case TRX_STATE_TXFRAME:
2391             if (m_flags.ccastarted_notif_en)
2392             {
2393                 nrf_802154_trx_transmit_frame_ccastarted();
2394             }
2395             break;
2396 
2397         case TRX_STATE_RXFRAME:
2398             break;
2399 
2400         default:
2401             NRF_802154_ASSERT(false);
2402     }
2403 
2404     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2405 }
2406 
irq_handler_address(void)2407 static void irq_handler_address(void)
2408 {
2409     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2410 
2411     // At this point we can be certain that no more DISABLED events
2412     // comming from the time before the transmission/reception started
2413     // will arrive. We can safely disable the DISABLED interrupt.
2414     nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_DISABLED_MASK);
2415 
2416     switch (m_trx_state)
2417     {
2418         case TRX_STATE_RXFRAME:
2419             if (m_flags.rxstarted_notif_en)
2420             {
2421                 nrf_802154_trx_receive_frame_started();
2422             }
2423             break;
2424 
2425         case TRX_STATE_RXACK:
2426             m_flags.rssi_started = true;
2427             nrf_802154_trx_receive_ack_started();
2428             break;
2429 
2430         case TRX_STATE_TXFRAME:
2431             nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_ADDRESS_MASK);
2432             m_flags.tx_started = true;
2433             nrf_802154_trx_transmit_frame_started();
2434             break;
2435 
2436         case TRX_STATE_TXACK:
2437             nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_ADDRESS_MASK);
2438             nrf_802154_trx_transmit_ack_started();
2439             break;
2440 
2441         default:
2442             NRF_802154_ASSERT(false);
2443     }
2444 
2445     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2446 }
2447 
irq_handler_bcmatch(void)2448 static void irq_handler_bcmatch(void)
2449 {
2450     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2451 
2452     uint8_t current_bcc;
2453     uint8_t next_bcc;
2454 
2455     NRF_802154_ASSERT(m_trx_state == TRX_STATE_RXFRAME);
2456 
2457     m_flags.psdu_being_received = true;
2458 
2459     // If CRCERROR event is set, it means that events are handled out of order due to software
2460     // latency. Just skip this handler in this case - frame will be dropped.
2461     if (nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_CRCERROR))
2462     {
2463         nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2464         return;
2465     }
2466 
2467     current_bcc = nrf_radio_bcc_get(NRF_RADIO) / 8U;
2468 
2469     next_bcc = nrf_802154_trx_receive_frame_bcmatched(current_bcc);
2470 
2471     if (next_bcc > current_bcc)
2472     {
2473         /* Note: If we don't make it before given octet is received by RADIO bcmatch will not be triggered.
2474          * The fact that filtering may be not completed at the call to nrf_802154_trx_receive_received handler
2475          * should be handled by the handler.
2476          */
2477         nrf_radio_bcc_set(NRF_RADIO, next_bcc * 8);
2478     }
2479 
2480     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2481 }
2482 
irq_handler_crcerror(void)2483 static void irq_handler_crcerror(void)
2484 {
2485     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2486 
2487     switch (m_trx_state)
2488     {
2489         case TRX_STATE_RXFRAME:
2490             rxframe_finish();
2491             /* On crc error TIMER is not needed, no ACK may be sent */
2492             timer_stop_and_clear();
2493             m_trx_state = TRX_STATE_FINISHED;
2494             nrf_802154_trx_receive_frame_crcerror();
2495             break;
2496 
2497         case TRX_STATE_RXACK:
2498             rxack_finish();
2499             m_trx_state = TRX_STATE_FINISHED;
2500             nrf_802154_trx_receive_ack_crcerror();
2501             break;
2502 
2503         default:
2504             NRF_802154_ASSERT(false);
2505     }
2506 
2507     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2508 }
2509 
irq_handler_crcok(void)2510 static void irq_handler_crcok(void)
2511 {
2512     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2513 
2514     switch (m_trx_state)
2515     {
2516         case TRX_STATE_RXFRAME:
2517             m_flags.rssi_started = true;
2518             rxframe_finish();
2519             m_trx_state = TRX_STATE_RXFRAME_FINISHED;
2520             nrf_802154_trx_receive_frame_received();
2521             break;
2522 
2523         case TRX_STATE_RXACK:
2524             rxack_finish();
2525             m_trx_state = TRX_STATE_FINISHED;
2526             nrf_802154_trx_receive_ack_received();
2527             break;
2528 
2529         default:
2530             NRF_802154_ASSERT(false);
2531     }
2532 
2533     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2534 }
2535 
txframe_finish_disable_ppis(bool cca)2536 static void txframe_finish_disable_ppis(bool cca)
2537 {
2538     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2539 
2540     nrf_802154_trx_ppi_for_ramp_up_clear(cca ? NRF_RADIO_TASK_RXEN : NRF_RADIO_TASK_TXEN, false);
2541     nrf_802154_trx_ppi_for_extra_cca_attempts_clear(); // fine to call unconditionally
2542 
2543     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2544 }
2545 
txframe_finish_disable_ints(void)2546 static void txframe_finish_disable_ints(void)
2547 {
2548     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2549 
2550     nrf_radio_int_disable(NRF_RADIO,
2551                           NRF_RADIO_INT_PHYEND_MASK |
2552                           NRF_RADIO_INT_CCAIDLE_MASK |
2553                           NRF_RADIO_INT_CCABUSY_MASK |
2554                           NRF_RADIO_INT_ADDRESS_MASK |
2555                           NRF_RADIO_INT_READY_MASK |
2556                           NRF_RADIO_INT_DISABLED_MASK);
2557 
2558     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2559 }
2560 
txframe_finish(void)2561 static void txframe_finish(void)
2562 {
2563     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2564 
2565     /* Below shown what is happening in the hardware
2566      *
2567      * Due to short RADIO.SHORT_PHYEND_DISABLE the RADIO is in TXDISABLE (currently ramping down for 21us) state or
2568      * has already reached DISABLED state (if we entered into ISR with greater latency)
2569      *
2570      * Even if RADIO reaches state DISABLED (event DISABLED was triggered by short), no transmission will be triggered
2571      * as PPI_EGU_RAMP_UP is self-disabling PPI channel.
2572      *
2573      * If FEM is in use the PPI_EGU_TIMER_START might be triggered if radio reached DISABLED state,
2574      * so the TIMER may start counting from the value on which FEM activation finished. The TIMER's CC registers
2575      * are set in the past so even if TIMER started no spurious FEM PA activation will occur.
2576      * We need to disable PPI_EGU_TIMER_START and then shutdown TIMER as it is not used.
2577      */
2578     txframe_finish_disable_ppis(m_transmit_with_cca);
2579 
2580     fem_for_tx_reset(m_transmit_with_cca);
2581 
2582     txframe_finish_disable_ints();
2583 
2584     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2585 
2586     m_flags.tx_started             = false;
2587     m_flags.missing_receive_buffer = false;
2588 
2589     /* Current state of peripherals
2590      * RADIO is either in TXDISABLE or DISABLED
2591      * FEM is powered but PA mode will be turned off on entry into DISABLED state or is already turned off
2592      * TIMER is shutdown
2593      * All PPIs that were used are disabled (forks are cleared if used)
2594      * RADIO.SHORTS are cleared
2595      */
2596 
2597     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2598 }
2599 
transmit_frame_abort(void)2600 static void transmit_frame_abort(void)
2601 {
2602     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2603 
2604     txframe_finish_disable_ppis(m_transmit_with_cca);
2605     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2606 
2607     fem_for_tx_reset(m_transmit_with_cca);
2608 
2609     txframe_finish_disable_ints();
2610 
2611     m_flags.tx_started             = false;
2612     m_flags.missing_receive_buffer = false;
2613 
2614     nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_CCASTOP);
2615     radio_robust_disable();
2616 
2617     m_trx_state = TRX_STATE_FINISHED;
2618 
2619     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2620 }
2621 
txack_finish(void)2622 static void txack_finish(void)
2623 {
2624     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2625 
2626     /* Below shown what is happening in the hardware
2627      *
2628      * Due to short RADIO.SHORT_PHYEND_DISABLE the RADIO is in TXDISABLE (currently ramping down for 21us) state or
2629      * has already reached DISABLED state (if we entered into ISR with greater latency)
2630      *
2631      * Even if RADIO reaches state DISABLED (event DISABLED was triggered by short), no transmission will be triggered
2632      * as only PPI_TIMER_TX_ACK was enabled.
2633      *
2634      * FEM will disable PA mode on RADIO.DISABLED event
2635      *
2636      * The TIMER was counting to trigger RADIO ramp up and FEM (if required). The TIMER is configured
2637      * to trigger STOP task on one of these events (whichever is later). As we finished the TIMER is
2638      * stopped now, and there is no PPIs starting it automatically by the hardware.
2639      */
2640     nrf_802154_trx_ppi_for_ack_tx_clear();
2641 
2642     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2643 
2644     mpsl_fem_pa_configuration_clear();
2645 
2646     nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE,
2647                              NRF_TIMER_SHORT_COMPARE0_STOP_MASK |
2648                              NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
2649 
2650     timer_stop_and_clear();
2651 
2652     nrf_radio_int_disable(NRF_RADIO,
2653                           NRF_RADIO_INT_PHYEND_MASK | NRF_RADIO_INT_ADDRESS_MASK |
2654                           NRF_RADIO_INT_DISABLED_MASK);
2655 
2656     /* Current state of peripherals
2657      * RADIO is either in TXDISABLE or DISABLED
2658      * FEM is powered but PA mode will be turned off on entry into DISABLED state or is already turned off
2659      * TIMER is shutdown
2660      * All PPIs that were used are disabled (forks are cleared if used)
2661      * RADIO.SHORTS are cleared
2662      */
2663 
2664     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2665 }
2666 
transmit_ack_abort(void)2667 static void transmit_ack_abort(void)
2668 {
2669     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2670 
2671     nrf_802154_trx_ppi_for_ack_tx_clear();
2672 
2673     nrf_radio_shorts_set(NRF_RADIO, SHORTS_IDLE);
2674 
2675     mpsl_fem_pa_configuration_clear();
2676 
2677     nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE,
2678                              NRF_TIMER_SHORT_COMPARE0_STOP_MASK |
2679                              NRF_TIMER_SHORT_COMPARE1_STOP_MASK);
2680 
2681     timer_stop_and_clear();
2682 
2683     nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_PHYEND_MASK | NRF_RADIO_INT_ADDRESS_MASK);
2684 
2685     radio_robust_disable();
2686 
2687     m_trx_state = TRX_STATE_FINISHED;
2688 
2689     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2690 }
2691 
irq_handler_phyend(void)2692 static void irq_handler_phyend(void)
2693 {
2694     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2695 
2696     switch (m_trx_state)
2697     {
2698         case TRX_STATE_TXFRAME:
2699             txframe_finish();
2700             m_trx_state = TRX_STATE_FINISHED;
2701             nrf_802154_trx_transmit_frame_transmitted();
2702             break;
2703 
2704         case TRX_STATE_TXACK:
2705             txack_finish();
2706             m_trx_state = TRX_STATE_FINISHED;
2707             nrf_802154_trx_transmit_ack_transmitted();
2708             break;
2709 
2710         default:
2711             NRF_802154_ASSERT(false);
2712     }
2713 
2714     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2715 }
2716 
go_idle_finish(void)2717 static void go_idle_finish(void)
2718 {
2719     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH);
2720 
2721     nrf_radio_int_disable(NRF_RADIO, NRF_RADIO_INT_DISABLED_MASK);
2722 
2723     fem_power_down_now();
2724 
2725     m_trx_state = TRX_STATE_IDLE;
2726 
2727     nrf_802154_trx_go_idle_finished();
2728 
2729     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH);
2730 }
2731 
irq_handler_disabled(void)2732 static void irq_handler_disabled(void)
2733 {
2734     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2735 
2736     switch (m_trx_state)
2737     {
2738         case TRX_STATE_GOING_IDLE:
2739             go_idle_finish();
2740             break;
2741 
2742         case TRX_STATE_TXFRAME:
2743         case TRX_STATE_TXACK:
2744         case TRX_STATE_RXFRAME:
2745             // Robust radio ramp-down requires that RADIO.DISABLE is cleared. If the ramp-up was
2746             // triggered by software, the event was cleared already immediately after triggering
2747             // RADIO.DISABLE task. If the ramp-up was triggered by (D)PPI, the event would need
2748             // to be cleared. The IRQ handler does that on entry to irq_handler_disabled.
2749             // The interrupt must not be disabled here though. It is possible that this handler is executed
2750             // before the radio ramp-up finishes as a result of a ramp-down triggered earlier. This is more
2751             // probable on platforms where code execution is fast and the critical section that configures
2752             // radio ramp-up is exited before that ramp-up finishes. To allow for this interrupt to fire again
2753             // when the ramp-up finishes and for the DISABLED event to be cleared once more, do not disable
2754             // the interrupt now. It's disabled in ADDRESS event handler.
2755             break;
2756 
2757         default:
2758             NRF_802154_ASSERT(false);
2759     }
2760 
2761     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2762 }
2763 
irq_handler_ccaidle(void)2764 static void irq_handler_ccaidle(void)
2765 {
2766     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2767 
2768     switch (m_trx_state)
2769     {
2770         case TRX_STATE_STANDALONE_CCA:
2771             standalone_cca_finish();
2772             m_trx_state = TRX_STATE_FINISHED;
2773             nrf_802154_trx_standalone_cca_finished(true);
2774             break;
2775 
2776         case TRX_STATE_TXFRAME:
2777             nrf_802154_trx_transmit_frame_ccaidle();
2778             break;
2779 
2780         default:
2781             NRF_802154_ASSERT(false);
2782     }
2783 
2784     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2785 }
2786 
irq_handler_ccabusy(void)2787 static void irq_handler_ccabusy(void)
2788 {
2789     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2790 
2791     switch (m_trx_state)
2792     {
2793         case TRX_STATE_TXFRAME:
2794             NRF_802154_ASSERT(m_transmit_with_cca);
2795 
2796             if (m_remaining_cca_attempts > 1)
2797             {
2798                 /* There are still remaining CCA attempts to be performed.
2799                  * Start of next CCA has already been triggered by (D)PPI.
2800                  *
2801                  * Assumptions:
2802                  * - RADIO is in RXIDLE and will transition to TX on CCAIDLE
2803                  * - TIMER is stopped
2804                  * - FEM has LNA ramped up and will ramp-up PA on CCAIDLE
2805                  */
2806                 m_remaining_cca_attempts--;
2807                 if (m_remaining_cca_attempts == 1)
2808                 {
2809                     /* The last CCA attempt was just triggered through a (D)PPI that connects
2810                      * RADIO->EVENTS_CCABUSY to RADIO->TASKS_CCASTART. Clear that (D)PPI so that
2811                      * there's no next CCA attempt. Also, configure an additional short that will
2812                      * disable the RADIO in case busy channel is detected so that consistency with
2813                      * single CCA approach is maintained. The RADIO is expected to be disabled
2814                      * when CCA concludes with result busy.
2815                      */
2816                     nrf_802154_trx_ppi_for_extra_cca_attempts_clear();
2817                     nrf_radio_shorts_set(
2818                         NRF_RADIO,
2819                         SHORTS_MULTI_CCA_TX | NRF_RADIO_SHORT_CCABUSY_DISABLE_MASK);
2820 
2821                     /* If the handler was delayed for the duration of a single CCA procedure, a race
2822                      * condition between the lines above and the end of CCA might occur. If that CCA
2823                      * detects busy channel, there are three cases how the CCABUSY might be placed in
2824                      * time relatively to the lines above:
2825                      * - before (D)PPI is disconnected and the shorts are reconfigured;
2826                      * - after (D)PPI is disconnected and before the shorts are reconfigured;
2827                      * - after (D)PPI id disconnected and the shorts are reconfigured;
2828                      *
2829                      * The recovery procedure for the last case is to manually trigger
2830                      * RADIO->TASKS_CCASTOP and RADIO->TASKS_DISABLE. For the second case it would
2831                      * be enough to only trigger RADIO->TASKS_DISABLE, but the cases cannot be
2832                      * distinguished in code and RADIO->TASKS_CCASTOP is harmless in the second case,
2833                      * so the same recovery procedure fixes both the second and the third case.
2834                      * For the first case such procedure will cause one fewer CCA attempt than
2835                      * requested. That's a low price to pay to ensure the RADIO always ends
2836                      * up in the expected, well-defined state, especially that this race should
2837                      * happen extremely rarely.
2838                      */
2839                     if (nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY))
2840                     {
2841                         /* RADIO->EVENTS_CCABUSY occurred during IRQ handler execution. Manually
2842                          * drive RADIO to state that should have been achieved through hardware and
2843                          * finish the procedure.
2844                          */
2845                         nrf_radio_task_trigger(NRF_RADIO, NRF_RADIO_TASK_CCASTOP);
2846                         radio_robust_disable();
2847                         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY);
2848 
2849                         txframe_finish();
2850                         m_trx_state = TRX_STATE_FINISHED;
2851                         nrf_802154_trx_transmit_frame_ccabusy();
2852                     }
2853                 }
2854             }
2855             else
2856             {
2857                 txframe_finish();
2858                 m_trx_state = TRX_STATE_FINISHED;
2859                 nrf_802154_trx_transmit_frame_ccabusy();
2860             }
2861             break;
2862 
2863         case TRX_STATE_STANDALONE_CCA:
2864             standalone_cca_finish();
2865             m_trx_state = TRX_STATE_FINISHED;
2866             nrf_802154_trx_standalone_cca_finished(false);
2867             break;
2868 
2869         default:
2870             NRF_802154_ASSERT(false);
2871     }
2872 
2873     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2874 }
2875 
irq_handler_edend(void)2876 static void irq_handler_edend(void)
2877 {
2878     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2879 
2880     NRF_802154_ASSERT(m_trx_state == TRX_STATE_ENERGY_DETECTION);
2881 
2882     uint8_t ed_sample = nrf_radio_ed_sample_get(NRF_RADIO);
2883 
2884     energy_detection_finish();
2885     m_trx_state = TRX_STATE_FINISHED;
2886 
2887     nrf_802154_trx_energy_detection_finished(ed_sample);
2888 
2889     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2890 }
2891 
2892 #if defined(RADIO_INTENSET_SYNC_Msk)
irq_handler_sync(void)2893 static void irq_handler_sync(void)
2894 {
2895     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2896 
2897     NRF_802154_ASSERT(m_trx_state == TRX_STATE_RXFRAME);
2898 
2899     nrf_802154_trx_receive_frame_prestarted();
2900 
2901     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2902 }
2903 
2904 #endif
2905 
nrf_802154_radio_irq_handler(void)2906 void nrf_802154_radio_irq_handler(void)
2907 {
2908     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2909 
2910     // Prevent interrupting of this handler by requests from higher priority code.
2911     nrf_802154_critical_section_forcefully_enter();
2912 
2913 #if defined(RADIO_INTENSET_SYNC_Msk)
2914     // Note: For NRF_RADIO_EVENT_SYNC we enable interrupt through EGU.
2915     // That's why we check here EGU's EGU_SYNC_INTMASK.
2916     // The RADIO does not have interrupt from SYNC event.
2917     if (nrf_egu_int_enable_check(NRF_802154_EGU_INSTANCE, EGU_SYNC_INTMASK) &&
2918         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_SYNC))
2919     {
2920         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_SYNC);
2921         nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_SYNC_EVENT);
2922 
2923         irq_handler_sync();
2924     }
2925 #endif
2926 
2927     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_READY_MASK) &&
2928         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_READY))
2929     {
2930         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_READY);
2931 
2932         irq_handler_ready();
2933     }
2934 
2935     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_ADDRESS_MASK) &&
2936         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS))
2937     {
2938         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS);
2939 
2940         irq_handler_address();
2941     }
2942 
2943     // Check MAC frame header.
2944     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_BCMATCH_MASK) &&
2945         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH))
2946     {
2947         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_BCMATCH);
2948 
2949         irq_handler_bcmatch();
2950     }
2951 
2952     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_CRCERROR_MASK) &&
2953         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_CRCERROR))
2954     {
2955         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCERROR);
2956 
2957         irq_handler_crcerror();
2958     }
2959 
2960     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_CRCOK_MASK) &&
2961         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_CRCOK))
2962     {
2963         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CRCOK);
2964 
2965         irq_handler_crcok();
2966     }
2967 
2968     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_PHYEND_MASK) &&
2969         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_PHYEND))
2970     {
2971         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND);
2972 
2973         irq_handler_phyend();
2974     }
2975 
2976     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_DISABLED_MASK) &&
2977         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_DISABLED))
2978     {
2979         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED);
2980 
2981         irq_handler_disabled();
2982     }
2983 
2984     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_CCAIDLE_MASK) &&
2985         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE))
2986     {
2987         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE);
2988 
2989         irq_handler_ccaidle();
2990     }
2991 
2992     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_CCABUSY_MASK) &&
2993         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY))
2994     {
2995         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_CCABUSY);
2996 
2997         irq_handler_ccabusy();
2998     }
2999 
3000     if (nrf_radio_int_enable_check(NRF_RADIO, NRF_RADIO_INT_EDEND_MASK) &&
3001         nrf_radio_event_check(NRF_RADIO, NRF_RADIO_EVENT_EDEND))
3002     {
3003         nrf_radio_event_clear(NRF_RADIO, NRF_RADIO_EVENT_EDEND);
3004 
3005         irq_handler_edend();
3006     }
3007 
3008     nrf_802154_critical_section_exit();
3009 
3010     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
3011 }
3012 
3013 #if NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
RADIO_IRQHandler(void)3014 void RADIO_IRQHandler(void)
3015 {
3016     nrf_802154_radio_irq_handler();
3017 }
3018 
3019 #endif // NRF_802154_INTERNAL_RADIO_IRQ_HANDLING
3020 
3021 #if defined(RADIO_INTENSET_SYNC_Msk)
nrf_802154_trx_swi_irq_handler(void)3022 void nrf_802154_trx_swi_irq_handler(void)
3023 {
3024     // If this handler is preempted by MARGIN, RADIO IRQ might be set to pending
3025     // and executed after MARGIN processing is finished, i.e. after the end of a timeslot.
3026     // To prevent that from happening, the handler is executed with disabled interrupts.
3027     nrf_802154_mcu_critical_state_t mcu_crit_state;
3028 
3029     nrf_802154_mcu_critical_enter(mcu_crit_state);
3030 
3031     if (nrf_egu_int_enable_check(NRF_802154_EGU_INSTANCE, EGU_SYNC_INTMASK) &&
3032         nrf_egu_event_check(NRF_802154_EGU_INSTANCE, EGU_SYNC_EVENT))
3033     {
3034         nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, EGU_SYNC_EVENT);
3035 
3036         // We are in SWI_IRQHandler, which priority is usually lower than RADIO_IRQHandler.
3037         // To avoid problems with critical sections, trigger RADIO_IRQ manually.
3038         // - If we are not in critical section, RADIO_IRQ will start shortly (calling
3039         // nrf_802154_radio_irq_handler) preempting current SWI_IRQHandler. From
3040         // nrf_802154_radio_irq_handler we acquire critical section and
3041         // process sync event.
3042         // If we are in critical section, the RADIO_IRQ is disabled on NVIC.
3043         // Following will make it pending, and processing of RADIO_IRQ will start
3044         // when critical section is left.
3045 
3046         nrf_802154_irq_set_pending(nrfx_get_irq_number(NRF_RADIO));
3047     }
3048 
3049     nrf_802154_mcu_critical_exit(mcu_crit_state);
3050 }
3051 
3052 #endif
3053 
nrf_802154_trx_radio_end_event_handle_get(void)3054 const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_end_event_handle_get(void)
3055 {
3056     static const nrf_802154_sl_event_handle_t r = {
3057 #if defined(DPPI_PRESENT)
3058         .event_addr = NRF_802154_DPPI_RADIO_END,
3059         .shared     = true
3060 #else
3061         .event_addr = (uint32_t)&NRF_RADIO->EVENTS_END
3062 #endif
3063     };
3064 
3065     return &r;
3066 }
3067 
nrf_802154_trx_radio_ready_event_handle_get(void)3068 const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_ready_event_handle_get(void)
3069 {
3070     static const nrf_802154_sl_event_handle_t r = {
3071 #if defined(DPPI_PRESENT)
3072         .event_addr = NRF_802154_DPPI_RADIO_READY,
3073         .shared     = true
3074 #else
3075         .event_addr = (uint32_t)&NRF_RADIO->EVENTS_READY
3076 #endif
3077     };
3078 
3079     return &r;
3080 }
3081 
nrf_802154_trx_radio_crcok_event_handle_get(void)3082 const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_crcok_event_handle_get(void)
3083 {
3084     static const nrf_802154_sl_event_handle_t r = {
3085         .event_addr = (uint32_t)&NRF_RADIO->EVENTS_CRCOK,
3086 #if defined(DPPI_PRESENT)
3087         .shared = false
3088 #endif
3089     };
3090 
3091     return &r;
3092 }
3093 
nrf_802154_trx_radio_phyend_event_handle_get(void)3094 const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_phyend_event_handle_get(void)
3095 {
3096     static const nrf_802154_sl_event_handle_t r = {
3097 #if defined(DPPI_PRESENT)
3098         .event_addr = NRF_802154_DPPI_RADIO_PHYEND,
3099         .shared     = true
3100 #else
3101         .event_addr = (uint32_t)&NRF_RADIO->EVENTS_PHYEND
3102 #endif
3103     };
3104 
3105     return &r;
3106 }
3107