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