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