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