1 /*
2  * Copyright (c) 2017 - 2023, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  */
34 
35 /**
36  * @file
37  *   This file implements Finite State Machine of nRF 802.15.4 radio driver.
38  *
39  */
40 
41 #define NRF_802154_MODULE_ID NRF_802154_DRV_MODULE_ID_CORE
42 
43 #include "nrf_802154_core.h"
44 
45 #include <assert.h>
46 #include <stdbool.h>
47 #include <stdint.h>
48 #include <string.h>
49 
50 #include "nrf_802154.h"
51 #include "nrf_802154_config.h"
52 #include "nrf_802154_const.h"
53 #include "nrf_802154_critical_section.h"
54 #include "nrf_802154_debug.h"
55 #include "nrf_802154_notification.h"
56 #include "nrf_802154_pib.h"
57 #include "nrf_802154_procedures_duration.h"
58 #include "nrf_802154_rssi.h"
59 #include "nrf_802154_rx_buffer.h"
60 #include "nrf_802154_sl_timer.h"
61 #include "nrf_802154_sl_utils.h"
62 #include "nrf_802154_stats.h"
63 #include "nrf_802154_utils.h"
64 #include "nrf_802154_trx.h"
65 #include "nrf_802154_tx_work_buffer.h"
66 #include "nrf_802154_tx_power.h"
67 #include "nrf_802154_types_internal.h"
68 #include "nrf_802154_utils.h"
69 #include "drivers/nrfx_errors.h"
70 #include "hal/nrf_radio.h"
71 #include "mac_features/nrf_802154_filter.h"
72 #include "mac_features/nrf_802154_frame_parser.h"
73 #include "mac_features/ack_generator/nrf_802154_ack_generator.h"
74 #include "rsch/nrf_802154_rsch.h"
75 #include "rsch/nrf_802154_rsch_crit_sect.h"
76 #include "timer/nrf_802154_timer_coord.h"
77 #include "platform/nrf_802154_hp_timer.h"
78 #include "platform/nrf_802154_irq.h"
79 #include "protocol/mpsl_fem_protocol_api.h"
80 
81 #include "nrf_802154_core_hooks.h"
82 #include "nrf_802154_sl_ant_div.h"
83 
84 /// Delay before first check of received frame: 24 bits is PHY header and MAC Frame Control field.
85 #define BCC_INIT                    (3 * 8)
86 
87 /// Duration of single iteration of Energy Detection procedure
88 #define ED_ITER_DURATION            128U
89 /// Overhead of hardware preparation for ED procedure (aTurnaroundTime) [number of iterations]
90 #define ED_ITERS_OVERHEAD           2U
91 
92 #define MAX_CRIT_SECT_TIME          60   ///< Maximal time that the driver spends in single critical section.
93 
94 #define LQI_VALUE_FACTOR            4    ///< Factor needed to calculate LQI value based on data from RADIO peripheral
95 #define LQI_MAX                     0xff ///< Maximal LQI value
96 
97 /** Get LQI of given received packet. If CRC is calculated by hardware LQI is included instead of CRC
98  *  in the frame. Length is stored in byte with index 0; CRC is 2 last bytes.
99  */
100 #define RX_FRAME_LQI(data)          ((data)[(data)[0] - 1])
101 
102 /** Timeout value when waiting for ntf_802154_trx_receive_frame_started after ntf_802154_trx_receive_frame_prestarted.
103  *  Timeout value in microseconds. The time equals to whole synchronization header (SHR) duration of 802.15.4 frame.
104  */
105 #define PRESTARTED_TIMER_TIMEOUT_US (160U)
106 
107 #if NRF_802154_RX_BUFFERS > 1
108 /// Pointer to currently used receive buffer.
109 static rx_buffer_t * mp_current_rx_buffer;
110 
111 #else
112 /// If there is only one buffer use const pointer to the receive buffer.
113 static rx_buffer_t * const mp_current_rx_buffer = &nrf_802154_rx_buffers[0];
114 
115 #endif
116 
117 static uint8_t                       * mp_ack;                 ///< Pointer to Ack frame buffer.
118 static uint8_t                       * mp_tx_data;             ///< Pointer to the data to transmit.
119 static uint32_t                        m_ed_time_left;         ///< Remaining time of the current energy detection procedure [us].
120 static uint8_t                         m_ed_result;            ///< Result of the current energy detection procedure.
121 static uint8_t                         m_last_lqi;             ///< LQI of the last received non-ACK frame, corrected for the temperature.
122 static nrf_802154_fal_tx_power_split_t m_tx_power;             ///< Power to be used to transmit the current frame split into components.
123 static int8_t                          m_last_rssi;            ///< RSSI of the last received non-ACK frame, corrected for the temperature.
124 
125 static nrf_802154_frame_parser_data_t m_current_rx_frame_data; ///< RX frame parser data.
126 
127 static volatile radio_state_t m_state;                         ///< State of the radio driver.
128 
129 typedef struct
130 {
131     bool frame_filtered        : 1;                           ///< If frame being received passed filtering operation.
132     bool frame_parsed          : 1;                           ///< If frame being received has been parsed
133     bool rx_timeslot_requested : 1;                           ///< If timeslot for the frame being received is already requested.
134     bool tx_with_cca           : 1;                           ///< If currently transmitted frame is transmitted with cca.
135     bool tx_diminished_prio    : 1;                           ///< If priority of the current transmission should be diminished.
136 } nrf_802154_flags_t;
137 
138 static nrf_802154_flags_t m_flags;                            ///< Flags used to store the current driver state.
139 
140 static volatile bool        m_rsch_timeslot_is_granted;       ///< State of the RSCH timeslot.
141 static volatile rsch_prio_t m_rsch_priority = RSCH_PRIO_IDLE; ///< Last notified RSCH priority.
142 
143 /** @brief Value of argument @c notifications_mask to @ref nrf_802154_trx_receive_frame */
144 static nrf_802154_trx_receive_notifications_t m_trx_receive_frame_notifications_mask;
145 /** @brief Value of argument @c notifications_mask to @ref nrf_802154_trx_transmit_frame */
146 static nrf_802154_trx_transmit_notifications_t m_trx_transmit_frame_notifications_mask;
147 
148 static volatile uint8_t      m_rx_prestarted_trig_count;
149 static nrf_802154_sl_timer_t m_rx_prestarted_timer;
150 
151 /** @brief Value of Coex TX Request mode */
152 static nrf_802154_coex_tx_request_mode_t m_coex_tx_request_mode;
153 
154 /** @brief Identifier of currently active reception window. */
155 static uint32_t m_rx_window_id;
156 
157 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
158 #if !NRF_802154_FRAME_TIMESTAMP_ENABLED
159 #error NRF_802154_FRAME_TIMESTAMP_ENABLED == 0 when NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED != 0
160 #endif
161 #endif // NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
162 
163 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
164 static uint32_t m_listening_start_hp_timestamp;
165 
166 #endif
167 
168 static const nrf_802154_transmitted_frame_props_t m_default_frame_props =
169     NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT;
170 
171 /***************************************************************************************************
172  * @section Common core operations
173  **************************************************************************************************/
174 
175 static rsch_prio_t min_required_rsch_prio(radio_state_t state);
176 
request_preconditions_for_state(radio_state_t state)177 static void request_preconditions_for_state(radio_state_t state)
178 {
179     nrf_802154_rsch_crit_sect_prio_request(min_required_rsch_prio(state));
180 }
181 
182 /** Set driver state.
183  *
184  * @param[in]  state  Driver state to set.
185  */
state_set(radio_state_t state)186 static void state_set(radio_state_t state)
187 {
188     m_state = state;
189 
190     nrf_802154_log_local_event(NRF_802154_LOG_VERBOSITY_LOW,
191                                NRF_802154_LOG_LOCAL_EVENT_ID_CORE__SET_STATE,
192                                (uint32_t)state);
193 
194     request_preconditions_for_state(state);
195 }
196 
197 /** Specifies what ramp up trigger mode to use when handling RX or TX operation request.
198  *
199  * It is assumed that the DELAYED_TRX module always requests HW mode both RX and TX,
200  * while in all other cases SW mode is required.
201  *
202  * @param[in]  request_orig  Module that originates the request.
203  */
ramp_up_mode_choose(req_originator_t request_orig)204 static nrf_802154_trx_ramp_up_trigger_mode_t ramp_up_mode_choose(req_originator_t request_orig)
205 {
206     return (request_orig == REQ_ORIG_DELAYED_TRX) ?
207            TRX_RAMP_UP_HW_TRIGGER : TRX_RAMP_UP_SW_TRIGGER;
208 }
209 
210 /** Clear RX frame data. */
rx_data_clear(void)211 static void rx_data_clear(void)
212 {
213     (void)nrf_802154_frame_parser_data_init(mp_current_rx_buffer->data,
214                                             0U,
215                                             PARSE_LEVEL_NONE,
216                                             &m_current_rx_frame_data);
217 }
218 
219 /** Clear flags describing frame being received. */
rx_flags_clear(void)220 static void rx_flags_clear(void)
221 {
222     m_flags.frame_filtered        = false;
223     m_flags.rx_timeslot_requested = false;
224     m_flags.frame_parsed          = false;
225 }
226 
227 /** Wait for the RSSI measurement. */
rssi_measurement_wait(void)228 static void rssi_measurement_wait(void)
229 {
230     while (!nrf_802154_trx_rssi_sample_is_available())
231     {
232         // Intentionally empty: This function is called from a critical section.
233         // WFE would not be waken up by a RADIO event.
234     }
235 }
236 
237 /** Get the result of the last RSSI measurement.
238  *
239  * @returns  Result of the last RSSI measurement in dBm.
240  */
rssi_last_measurement_get(void)241 static int8_t rssi_last_measurement_get(void)
242 {
243     uint8_t rssi_sample = nrf_802154_trx_rssi_last_sample_get();
244 
245     rssi_sample = nrf_802154_rssi_sample_corrected_get(rssi_sample);
246 
247     return -((int8_t)rssi_sample);
248 }
249 
250 /** Get LQI of a received frame.
251  *
252  * @param[in]  p_data  Pointer to buffer containing PHR and PSDU of received frame
253  *
254  * @returns  LQI of given frame.
255  */
lqi_get(const uint8_t * p_data)256 static uint8_t lqi_get(const uint8_t * p_data)
257 {
258     uint32_t lqi = RX_FRAME_LQI(p_data);
259 
260     lqi  = nrf_802154_rssi_lqi_corrected_get(lqi);
261     lqi *= LQI_VALUE_FACTOR;
262 
263     if (lqi > LQI_MAX)
264     {
265         lqi = LQI_MAX;
266     }
267 
268     return (uint8_t)lqi;
269 }
270 
271 #if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
272 /**
273  * @brief Get timestamp made by timer coordinator.
274  *
275  * @note This function increments the returned value by 1 us if the timestamp is equal to the
276  *       @ref NRF_802154_NO_TIMESTAMP value to indicate that the timestamp is available.
277  *
278  * @returns Timestamp [us] of the last event captured by timer coordinator frame or
279  *          @ref NRF_802154_NO_TIMESTAMP if the timestamp is inaccurate.
280  */
timer_coord_timestamp_get(void)281 static uint64_t timer_coord_timestamp_get(void)
282 {
283     uint64_t timestamp          = NRF_802154_NO_TIMESTAMP;
284     bool     timestamp_received = nrf_802154_timer_coord_timestamp_get(&timestamp);
285 
286     if (!timestamp_received)
287     {
288         timestamp = NRF_802154_NO_TIMESTAMP;
289     }
290     else if (timestamp == NRF_802154_NO_TIMESTAMP)
291     {
292         timestamp++;
293     }
294     else
295     {
296         // Return timestamp without correction
297     }
298 
299     return timestamp;
300 }
301 
302 #endif
303 
received_frame_notify(uint8_t * p_data)304 static void received_frame_notify(uint8_t * p_data)
305 {
306     nrf_802154_notify_received(p_data, m_last_rssi, m_last_lqi);
307 }
308 
309 /** Allow nesting critical sections and notify MAC layer that a frame was received. */
received_frame_notify_and_nesting_allow(uint8_t * p_data)310 static void received_frame_notify_and_nesting_allow(uint8_t * p_data)
311 {
312     nrf_802154_critical_section_nesting_allow();
313 
314     received_frame_notify(p_data);
315 
316     nrf_802154_critical_section_nesting_deny();
317 }
318 
319 /** Notify MAC layer that receive procedure failed. */
receive_failed_notify(nrf_802154_rx_error_t error)320 static void receive_failed_notify(nrf_802154_rx_error_t error)
321 {
322     nrf_802154_critical_section_nesting_allow();
323 
324     // Don't care about the result - if the notification cannot be performed
325     // no impact on the device's operation is expected
326     (void)nrf_802154_notify_receive_failed(error, m_rx_window_id, true);
327 
328     nrf_802154_critical_section_nesting_deny();
329 }
330 
331 /** Notify MAC layer that transmission of requested frame has started. */
transmit_started_notify(void)332 static void transmit_started_notify(void)
333 {
334     uint8_t * p_frame = mp_tx_data;
335 
336     if (nrf_802154_core_hooks_tx_started(p_frame))
337     {
338         nrf_802154_tx_started(p_frame);
339     }
340 
341 }
342 
343 /** Notify MAC layer that transmission of ACK frame has started. */
transmit_ack_started_notify()344 static void transmit_ack_started_notify()
345 {
346     nrf_802154_core_hooks_tx_ack_started(mp_ack);
347     nrf_802154_tx_ack_started(mp_ack);
348 }
349 
350 /** Notify that reception of a frame has started. */
receive_started_notify(void)351 static void receive_started_notify(void)
352 {
353     const uint8_t * p_frame = mp_current_rx_buffer->data;
354 
355     nrf_802154_core_hooks_rx_started(p_frame);
356 }
357 
358 /** Notify MAC layer that a frame was transmitted. */
transmitted_frame_notify(uint8_t * p_ack,int8_t power,uint8_t lqi)359 static void transmitted_frame_notify(uint8_t * p_ack, int8_t power, uint8_t lqi)
360 {
361     uint8_t                           * p_frame  = mp_tx_data;
362     nrf_802154_transmit_done_metadata_t metadata = {0};
363 
364     metadata.data.transmitted.p_ack = p_ack;
365     metadata.data.transmitted.power = power;
366     metadata.data.transmitted.lqi   = lqi;
367 
368     if (p_ack == NULL)
369     {
370         metadata.data.transmitted.time = NRF_802154_NO_TIMESTAMP;
371     }
372     else
373     {
374         nrf_802154_stat_timestamp_read(&metadata.data.transmitted.time, last_ack_end_timestamp);
375     }
376 
377     nrf_802154_critical_section_nesting_allow();
378 
379     nrf_802154_core_hooks_transmitted(p_frame);
380 
381     nrf_802154_notify_transmitted(p_frame, &metadata);
382 
383     nrf_802154_critical_section_nesting_deny();
384 }
385 
386 /** Notify MAC layer that transmission procedure failed. */
transmit_failed_notify(uint8_t * p_frame,nrf_802154_tx_error_t error,const nrf_802154_transmit_done_metadata_t * p_meta)387 static void transmit_failed_notify(uint8_t                                   * p_frame,
388                                    nrf_802154_tx_error_t                       error,
389                                    const nrf_802154_transmit_done_metadata_t * p_meta)
390 {
391     if (nrf_802154_core_hooks_tx_failed(p_frame, error))
392     {
393         nrf_802154_notify_transmit_failed(p_frame, error, p_meta);
394     }
395 }
396 
397 /** Allow nesting critical sections and notify MAC layer that transmission procedure failed. */
transmit_failed_notify_and_nesting_allow(nrf_802154_tx_error_t error,const nrf_802154_transmit_done_metadata_t * p_meta)398 static void transmit_failed_notify_and_nesting_allow(
399     nrf_802154_tx_error_t                       error,
400     const nrf_802154_transmit_done_metadata_t * p_meta)
401 {
402     nrf_802154_critical_section_nesting_allow();
403 
404     transmit_failed_notify(mp_tx_data, error, p_meta);
405 
406     nrf_802154_critical_section_nesting_deny();
407 }
408 
409 /** Notify MAC layer that energy detection procedure ended. */
energy_detected_notify(uint8_t result)410 static void energy_detected_notify(uint8_t result)
411 {
412     nrf_802154_critical_section_nesting_allow();
413 
414     nrf_802154_notify_energy_detected(result);
415 
416     nrf_802154_critical_section_nesting_deny();
417 }
418 
419 /** Notify MAC layer that CCA procedure ended. */
cca_notify(bool result)420 static void cca_notify(bool result)
421 {
422     nrf_802154_critical_section_nesting_allow();
423 
424     nrf_802154_notify_cca(result);
425 
426     nrf_802154_critical_section_nesting_deny();
427 }
428 
429 /** Check if timeslot is currently granted.
430  *
431  * @retval true   The timeslot is granted.
432  * @retval false  The timeslot is not granted.
433  */
timeslot_is_granted(void)434 static bool timeslot_is_granted(void)
435 {
436     return m_rsch_timeslot_is_granted;
437 }
438 
antenna_diversity_is_enabled(void)439 static bool antenna_diversity_is_enabled(void)
440 {
441     return (NRF_802154_SL_ANT_DIV_MODE_DISABLED !=
442             nrf_802154_sl_ant_div_cfg_mode_get(NRF_802154_SL_ANT_DIV_OP_RX));
443 }
444 
445 /***************************************************************************************************
446  * @section RX buffer management
447  **************************************************************************************************/
448 
449 /** Set currently used rx buffer to given address.
450  *
451  * @param[in]  p_rx_buffer  Pointer to receive buffer that should be used now.
452  */
rx_buffer_in_use_set(rx_buffer_t * p_rx_buffer)453 static void rx_buffer_in_use_set(rx_buffer_t * p_rx_buffer)
454 {
455 #if NRF_802154_RX_BUFFERS > 1
456     mp_current_rx_buffer = p_rx_buffer;
457 #else
458     (void)p_rx_buffer;
459 #endif
460 }
461 
462 /** Check if currently there is available rx buffer.
463  *
464  * @retval true   There is available rx buffer.
465  * @retval false  Currently there is no available rx buffer.
466  */
rx_buffer_is_available(void)467 static bool rx_buffer_is_available(void)
468 {
469     return (mp_current_rx_buffer != NULL) && (mp_current_rx_buffer->free);
470 }
471 
472 /** Get pointer to available rx buffer.
473  *
474  * @returns Pointer to available rx buffer or NULL if rx buffer is not available.
475  */
rx_buffer_get(void)476 static uint8_t * rx_buffer_get(void)
477 {
478     return rx_buffer_is_available() ? mp_current_rx_buffer->data : NULL;
479 }
480 
481 /***************************************************************************************************
482  * @section ACK transmission management
483  **************************************************************************************************/
484 
485 /** Check if ACK is requested in given frame.
486  *
487  * @param[in]  p_frame  Pointer to a frame to check.
488  *
489  * @retval  true   ACK is requested in given frame.
490  * @retval  false  ACK is not requested in given frame.
491  */
ack_is_requested(const uint8_t * p_frame)492 static bool ack_is_requested(const uint8_t * p_frame)
493 {
494     nrf_802154_frame_parser_data_t frame_data;
495 
496     bool result = nrf_802154_frame_parser_data_init(p_frame,
497                                                     p_frame[PHR_OFFSET] + PHR_SIZE,
498                                                     PARSE_LEVEL_FCF_OFFSETS,
499                                                     &frame_data);
500 
501     return result && nrf_802154_frame_parser_ar_bit_is_set(&frame_data);
502 }
503 
504 /***************************************************************************************************
505  * @section Energy detection management
506  **************************************************************************************************/
507 
508 /** Setup next iteration of energy detection procedure.
509  *
510  *  Energy detection procedure is performed in iterations to make sure it is performed for requested
511  *  time regardless radio arbitration.
512  *
513  *  @param[inout] p_requested_ed_time_us  Remaining time of energy detection procedure [us]. Value will be updated
514  *                                        with time remaining for the next attempt of energy detection.
515  *  @param[out]   p_next_trx_ed_count     Number of trx energy detection iterations to perform.
516  *
517  *  @retval  true   Next iteration of energy detection procedure will be performed now.
518  *  @retval  false  Next iteration of energy detection procedure will not be performed now due to
519  *                  ending timeslot.
520  */
ed_iter_setup(uint32_t * p_requested_ed_time_us,uint32_t * p_next_trx_ed_count)521 static bool ed_iter_setup(uint32_t * p_requested_ed_time_us, uint32_t * p_next_trx_ed_count)
522 {
523     uint32_t iters_left_in_timeslot = nrf_802154_rsch_timeslot_us_left_get() / ED_ITER_DURATION;
524 
525     if (iters_left_in_timeslot > ED_ITERS_OVERHEAD)
526     {
527         /* Note that in single phy iters_left_in_timeslot will always be very big thus we will get here. */
528         iters_left_in_timeslot -= ED_ITERS_OVERHEAD;
529 
530         uint32_t requested_iters = *p_requested_ed_time_us / ED_ITER_DURATION;
531 
532         if (requested_iters < iters_left_in_timeslot)
533         {
534             /* We will finish all iterations before timeslot end, thus no time is left */
535             *p_requested_ed_time_us = 0U;
536         }
537         else
538         {
539             *p_requested_ed_time_us = *p_requested_ed_time_us -
540                                       (iters_left_in_timeslot * ED_ITER_DURATION);
541             requested_iters = iters_left_in_timeslot;
542         }
543 
544         *p_next_trx_ed_count = requested_iters;
545 
546         return true;
547     }
548 
549     return false;
550 }
551 
552 /***************************************************************************************************
553  * @section FSM transition request sub-procedures
554  **************************************************************************************************/
555 
min_required_rsch_prio(radio_state_t state)556 static rsch_prio_t min_required_rsch_prio(radio_state_t state)
557 {
558     switch (state)
559     {
560         case RADIO_STATE_SLEEP:
561             return RSCH_PRIO_IDLE;
562 
563         case RADIO_STATE_FALLING_ASLEEP:
564         case RADIO_STATE_RX:
565             return RSCH_PRIO_IDLE_LISTENING;
566 
567         case RADIO_STATE_RX_ACK:
568         case RADIO_STATE_ED:
569         case RADIO_STATE_CCA:
570             return RSCH_PRIO_RX;
571 
572         case RADIO_STATE_TX:
573         case RADIO_STATE_TX_ACK:
574 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
575         case RADIO_STATE_CONTINUOUS_CARRIER:
576         case RADIO_STATE_MODULATED_CARRIER:
577 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
578             return RSCH_PRIO_TX;
579 
580         case RADIO_STATE_CCA_TX:
581             if (m_flags.tx_diminished_prio)
582             {
583                 return RSCH_PRIO_IDLE_LISTENING;
584             }
585             else
586             {
587                 return RSCH_PRIO_TX;
588             }
589 
590         default:
591             assert(false);
592             return RSCH_PRIO_IDLE;
593     }
594 }
595 
is_state_allowed_for_prio(rsch_prio_t prio,radio_state_t state)596 static bool is_state_allowed_for_prio(rsch_prio_t prio, radio_state_t state)
597 {
598     return (min_required_rsch_prio(state) <= prio);
599 }
600 
are_preconditions_met(void)601 static bool are_preconditions_met(void)
602 {
603     rsch_prio_t   current_prio;
604     radio_state_t current_state;
605 
606     current_prio  = m_rsch_priority;
607     current_state = m_state;
608 
609     return is_state_allowed_for_prio(current_prio, current_state);
610 }
611 
action_needed(rsch_prio_t old_prio,rsch_prio_t new_prio,radio_state_t state)612 static int_fast8_t action_needed(rsch_prio_t old_prio, rsch_prio_t new_prio, radio_state_t state)
613 {
614     bool old_prio_allows = is_state_allowed_for_prio(old_prio, state);
615     bool new_prio_allows = is_state_allowed_for_prio(new_prio, state);
616 
617     int_fast8_t result = 0;
618 
619     if (old_prio_allows && !new_prio_allows)
620     {
621         result = -1;
622     }
623     else if (!old_prio_allows && new_prio_allows)
624     {
625         result = 1;
626     }
627 
628     return result;
629 }
630 
631 /** Check if time remaining in the timeslot is long enough to process whole critical section. */
remaining_timeslot_time_is_enough_for_crit_sect(void)632 static bool remaining_timeslot_time_is_enough_for_crit_sect(void)
633 {
634     return nrf_802154_rsch_timeslot_us_left_get() >= MAX_CRIT_SECT_TIME;
635 }
636 
637 /** Check if critical section can be processed at the moment.
638  *
639  * @note This function returns valid result only inside critical section.
640  *
641  * @retval true   There is enough time in current timeslot or timeslot is denied at the moment.
642  * @retval false  Current timeslot ends too shortly to process critical section inside.
643  */
critical_section_can_be_processed_now(void)644 static bool critical_section_can_be_processed_now(void)
645 {
646     return !timeslot_is_granted() || remaining_timeslot_time_is_enough_for_crit_sect();
647 }
648 
649 /** Enter critical section and verify if there is enough time to complete operations within. */
critical_section_enter_and_verify_timeslot_length(void)650 static bool critical_section_enter_and_verify_timeslot_length(void)
651 {
652     bool result = nrf_802154_critical_section_enter();
653 
654     if (result)
655     {
656         if (!critical_section_can_be_processed_now())
657         {
658             result = false;
659 
660             nrf_802154_critical_section_exit();
661         }
662     }
663 
664     return result;
665 }
666 
can_terminate_current_operation(radio_state_t state,nrf_802154_term_t term_lvl,bool receiving_psdu_now)667 static bool can_terminate_current_operation(radio_state_t     state,
668                                             nrf_802154_term_t term_lvl,
669                                             bool              receiving_psdu_now)
670 {
671     bool result = false;
672 
673     switch (state)
674     {
675         case RADIO_STATE_SLEEP:
676         case RADIO_STATE_FALLING_ASLEEP:
677 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
678         case RADIO_STATE_CONTINUOUS_CARRIER:
679         case RADIO_STATE_MODULATED_CARRIER:
680 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
681             result = true;
682             break;
683 
684         case RADIO_STATE_RX:
685             result = (term_lvl >= NRF_802154_TERM_802154) || !receiving_psdu_now;
686             break;
687 
688         case RADIO_STATE_TX_ACK:
689         case RADIO_STATE_CCA_TX:
690         case RADIO_STATE_TX:
691         case RADIO_STATE_RX_ACK:
692         case RADIO_STATE_ED:
693         case RADIO_STATE_CCA:
694             result = (term_lvl >= NRF_802154_TERM_802154);
695             break;
696 
697         default:
698             assert(false);
699     }
700 
701     return result;
702 }
703 
operation_terminated_notify(radio_state_t state,bool receiving_psdu_now)704 static void operation_terminated_notify(radio_state_t state, bool receiving_psdu_now)
705 {
706     switch (state)
707     {
708         case RADIO_STATE_SLEEP:
709         case RADIO_STATE_FALLING_ASLEEP:
710 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
711         case RADIO_STATE_CONTINUOUS_CARRIER:
712         case RADIO_STATE_MODULATED_CARRIER:
713 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
714             break;
715 
716         case RADIO_STATE_RX:
717             if (receiving_psdu_now)
718             {
719                 // Don't care about the result - if the notification cannot be performed
720                 // no impact on the device's operation is expected
721                 (void)nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_ABORTED,
722                                                        m_rx_window_id,
723                                                        true);
724             }
725 
726             break;
727 
728         case RADIO_STATE_TX_ACK:
729             mp_current_rx_buffer->free = false;
730             nrf_802154_core_hooks_tx_ack_failed(mp_ack, NRF_802154_TX_ERROR_ABORTED);
731             received_frame_notify(mp_current_rx_buffer->data);
732             break;
733 
734         case RADIO_STATE_CCA_TX:
735         case RADIO_STATE_TX:
736         {
737             nrf_802154_transmit_done_metadata_t metadata = {};
738 
739             nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props);
740             transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_ABORTED, &metadata);
741         }
742         break;
743 
744         case RADIO_STATE_RX_ACK:
745         {
746             nrf_802154_transmit_done_metadata_t metadata = {};
747 
748             nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props);
749             transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_ABORTED, &metadata);
750         }
751         break;
752 
753         case RADIO_STATE_ED:
754             nrf_802154_notify_energy_detection_failed(NRF_802154_ED_ERROR_ABORTED);
755             break;
756 
757         case RADIO_STATE_CCA:
758             nrf_802154_notify_cca_failed(NRF_802154_CCA_ERROR_ABORTED);
759             break;
760 
761         default:
762             assert(false);
763     }
764 }
765 
766 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
operation_terminated_update_total_times(trx_state_t trx_state,uint32_t timestamp)767 static void operation_terminated_update_total_times(trx_state_t trx_state, uint32_t timestamp)
768 {
769     uint32_t t;
770 
771     switch (trx_state)
772     {
773         case TRX_STATE_RXFRAME:
774         case TRX_STATE_RXACK:
775             t = timestamp - m_listening_start_hp_timestamp;
776             nrf_802154_stat_totals_increment(total_listening_time, t);
777             break;
778 
779         default:
780             break;
781     }
782 }
783 
operation_terminated_update_total_times_is_required(trx_state_t trx_state)784 static bool operation_terminated_update_total_times_is_required(trx_state_t trx_state)
785 {
786     switch (trx_state)
787     {
788         case TRX_STATE_RXFRAME:
789         case TRX_STATE_RXACK:
790             /* These cases must be in-sync with implementation of
791              * operation_terminated_update_total_times
792              */
793             return true;
794 
795         default:
796             return false;
797     }
798 }
799 
800 #endif
801 
trx_abort(void)802 static void trx_abort(void)
803 {
804 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
805     trx_state_t trx_state       = nrf_802154_trx_state_get();
806     bool        update_required = operation_terminated_update_total_times_is_required(trx_state);
807 
808 #endif
809 
810     nrf_802154_trx_abort();
811 
812 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
813     if (update_required)
814     {
815         uint32_t timestamp = nrf_802154_hp_timer_current_time_get();
816 
817         operation_terminated_update_total_times(trx_state, timestamp);
818     }
819 #endif
820 }
821 
trx_disable(void)822 static void trx_disable(void)
823 {
824 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
825     trx_state_t trx_state       = nrf_802154_trx_state_get();
826     bool        update_required = operation_terminated_update_total_times_is_required(trx_state);
827 
828 #endif
829 
830     nrf_802154_trx_disable();
831 
832 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
833     if (update_required)
834     {
835         uint32_t timestamp = nrf_802154_hp_timer_current_time_get();
836 
837         operation_terminated_update_total_times(trx_state, timestamp);
838     }
839 #endif
840 }
841 
842 /** Terminate ongoing operation.
843  *
844  * This function is called when MAC layer requests transition to another operation.
845  *
846  * After calling this function RADIO should enter DISABLED state and Radio Scheduler
847  * should be in continuous mode.
848  *
849  * @param[in]  term_lvl      Termination level of this request. Selects procedures to abort.
850  * @param[in]  req_orig      Module that originates termination request.
851  * @param[in]  notify_abort  If Termination of current operation shall be notified.
852  *
853  * @retval true   Terminated ongoing operation.
854  * @retval false  Ongoing operation was not terminated.
855  */
current_operation_terminate(nrf_802154_term_t term_lvl,req_originator_t req_orig,bool notify)856 static bool current_operation_terminate(nrf_802154_term_t term_lvl,
857                                         req_originator_t  req_orig,
858                                         bool              notify)
859 {
860     bool result = nrf_802154_core_hooks_terminate(term_lvl, req_orig);
861 
862     if (result)
863     {
864         bool receiving_psdu_now = false;
865 
866         if (m_state == RADIO_STATE_RX)
867         {
868             receiving_psdu_now = nrf_802154_trx_psdu_is_being_received();
869         }
870 
871         result = can_terminate_current_operation(m_state, term_lvl, receiving_psdu_now);
872 
873         if (result)
874         {
875             trx_abort();
876 
877             if (m_state == RADIO_STATE_RX)
878             {
879                 /* When in rx mode, nrf_802154_trx_receive_frame_prestarted handler might
880                  * have already been called. We need to stop counting timeout. */
881                 m_rx_prestarted_trig_count = 0;
882                 (void)nrf_802154_sl_timer_remove(&m_rx_prestarted_timer);
883 
884                 /* Notify antenna diversity module that RX has been aborted. */
885                 nrf_802154_sl_ant_div_rx_aborted_notify();
886 
887                 /* We might have boosted preconditions (to support coex) above level
888                  * normally requested for current state by request_preconditions_for_state(m_state).
889                  * When current operation is terminated we request preconditions back
890                  * thus ceasing to request to coex. */
891                 request_preconditions_for_state(m_state);
892             }
893 
894             if (m_state == RADIO_STATE_ED)
895             {
896                 nrf_802154_sl_ant_div_energy_detection_aborted_notify();
897             }
898 
899             if (notify)
900             {
901                 operation_terminated_notify(m_state, receiving_psdu_now);
902             }
903         }
904 
905     }
906 
907     return result;
908 }
909 
910 /** Enter Sleep state. */
sleep_init(void)911 static void sleep_init(void)
912 {
913     // This function is always executed from a critical section, so this check is safe.
914     if (timeslot_is_granted())
915     {
916         nrf_802154_timer_coord_stop();
917     }
918 }
919 
920 /** Initialize Falling Asleep operation. */
falling_asleep_init(void)921 static void falling_asleep_init(void)
922 {
923     if (nrf_802154_trx_go_idle())
924     {
925         // There will be nrf_802154_trx_in_idle call, where we will continue processing
926     }
927     else
928     {
929         sleep_init();
930         state_set(RADIO_STATE_SLEEP);
931     }
932 }
933 
934 /**@brief Makes value to be passed to @ref nrf_802154_trx_receive_frame as @c notifications_mask parameter */
make_trx_frame_receive_notification_mask(void)935 static nrf_802154_trx_receive_notifications_t make_trx_frame_receive_notification_mask(void)
936 {
937     nrf_802154_trx_receive_notifications_t result = TRX_RECEIVE_NOTIFICATION_NONE;
938 
939 #if (NRF_802154_STATS_COUNT_ENERGY_DETECTED_EVENTS)
940     result |= TRX_RECEIVE_NOTIFICATION_PRESTARTED;
941 #endif
942 #if (NRF_802154_STATS_COUNT_RECEIVED_PREAMBLES)
943     result |= TRX_RECEIVE_NOTIFICATION_STARTED;
944 #endif
945 
946     if (nrf_802154_wifi_coex_is_enabled())
947     {
948         switch (nrf_802154_pib_coex_rx_request_mode_get())
949         {
950             case NRF_802154_COEX_RX_REQUEST_MODE_DESTINED:
951                 /* Coex requesting handled through nrf_802154_trx_receive_frame_bcmatched handler.
952                  * No additional notifications required. */
953                 break;
954 
955             case NRF_802154_COEX_RX_REQUEST_MODE_ENERGY_DETECTION:
956                 result |= TRX_RECEIVE_NOTIFICATION_PRESTARTED | TRX_RECEIVE_NOTIFICATION_STARTED;
957                 // Note: TRX_RECEIVE_NOTIFICATION_STARTED is required for stopping counting timeout for
958                 // activity triggered by nrf_802154_trx_receive_frame_prestarted.
959                 break;
960 
961             case NRF_802154_COEX_RX_REQUEST_MODE_PREAMBLE:
962                 result |= TRX_RECEIVE_NOTIFICATION_STARTED;
963                 break;
964 
965             default:
966                 assert(false);
967         }
968     }
969 
970     return result;
971 }
972 
973 /**@brief Makes value to be passed to @ref nrf_802154_trx_transmit_frame as @c notifications_mask parameter
974  *
975  * @param[in] cca   Pass true, if cca operation it to be performed before transmit.
976  *                  Pass false otherwise.
977  */
make_trx_frame_transmit_notification_mask(bool cca)978 static nrf_802154_trx_transmit_notifications_t make_trx_frame_transmit_notification_mask(bool cca)
979 {
980     nrf_802154_trx_transmit_notifications_t result = TRX_TRANSMIT_NOTIFICATION_NONE;
981 
982 #if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
983     if (cca)
984     {
985         result |= TRX_TRANSMIT_NOTIFICATION_CCAIDLE;
986     }
987 #endif
988 
989     if (nrf_802154_wifi_coex_is_enabled())
990     {
991         switch (nrf_802154_pib_coex_tx_request_mode_get())
992         {
993             case NRF_802154_COEX_TX_REQUEST_MODE_FRAME_READY:
994             case NRF_802154_COEX_TX_REQUEST_MODE_CCA_START:
995             case NRF_802154_COEX_TX_REQUEST_MODE_ON_CCA_TOGGLE:
996                 /* No additional notifications required. */
997                 break;
998 
999             case NRF_802154_COEX_TX_REQUEST_MODE_CCA_DONE:
1000                 result |= TRX_TRANSMIT_NOTIFICATION_CCAIDLE;
1001                 break;
1002 
1003             default:
1004                 assert(false);
1005         }
1006     }
1007 
1008     return result;
1009 }
1010 
1011 /**
1012  * @brief Initializes RX operation
1013  *
1014  * @param[in]  ru_tr_mode            Desired trigger mode for radio ramp up.
1015  * @param[out] p_abort_shall_follow  It is set to `true` when initialization fails and the trx
1016  *                                   module needs to be reset. When obtaining `true` here, the user
1017  *                                   is then obliged to call @ref nrf_802154_trx_abort. Such a case
1018  *                                   can only happen when @p ru_tr_mode = TRX_RAMP_UP_HW_TRIGGER.
1019  *                                   In all other cases, the value is not modified at all, so it
1020  *                                   should be initialized to `false` before calling the function.
1021  *                                   Can be NULL if @p ru_tr_mode is not TRX_RAMP_UP_HW_TRIGGER.
1022  */
rx_init(nrf_802154_trx_ramp_up_trigger_mode_t ru_tr_mode,bool * p_abort_shall_follow)1023 static void rx_init(nrf_802154_trx_ramp_up_trigger_mode_t ru_tr_mode, bool * p_abort_shall_follow)
1024 {
1025     bool free_buffer;
1026 
1027     if (!timeslot_is_granted())
1028     {
1029         return;
1030     }
1031 
1032     if (!are_preconditions_met())
1033     {
1034         return;
1035     }
1036 
1037     // Clear filtering flag
1038     rx_flags_clear();
1039 
1040     // Find available RX buffer
1041     free_buffer = rx_buffer_is_available();
1042 
1043     nrf_802154_trx_receive_buffer_set(rx_buffer_get());
1044 
1045     nrf_802154_fal_tx_power_split_t split_power = {0};
1046 
1047     (void)nrf_802154_tx_power_split_pib_power_get(&split_power);
1048 
1049     nrf_802154_trx_receive_frame(BCC_INIT / 8U,
1050                                  ru_tr_mode,
1051                                  m_trx_receive_frame_notifications_mask,
1052                                  &split_power);
1053 
1054     if (ru_tr_mode == TRX_RAMP_UP_HW_TRIGGER)
1055     {
1056         uint32_t ppi_ch = nrf_802154_trx_ramp_up_ppi_channel_get();
1057 
1058         if (!nrf_802154_rsch_delayed_timeslot_ppi_update(ppi_ch))
1059         {
1060             /**
1061              * The trigger has occurred. This has happened too early so there is a high risk
1062              * that the radio will not ramp up. It is necessary to abort the operation.
1063              */
1064             assert(p_abort_shall_follow);
1065             *p_abort_shall_follow = true;
1066         }
1067     }
1068 
1069 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
1070     m_listening_start_hp_timestamp = nrf_802154_hp_timer_current_time_get();
1071     // The introduction of TRX_RAMP_UP_HW_TRIGGER broke the measurement method used here.
1072     // Obtained timestamp is no more related to the moment when listening starts.
1073     // TODO: Remove TOTAL_TIMES_MEASUREMENT feature, as it has been verified that it is
1074     // not needed.
1075 #endif
1076 
1077 #if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
1078 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
1079     // Configure the timer coordinator to get a timestamp of the END event which
1080     // fires several cycles after CRCOK or CRCERROR events.
1081     nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_end_event_handle_get());
1082 #else
1083     // Configure the timer coordinator to get a timestamp of the CRCOK event.
1084     nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_crcok_event_handle_get());
1085 #endif
1086 #endif
1087 
1088     // Find RX buffer if none available
1089     if (!free_buffer)
1090     {
1091         rx_buffer_in_use_set(nrf_802154_rx_buffer_free_find());
1092 
1093         nrf_802154_trx_receive_buffer_set(rx_buffer_get());
1094     }
1095 
1096     rx_data_clear();
1097 
1098     mp_ack = NULL;
1099 }
1100 
1101 /** Initialize TX operation. */
tx_init(const uint8_t * p_data,nrf_802154_trx_ramp_up_trigger_mode_t rampup_trigg_mode,bool cca)1102 static bool tx_init(const uint8_t                       * p_data,
1103                     nrf_802154_trx_ramp_up_trigger_mode_t rampup_trigg_mode,
1104                     bool                                  cca)
1105 {
1106     if (!timeslot_is_granted() || !nrf_802154_rsch_timeslot_request(
1107             nrf_802154_tx_duration_get(p_data[0], cca, ack_is_requested(p_data))))
1108     {
1109         return false;
1110     }
1111 
1112     if (!are_preconditions_met())
1113     {
1114         return false;
1115     }
1116 
1117 #if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
1118     if (cca)
1119     {
1120         // Configure the timer coordinator to get a time stamp of the READY event.
1121         // Note: This event triggers CCASTART, so the time stamp of READY event
1122         // is the time stamp when CCA started.
1123         nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_ready_event_handle_get());
1124     }
1125     else
1126     {
1127         // Configure the timer coordinator to get a time stamp of the PHYEND event.
1128         nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_phyend_event_handle_get());
1129     }
1130 #endif
1131 
1132     m_flags.tx_with_cca = cca;
1133     nrf_802154_trx_transmit_frame(nrf_802154_tx_work_buffer_get(p_data),
1134                                   rampup_trigg_mode,
1135                                   cca,
1136                                   &m_tx_power,
1137                                   m_trx_transmit_frame_notifications_mask);
1138 
1139     if (rampup_trigg_mode == TRX_RAMP_UP_HW_TRIGGER)
1140     {
1141         uint32_t ppi_ch = nrf_802154_trx_ramp_up_ppi_channel_get();
1142 
1143         if (!nrf_802154_rsch_delayed_timeslot_ppi_update(ppi_ch))
1144         {
1145             /**
1146              * The trigger has occurred. This has happened too early so there is a high risk
1147              * that the radio will not ramp up. It is necessary to abort the operation.
1148              */
1149             nrf_802154_trx_abort();
1150             return false;
1151         }
1152     }
1153 
1154     return true;
1155 }
1156 
1157 /** Initialize ED operation */
ed_init(void)1158 static void ed_init(void)
1159 {
1160     if (!timeslot_is_granted())
1161     {
1162         return;
1163     }
1164 
1165     if (!are_preconditions_met())
1166     {
1167         return;
1168     }
1169 
1170     uint32_t trx_ed_count = 0U;
1171 
1172     // Notify antenna diversity about energy detection request. Antenna diversity state
1173     // will be updated, and m_ed_time_left reduced accordingly.
1174     nrf_802154_sl_ant_div_energy_detection_requested_notify(&m_ed_time_left);
1175 
1176     if (!ed_iter_setup(&m_ed_time_left, &trx_ed_count))
1177     {
1178         // Just wait for next timeslot if there is not enough time in this one.
1179         return;
1180     }
1181 
1182     nrf_802154_trx_energy_detection(trx_ed_count);
1183 }
1184 
1185 /** Initialize CCA operation. */
cca_init(void)1186 static void cca_init(void)
1187 {
1188     if (!timeslot_is_granted() || !nrf_802154_rsch_timeslot_request(nrf_802154_cca_duration_get()))
1189     {
1190         return;
1191     }
1192 
1193     if (!are_preconditions_met())
1194     {
1195         return;
1196     }
1197 
1198     nrf_802154_trx_standalone_cca();
1199 }
1200 
1201 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
1202 
1203 /** Initialize Continuous Carrier operation. */
continuous_carrier_init(void)1204 static void continuous_carrier_init(void)
1205 {
1206     if (!timeslot_is_granted())
1207     {
1208         return;
1209     }
1210 
1211     if (!are_preconditions_met())
1212     {
1213         return;
1214     }
1215     nrf_802154_fal_tx_power_split_t split_power = {0};
1216 
1217     (void)nrf_802154_tx_power_split_pib_power_get(&split_power);
1218 
1219     nrf_802154_trx_continuous_carrier(&split_power);
1220 }
1221 
1222 /** Initialize Modulated Carrier operation. */
modulated_carrier_init(const uint8_t * p_data)1223 static void modulated_carrier_init(const uint8_t * p_data)
1224 {
1225     if (!timeslot_is_granted())
1226     {
1227         return;
1228     }
1229 
1230     if (!are_preconditions_met())
1231     {
1232         return;
1233     }
1234 
1235     nrf_802154_fal_tx_power_split_t split_power = {0};
1236 
1237     (void)nrf_802154_tx_power_split_pib_power_get(&split_power);
1238 
1239     nrf_802154_trx_modulated_carrier(p_data, &split_power);
1240 }
1241 
1242 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
1243 
1244 /***************************************************************************************************
1245  * @section Radio Scheduler notification handlers
1246  **************************************************************************************************/
on_timeslot_ended(void)1247 static void on_timeslot_ended(void)
1248 {
1249     bool result;
1250 
1251     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1252 
1253     if (timeslot_is_granted())
1254     {
1255         m_rsch_timeslot_is_granted = false;
1256 
1257         bool receiving_psdu_now = false;
1258 
1259         if (m_state == RADIO_STATE_RX)
1260         {
1261             receiving_psdu_now = nrf_802154_trx_psdu_is_being_received();
1262         }
1263 
1264         trx_disable();
1265 
1266         nrf_802154_timer_coord_stop();
1267 
1268         nrf_802154_rsch_continuous_ended();
1269 
1270         result = nrf_802154_core_hooks_terminate(NRF_802154_TERM_802154, REQ_ORIG_RSCH);
1271         assert(result);
1272         (void)result;
1273 
1274         switch (m_state)
1275         {
1276             case RADIO_STATE_FALLING_ASLEEP:
1277                 state_set(RADIO_STATE_SLEEP);
1278                 break;
1279 
1280             case RADIO_STATE_RX:
1281                 if (receiving_psdu_now)
1282                 {
1283                     receive_failed_notify(NRF_802154_RX_ERROR_TIMESLOT_ENDED);
1284                 }
1285 
1286                 break;
1287 
1288             case RADIO_STATE_TX_ACK:
1289                 state_set(RADIO_STATE_RX);
1290                 mp_current_rx_buffer->free = false;
1291                 nrf_802154_core_hooks_tx_ack_failed(mp_ack, NRF_802154_TX_ERROR_TIMESLOT_ENDED);
1292                 received_frame_notify_and_nesting_allow(mp_current_rx_buffer->data);
1293                 break;
1294 
1295             case RADIO_STATE_CCA_TX:
1296             case RADIO_STATE_TX:
1297             case RADIO_STATE_RX_ACK:
1298             {
1299                 state_set(RADIO_STATE_RX);
1300                 nrf_802154_transmit_done_metadata_t metadata = {};
1301 
1302                 nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props);
1303                 transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_TIMESLOT_ENDED,
1304                                                          &metadata);
1305             }
1306             break;
1307 
1308             case RADIO_STATE_ED:
1309             case RADIO_STATE_CCA:
1310 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
1311             case RADIO_STATE_CONTINUOUS_CARRIER:
1312             case RADIO_STATE_MODULATED_CARRIER:
1313 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
1314             case RADIO_STATE_SLEEP:
1315                 // Intentionally empty.
1316                 break;
1317 
1318             default:
1319                 assert(false);
1320         }
1321     }
1322 
1323     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1324 }
1325 
on_preconditions_denied(radio_state_t state)1326 static void on_preconditions_denied(radio_state_t state)
1327 {
1328     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1329 
1330     bool result;
1331 
1332     result = nrf_802154_core_hooks_terminate(NRF_802154_TERM_802154, REQ_ORIG_CORE);
1333     assert(result);
1334     (void)result;
1335 
1336     bool receiving_psdu_now = false;
1337 
1338     if (state == RADIO_STATE_RX)
1339     {
1340         receiving_psdu_now = nrf_802154_trx_psdu_is_being_received();
1341     }
1342 
1343     trx_abort();
1344 
1345     switch (state)
1346     {
1347         case RADIO_STATE_FALLING_ASLEEP:
1348             // There should be on_timeslot_ended event
1349             break;
1350 
1351         case RADIO_STATE_RX:
1352             if (receiving_psdu_now)
1353             {
1354                 receive_failed_notify(NRF_802154_RX_ERROR_ABORTED);
1355             }
1356 
1357             break;
1358 
1359         case RADIO_STATE_TX_ACK:
1360             state_set(RADIO_STATE_RX);
1361             break;
1362 
1363         case RADIO_STATE_CCA_TX:
1364             m_flags.tx_diminished_prio = false;
1365         // Fallthrough
1366 
1367         case RADIO_STATE_TX:
1368         case RADIO_STATE_RX_ACK:
1369             state_set(RADIO_STATE_RX);
1370             break;
1371 
1372         case RADIO_STATE_ED:
1373         case RADIO_STATE_CCA:
1374 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
1375         case RADIO_STATE_CONTINUOUS_CARRIER:
1376         case RADIO_STATE_MODULATED_CARRIER:
1377 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
1378         case RADIO_STATE_SLEEP:
1379             // Intentionally empty.
1380             break;
1381 
1382         default:
1383             assert(false);
1384     }
1385 
1386     operation_terminated_notify(state, receiving_psdu_now);
1387 
1388     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1389 }
1390 
on_preconditions_approved(radio_state_t state)1391 static void on_preconditions_approved(radio_state_t state)
1392 {
1393     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1394 
1395     trx_abort();
1396 
1397     switch (state)
1398     {
1399         case RADIO_STATE_SLEEP:
1400             // Intentionally empty. Appropriate action will be performed on state change.
1401             break;
1402 
1403         case RADIO_STATE_RX:
1404             rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
1405             break;
1406 
1407         case RADIO_STATE_CCA_TX:
1408             (void)tx_init(mp_tx_data, TRX_RAMP_UP_SW_TRIGGER, true);
1409             break;
1410 
1411         case RADIO_STATE_TX:
1412             (void)tx_init(mp_tx_data, TRX_RAMP_UP_SW_TRIGGER, false);
1413             break;
1414 
1415         case RADIO_STATE_ED:
1416             ed_init();
1417             break;
1418 
1419         case RADIO_STATE_CCA:
1420             cca_init();
1421             break;
1422 
1423 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
1424         case RADIO_STATE_CONTINUOUS_CARRIER:
1425             continuous_carrier_init();
1426             break;
1427 
1428         case RADIO_STATE_MODULATED_CARRIER:
1429             modulated_carrier_init(mp_tx_data);
1430             break;
1431 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
1432 
1433         default:
1434             assert(false);
1435     }
1436 
1437     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1438 }
1439 
on_timeslot_started(void)1440 static void on_timeslot_started(void)
1441 {
1442     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1443 
1444     nrf_802154_trx_enable();
1445 
1446     m_rsch_timeslot_is_granted = true;
1447 
1448     nrf_802154_timer_coord_start();
1449 
1450     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1451 }
1452 
preconditions_approved_should_be_ignored(rsch_prio_t previously_approved_prio,rsch_prio_t currently_approved_prio)1453 static bool preconditions_approved_should_be_ignored(rsch_prio_t previously_approved_prio,
1454                                                      rsch_prio_t currently_approved_prio)
1455 {
1456     // Approved preconditions should only be ignored only all the following conditions are met:
1457     // * all preconditions apart from Coex had already been approved;
1458     // * the call is a result of Coex becoming approved at the highest priority;
1459     // * currently performed operation is transmission with CCA;
1460     // * Coex for transmission is requested after CCA reports idle channel
1461     bool only_coex_was_unapproved       = (previously_approved_prio == RSCH_PRIO_RX);
1462     bool all_preconditions_are_approved = (currently_approved_prio == RSCH_PRIO_MAX);
1463     bool current_state_is_cca_tx        = (m_state == RADIO_STATE_CCA_TX);
1464     bool coex_tx_request_mode_allows    = (m_coex_tx_request_mode ==
1465                                            NRF_802154_COEX_TX_REQUEST_MODE_CCA_DONE);
1466 
1467     return (only_coex_was_unapproved &&
1468             all_preconditions_are_approved &&
1469             current_state_is_cca_tx &&
1470             coex_tx_request_mode_allows);
1471 }
1472 
nrf_802154_rsch_crit_sect_prio_changed(rsch_prio_t prio)1473 void nrf_802154_rsch_crit_sect_prio_changed(rsch_prio_t prio)
1474 {
1475     rsch_prio_t old_prio = m_rsch_priority;
1476 
1477     m_rsch_priority = prio;
1478 
1479     if ((old_prio == RSCH_PRIO_IDLE) && (prio != RSCH_PRIO_IDLE))
1480     {
1481         // We have just got a timeslot.
1482         on_timeslot_started();
1483     }
1484     else if ((old_prio != RSCH_PRIO_IDLE) && (prio == RSCH_PRIO_IDLE))
1485     {
1486         // We are giving back timeslot.
1487         on_timeslot_ended();
1488         return;
1489     }
1490     else if (prio == RSCH_PRIO_IDLE)
1491     {
1492         // It might happen that even though IDLE has already been notified, this function is called
1493         // again as a result of preemptions caused by unexpected timeslot change (e.g. the application
1494         // requested transition to sleep while out of timeslot and RAAL notified timeslot start
1495         // in the middle of that sleep request). The following block makes RAAL finish its processing.
1496         nrf_802154_rsch_continuous_ended();
1497     }
1498     else
1499     {
1500         // Intentionally empty
1501     }
1502 
1503     int_fast8_t transition = action_needed(old_prio, prio, m_state);
1504 
1505     if (transition == 0)
1506     {
1507         return;
1508     }
1509     else if (transition < 0)
1510     {
1511         on_preconditions_denied(m_state);
1512 
1513         // After denying preconditions, TRX is disabled. However, it is possible that the existing
1514         // preconditions are enough for the new state (entered due to denied preconditions) and TRX
1515         // could be enabled for the new state. If this is the case, on_preconditions_approved() is
1516         // called to fully switch to the new state.
1517         radio_state_t new_state = m_state;
1518 
1519         if (is_state_allowed_for_prio(prio, new_state))
1520         {
1521             on_preconditions_approved(new_state);
1522         }
1523     }
1524     else
1525     {
1526         if (!preconditions_approved_should_be_ignored(old_prio, prio))
1527         {
1528             on_preconditions_approved(m_state);
1529         }
1530     }
1531 }
1532 
1533 /***************************************************************************************************
1534  * @section RADIO interrupt handler
1535  **************************************************************************************************/
1536 
nrf_802154_trx_receive_ack_started(void)1537 void nrf_802154_trx_receive_ack_started(void)
1538 {
1539     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1540 
1541     assert(m_state == RADIO_STATE_RX_ACK);
1542     nrf_802154_core_hooks_rx_ack_started();
1543 
1544     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1545 }
1546 
on_rx_prestarted_timeout(nrf_802154_sl_timer_t * p_timer)1547 static void on_rx_prestarted_timeout(nrf_802154_sl_timer_t * p_timer)
1548 {
1549     (void)p_timer;
1550 
1551     /* If we were in critical section this handler would not be called.
1552      * If we were outside of critical section this handler could be called,
1553      * and nrf_802154_critical_section_enter must succeed.
1554      * Justification:
1555      * - If higher priority interrupt preempts this handler before it takes critical section, that
1556      * interrupt may enter/exit critical section, but when it returns to this handler
1557      * entering critical section will succeed.
1558      * - If we entered critical section here the higher priority interrupt from radio
1559      * will not occur.
1560      * - The only related interrupt that can preempt this handler while it owns critical section
1561      * is from raal timeslot margin, which will fail to enter critical section and schedule
1562      * priority change to be called by nrf_802154_critical_section_exit.
1563      *
1564      * Critical section is entered forcefully here nonetheless, due to a rare issue with
1565      * nrf_802154_critical_section_exit being preempted before the nested critical section counter
1566      * could be decremented. Allowing for critical section nesting here resolves the problem.
1567      * TODO: After the bug is fixed, change to nrf_802154_critical_section_enter and check if
1568      * critical section was successfully entered.
1569      */
1570 
1571     nrf_802154_critical_section_forcefully_enter();
1572 
1573     nrf_802154_sl_ant_div_rx_preamble_timeout_notify();
1574 
1575     do
1576     {
1577         /**
1578          * Multiple, rapidly consecutive reception start events without later moving to the next
1579          * step are possible. There is a special handling for this case here.
1580          */
1581         if (m_rx_prestarted_trig_count > 1)
1582         {
1583             uint64_t now = nrf_802154_sl_timer_current_time_get();
1584 
1585             /**
1586              * If the value of trigger_time field is a moment in the future, it means that timer
1587              * handling has been preempted by HELPER1 radio event after removing the timer from
1588              * scheduler, but before handling this callback. In that case, process the timeout
1589              * as usual, but notify  antenna diversity module that another preamble was detected
1590              * in order to repeat RSSI measurements.
1591              */
1592             if (nrf_802154_sl_time64_is_in_future(now, m_rx_prestarted_timer.trigger_time))
1593             {
1594                 m_rx_prestarted_trig_count = 1;
1595                 nrf_802154_sl_ant_div_rx_preamble_detected_notify();
1596                 break;
1597             }
1598         }
1599 
1600         m_rx_prestarted_trig_count = 0;
1601     }
1602     while (0);
1603 
1604     /* If nrf_802154_trx_receive_frame_prestarted boosted preconditions beyond those normally
1605      * required by current state, they need to be restored now.
1606      */
1607     if (nrf_802154_pib_coex_rx_request_mode_get() ==
1608         NRF_802154_COEX_RX_REQUEST_MODE_ENERGY_DETECTION)
1609     {
1610         request_preconditions_for_state(m_state);
1611     }
1612     nrf_802154_critical_section_exit();
1613 }
1614 
nrf_802154_trx_receive_frame_prestarted(void)1615 void nrf_802154_trx_receive_frame_prestarted(void)
1616 {
1617     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1618 
1619     if (!antenna_diversity_is_enabled())
1620     {
1621         // Only assert if notifications mask would not allow for calling this function.
1622         assert((m_trx_receive_frame_notifications_mask & TRX_RECEIVE_NOTIFICATION_PRESTARTED) !=
1623                0U);
1624     }
1625     else
1626     {
1627         // Antenna diversity uses this function for detecting possible preamble on air.
1628     }
1629 
1630     assert(m_state == RADIO_STATE_RX);
1631 
1632 #if (NRF_802154_STATS_COUNT_ENERGY_DETECTED_EVENTS)
1633     nrf_802154_stat_counter_increment(received_energy_events);
1634 #endif
1635 
1636     nrf_802154_sl_ant_div_rx_preamble_detected_notify();
1637 
1638     // Antenna diversity module should be notified if framestart doesn't come.
1639     bool rx_timeout_should_be_started = antenna_diversity_is_enabled();
1640 
1641     if (nrf_802154_pib_coex_rx_request_mode_get() ==
1642         NRF_802154_COEX_RX_REQUEST_MODE_ENERGY_DETECTION)
1643     {
1644         // Request boosted preconditions for receive
1645         nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_RX);
1646         // Boosted preconditions should be reverted if the framestart doesn't come.
1647         rx_timeout_should_be_started = true;
1648     }
1649 
1650     /*
1651      * This handler might not be followed by nrf_802154_trx_receive_frame_started. The timer
1652      * below is used for timing out if the framestart doesn't come.
1653      * There are two reasons for that: reverting boosted preconditions and notifying antenna diversity
1654      * module.
1655      */
1656     if (rx_timeout_should_be_started)
1657     {
1658 
1659         uint64_t now = nrf_802154_sl_timer_current_time_get();
1660 
1661         (void)nrf_802154_sl_timer_remove(&m_rx_prestarted_timer);
1662 
1663         m_rx_prestarted_timer.trigger_time             = now + PRESTARTED_TIMER_TIMEOUT_US;
1664         m_rx_prestarted_timer.action_type              = NRF_802154_SL_TIMER_ACTION_TYPE_CALLBACK;
1665         m_rx_prestarted_timer.action.callback.callback = on_rx_prestarted_timeout;
1666 
1667         nrf_802154_sl_timer_ret_t ret;
1668 
1669         ret = nrf_802154_sl_timer_add(&m_rx_prestarted_timer);
1670         assert(ret == NRF_802154_SL_TIMER_RET_SUCCESS);
1671         (void)ret;
1672 
1673         m_rx_prestarted_trig_count += 1;
1674     }
1675 
1676     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1677 }
1678 
nrf_802154_trx_receive_frame_started(void)1679 void nrf_802154_trx_receive_frame_started(void)
1680 {
1681     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1682 
1683     assert(m_state == RADIO_STATE_RX);
1684     assert((m_trx_receive_frame_notifications_mask & TRX_RECEIVE_NOTIFICATION_STARTED) != 0U);
1685 
1686 #if (NRF_802154_STATS_COUNT_RECEIVED_PREAMBLES)
1687     nrf_802154_stat_counter_increment(received_preambles);
1688 #endif
1689 
1690     switch (nrf_802154_pib_coex_rx_request_mode_get())
1691     {
1692         case NRF_802154_COEX_RX_REQUEST_MODE_ENERGY_DETECTION:
1693             m_rx_prestarted_trig_count = 0;
1694             (void)nrf_802154_sl_timer_remove(&m_rx_prestarted_timer);
1695         /* Fallthrough */
1696 
1697         case NRF_802154_COEX_RX_REQUEST_MODE_PREAMBLE:
1698             /* Request boosted preconditions */
1699             nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_RX);
1700             break;
1701 
1702         default:
1703             break;
1704     }
1705 
1706     if (antenna_diversity_is_enabled())
1707     {
1708         // If antenna diversity is enabled, rx_prestarted_timer would be started even
1709         // in different coex rx request modes than NRF_802154_COEX_RX_REQUEST_MODE_ENERGY_DETECTION
1710         m_rx_prestarted_trig_count = 0;
1711         (void)nrf_802154_sl_timer_remove(&m_rx_prestarted_timer);
1712         nrf_802154_sl_ant_div_rx_frame_started_notify();
1713     }
1714 
1715     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1716 }
1717 
nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)1718 uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc)
1719 {
1720     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1721 
1722     uint8_t                         next_bcc;
1723     nrf_802154_filter_mode_t        filter_mode;
1724     bool                            parse_result;
1725     bool                            should_filter = false;
1726     nrf_802154_rx_error_t           filter_result = NRF_802154_RX_ERROR_NONE;
1727     nrf_802154_frame_parser_level_t parse_level   = PARSE_LEVEL_NONE;
1728     nrf_802154_frame_parser_level_t prev_level    =
1729         nrf_802154_frame_parser_parse_level_get(&m_current_rx_frame_data);
1730 
1731     assert(m_state == RADIO_STATE_RX);
1732 
1733     switch (prev_level)
1734     {
1735         case PARSE_LEVEL_NONE:
1736             parse_level   = PARSE_LEVEL_FCF_OFFSETS;
1737             filter_mode   = NRF_802154_FILTER_MODE_FCF;
1738             should_filter = true;
1739             break;
1740 
1741         case PARSE_LEVEL_FCF_OFFSETS:
1742             parse_level   = PARSE_LEVEL_DST_ADDRESSING_END;
1743             filter_mode   = NRF_802154_FILTER_MODE_DST_ADDR;
1744             should_filter = true;
1745             break;
1746 
1747         case PARSE_LEVEL_DST_ADDRESSING_END:
1748             parse_level = PARSE_LEVEL_SEC_CTRL_OFFSETS;
1749             break;
1750 
1751         case PARSE_LEVEL_SEC_CTRL_OFFSETS:
1752             parse_level = PARSE_LEVEL_AUX_SEC_HDR_END;
1753             break;
1754 
1755         default:
1756             /* Parsing completed. Nothing more to be done. */
1757             nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1758             return 0;
1759     }
1760 
1761     parse_result = nrf_802154_frame_parser_valid_data_extend(&m_current_rx_frame_data,
1762                                                              bcc,
1763                                                              parse_level);
1764 
1765     if (!parse_result)
1766     {
1767         should_filter = false;
1768         filter_result = NRF_802154_RX_ERROR_INVALID_FRAME;
1769     }
1770 
1771     if (should_filter)
1772     {
1773         filter_result = nrf_802154_filter_frame_part(&m_current_rx_frame_data, filter_mode);
1774 
1775         if ((filter_result == NRF_802154_RX_ERROR_NONE) &&
1776             (filter_mode == NRF_802154_FILTER_MODE_DST_ADDR))
1777         {
1778             m_flags.frame_filtered = true;
1779 
1780             nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_RX);
1781             nrf_802154_ack_generator_reset();
1782         }
1783 
1784         if (nrf_802154_pib_promiscuous_get())
1785         {
1786             /*
1787              * In promiscuous mode all filtering should be ignored unless the frame has
1788              * invalid length.
1789              */
1790             filter_result = filter_result == NRF_802154_RX_ERROR_INVALID_LENGTH ?
1791                             filter_result : NRF_802154_RX_ERROR_NONE;
1792         }
1793     }
1794 
1795     if (filter_result != NRF_802154_RX_ERROR_NONE)
1796     {
1797         trx_abort();
1798         rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
1799 
1800         /* Release boosted preconditions */
1801         request_preconditions_for_state(m_state);
1802 
1803         if (nrf_802154_frame_parser_frame_type_get(&m_current_rx_frame_data) != FRAME_TYPE_ACK)
1804         {
1805             receive_failed_notify(filter_result);
1806         }
1807 
1808         nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1809         return 0;
1810     }
1811 
1812     switch (parse_level)
1813     {
1814         case PARSE_LEVEL_FCF_OFFSETS:
1815             next_bcc = PHR_SIZE + nrf_802154_frame_parser_dst_addressing_end_offset_get(
1816                 &m_current_rx_frame_data);
1817             break;
1818 
1819         case PARSE_LEVEL_DST_ADDRESSING_END:
1820             next_bcc = PHR_SIZE + nrf_802154_frame_parser_addressing_end_offset_get(
1821                 &m_current_rx_frame_data) + SECURITY_CONTROL_SIZE;
1822             break;
1823 
1824         case PARSE_LEVEL_SEC_CTRL_OFFSETS:
1825             next_bcc = PHR_SIZE + nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(
1826                 &m_current_rx_frame_data);
1827             break;
1828 
1829         default:
1830             next_bcc = 0;
1831             break;
1832     }
1833 
1834     if (!m_flags.rx_timeslot_requested)
1835     {
1836         uint16_t duration = nrf_802154_rx_duration_get(
1837             mp_current_rx_buffer->data[0],
1838             nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data));
1839 
1840         if (nrf_802154_rsch_timeslot_request(duration))
1841         {
1842             m_flags.rx_timeslot_requested = true;
1843 
1844             receive_started_notify();
1845         }
1846         else
1847         {
1848             // Disable receiver and wait for a new timeslot.
1849             trx_abort();
1850 
1851             // We should not leave trx in temporary state, let's receive then.
1852             // We avoid hard reset of radio during TX ACK phase due to timeslot end,
1853             // which could result in spurious RF emission.
1854             rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
1855 
1856             // Don't care about the result - if the notification cannot be performed
1857             // no impact on the device's operation is expected
1858             (void)nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_TIMESLOT_ENDED,
1859                                                    m_rx_window_id,
1860                                                    true);
1861         }
1862     }
1863 
1864     if (m_flags.frame_filtered &&
1865         nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) &&
1866         nrf_802154_pib_auto_ack_get())
1867     {
1868         mp_ack = nrf_802154_ack_generator_create(&m_current_rx_frame_data);
1869     }
1870 
1871     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1872 
1873     return next_bcc;
1874 }
1875 
nrf_802154_trx_go_idle_finished(void)1876 void nrf_802154_trx_go_idle_finished(void)
1877 {
1878     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1879 
1880     sleep_init();
1881     state_set(RADIO_STATE_SLEEP);
1882 
1883     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1884 }
1885 
1886 static void on_bad_ack(void);
1887 
1888 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
update_total_times_on_receive_end(uint32_t listening_start_hp_timestamp,uint32_t receive_end_hp_timestamp,uint8_t phr)1889 static void update_total_times_on_receive_end(uint32_t listening_start_hp_timestamp,
1890                                               uint32_t receive_end_hp_timestamp, uint8_t phr)
1891 {
1892     uint32_t t_listening;
1893     uint32_t t_frame;
1894 
1895     t_frame     = nrf_802154_frame_duration_get(phr, true, true);
1896     t_listening = receive_end_hp_timestamp - listening_start_hp_timestamp;
1897 
1898     if (t_frame > t_listening)
1899     {
1900         t_frame = t_listening;
1901     }
1902 
1903     t_listening -= t_frame;
1904 
1905     nrf_802154_stat_totals_increment(total_listening_time, t_listening);
1906     nrf_802154_stat_totals_increment(total_receive_time, t_frame);
1907 }
1908 
1909 #endif
1910 
1911 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
nrf_802154_stat_totals_get_notify(void)1912 void nrf_802154_stat_totals_get_notify(void)
1913 {
1914     // Total times are going to be read, update stat_totals to hold
1915     // correct times until now.
1916 
1917     nrf_802154_mcu_critical_state_t mcu_cs;
1918 
1919     nrf_802154_mcu_critical_enter(mcu_cs);
1920 
1921     trx_state_t trx_state = nrf_802154_trx_state_get();
1922 
1923     if ((trx_state == TRX_STATE_RXFRAME) || (trx_state == TRX_STATE_RXACK))
1924     {
1925         uint32_t listening_end_timestamp = nrf_802154_hp_timer_current_time_get();
1926 
1927         if (listening_end_timestamp - m_listening_start_hp_timestamp >= MAX_PHY_FRAME_TIME_US)
1928         {
1929             /* m_listening_start_hp_timestamp ... now - MAX_PHY_FRAME_TIME_US must be listening.
1930              * Last MAX_PHY_FRAME_TIME_US is considered uncertain.
1931              */
1932             listening_end_timestamp -= MAX_PHY_FRAME_TIME_US;
1933 
1934             uint32_t t_listening = listening_end_timestamp - m_listening_start_hp_timestamp;
1935 
1936             m_listening_start_hp_timestamp = listening_end_timestamp;
1937 
1938             nrf_802154_stat_totals_increment(total_listening_time, t_listening);
1939         }
1940         else
1941         {
1942             /* Too little time passed since m_listening_start_hp_timestamp, we don't know
1943              * if frame is being received now until it is received. */
1944         }
1945     }
1946 
1947     nrf_802154_mcu_critical_exit(mcu_cs);
1948 
1949 }
1950 
1951 #endif
1952 
nrf_802154_trx_receive_frame_crcerror(void)1953 void nrf_802154_trx_receive_frame_crcerror(void)
1954 {
1955     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
1956 
1957 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
1958     uint32_t receive_end_hp_timestamp     = nrf_802154_hp_timer_timestamp_get();
1959     uint32_t listening_start_hp_timestamp = m_listening_start_hp_timestamp;
1960 
1961 #endif
1962 
1963     assert(m_state == RADIO_STATE_RX);
1964     rx_flags_clear();
1965     rx_data_clear();
1966 
1967     // We don't change receive buffer, receive will go to the same that was already used
1968     request_preconditions_for_state(m_state);
1969 
1970     nrf_802154_fal_tx_power_split_t split_power = {0};
1971 
1972     (void)nrf_802154_tx_power_split_pib_power_get(&split_power);
1973 
1974     nrf_802154_trx_receive_frame(BCC_INIT / 8U,
1975                                  TRX_RAMP_UP_SW_TRIGGER,
1976                                  m_trx_receive_frame_notifications_mask,
1977                                  &split_power);
1978 
1979 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
1980     m_listening_start_hp_timestamp = nrf_802154_hp_timer_current_time_get();
1981 
1982     // Configure the timer coordinator to get a timestamp of the END event which
1983     // fires several cycles after CRCOK or CRCERROR events.
1984     nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_end_event_handle_get());
1985 #endif
1986 
1987 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
1988     update_total_times_on_receive_end(listening_start_hp_timestamp,
1989                                       receive_end_hp_timestamp,
1990                                       mp_current_rx_buffer->data[PHR_OFFSET]);
1991 #endif
1992 
1993 #if NRF_802154_NOTIFY_CRCERROR
1994     receive_failed_notify(NRF_802154_RX_ERROR_INVALID_FCS);
1995 #endif // NRF_802154_NOTIFY_CRCERROR
1996 
1997     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
1998 }
1999 
nrf_802154_trx_receive_ack_crcerror(void)2000 void nrf_802154_trx_receive_ack_crcerror(void)
2001 {
2002     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2003 
2004     assert(m_state == RADIO_STATE_RX_ACK);
2005 
2006 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
2007     uint32_t receive_end_hp_timestamp     = nrf_802154_hp_timer_timestamp_get();
2008     uint32_t listening_start_hp_timestamp = m_listening_start_hp_timestamp;
2009 
2010     update_total_times_on_receive_end(listening_start_hp_timestamp,
2011                                       receive_end_hp_timestamp,
2012                                       mp_current_rx_buffer->data[PHR_OFFSET]);
2013 #endif
2014 
2015     on_bad_ack();
2016 
2017     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2018 }
2019 
nrf_802154_trx_receive_frame_received(void)2020 void nrf_802154_trx_receive_frame_received(void)
2021 {
2022     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2023 
2024     uint8_t             * p_received_data = mp_current_rx_buffer->data;
2025     nrf_802154_rx_error_t filter_result   = NRF_802154_RX_ERROR_RUNTIME;
2026 
2027     // Latch RSSI and LQI values before sending ACK
2028     m_last_rssi = rssi_last_measurement_get();
2029     m_last_lqi  = lqi_get(p_received_data);
2030 
2031 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
2032     uint32_t receive_end_hp_timestamp     = nrf_802154_hp_timer_timestamp_get();
2033     uint32_t listening_start_hp_timestamp = m_listening_start_hp_timestamp;
2034 
2035     update_total_times_on_receive_end(listening_start_hp_timestamp,
2036                                       receive_end_hp_timestamp,
2037                                       mp_current_rx_buffer->data[PHR_OFFSET]);
2038 #endif
2039 
2040     bool parse_result = nrf_802154_frame_parser_valid_data_extend(
2041         &m_current_rx_frame_data,
2042         PHR_SIZE + nrf_802154_frame_parser_frame_length_get(&m_current_rx_frame_data),
2043         PARSE_LEVEL_FULL);
2044 
2045     if (parse_result && !m_flags.frame_filtered)
2046     {
2047         filter_result = nrf_802154_filter_frame_part(&m_current_rx_frame_data,
2048                                                      NRF_802154_FILTER_MODE_ALL);
2049 
2050         if (filter_result == NRF_802154_RX_ERROR_NONE)
2051         {
2052             uint16_t duration = nrf_802154_ack_duration_with_turnaround_get();
2053 
2054             if (nrf_802154_rsch_timeslot_request(duration))
2055             {
2056                 m_flags.frame_filtered        = true;
2057                 m_flags.rx_timeslot_requested = true;
2058 
2059                 nrf_802154_ack_generator_reset();
2060                 receive_started_notify();
2061             }
2062             else
2063             {
2064                 filter_result = NRF_802154_RX_ERROR_TIMESLOT_ENDED;
2065             }
2066         }
2067     }
2068 
2069     if (m_flags.frame_filtered || nrf_802154_pib_promiscuous_get())
2070     {
2071         nrf_802154_stat_counter_increment(received_frames);
2072 
2073 #if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
2074         uint64_t ts = timer_coord_timestamp_get();
2075 
2076         nrf_802154_stat_timestamp_write(last_rx_end_timestamp, ts);
2077 #endif
2078 
2079         nrf_802154_sl_ant_div_rx_frame_received_notify();
2080 
2081         bool send_ack = false;
2082 
2083         if (m_flags.frame_filtered &&
2084             parse_result &&
2085             nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) &&
2086             nrf_802154_pib_auto_ack_get())
2087         {
2088             nrf_802154_tx_work_buffer_reset(&m_default_frame_props);
2089             mp_ack   = nrf_802154_ack_generator_create(&m_current_rx_frame_data);
2090             send_ack = (mp_ack != NULL);
2091         }
2092 
2093         if (send_ack)
2094         {
2095             state_set(RADIO_STATE_TX_ACK);
2096 
2097             if (is_state_allowed_for_prio(m_rsch_priority, RADIO_STATE_TX_ACK))
2098             {
2099                 if (nrf_802154_trx_transmit_ack(nrf_802154_tx_work_buffer_get(mp_ack), ACK_IFS))
2100                 {
2101                     // Intentionally empty: transmitting ack, because we can
2102                 }
2103                 else
2104                 {
2105                     mp_current_rx_buffer->free = false;
2106 
2107                     state_set(RADIO_STATE_RX);
2108                     rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2109 
2110                     received_frame_notify_and_nesting_allow(p_received_data);
2111                 }
2112             }
2113             else
2114             {
2115                 if (!nrf_802154_rsch_prec_is_approved(RSCH_PREC_COEX,
2116                                                       min_required_rsch_prio(RADIO_STATE_TX_ACK)))
2117                 {
2118                     nrf_802154_stat_counter_increment(coex_denied_requests);
2119                 }
2120 
2121                 mp_current_rx_buffer->free = false;
2122 
2123                 state_set(RADIO_STATE_RX);
2124                 rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2125 
2126                 received_frame_notify_and_nesting_allow(p_received_data);
2127             }
2128         }
2129         else
2130         {
2131             request_preconditions_for_state(m_state);
2132             // Filter out received ACK frame if promiscuous mode is disabled.
2133             if (((p_received_data[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != FRAME_TYPE_ACK) ||
2134                 nrf_802154_pib_promiscuous_get())
2135             {
2136                 // Current buffer will be passed to the application
2137                 mp_current_rx_buffer->free = false;
2138 
2139                 // Find new buffer
2140                 rx_buffer_in_use_set(nrf_802154_rx_buffer_free_find());
2141 
2142                 rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2143 
2144                 received_frame_notify_and_nesting_allow(p_received_data);
2145             }
2146             else
2147             {
2148                 // Receive to the same buffer
2149                 rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2150             }
2151         }
2152     }
2153     else
2154     {
2155         // CRC is OK, but filtering operation did not end - it is invalid frame with valid CRC
2156         // or problem due to software latency (i.e. handled BCMATCH, CRCERROR, CRCOK from two
2157         // consecutively received frames).
2158         request_preconditions_for_state(m_state);
2159         rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2160 
2161         receive_failed_notify(filter_result);
2162     }
2163 
2164     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2165 }
2166 
nrf_802154_trx_transmit_frame_started(void)2167 void nrf_802154_trx_transmit_frame_started(void)
2168 {
2169     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2170 
2171     assert((m_state == RADIO_STATE_TX) || (m_state == RADIO_STATE_CCA_TX));
2172     transmit_started_notify();
2173 
2174     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2175 }
2176 
nrf_802154_trx_transmit_ack_started(void)2177 void nrf_802154_trx_transmit_ack_started(void)
2178 {
2179     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2180 
2181     assert(m_state == RADIO_STATE_TX_ACK);
2182     transmit_ack_started_notify();
2183 
2184     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2185 }
2186 
nrf_802154_trx_transmit_ack_transmitted(void)2187 void nrf_802154_trx_transmit_ack_transmitted(void)
2188 {
2189     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2190 
2191     assert(m_state == RADIO_STATE_TX_ACK);
2192 
2193 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
2194     uint32_t t_transmit = TX_RAMP_UP_TIME + nrf_802154_frame_duration_get(mp_ack[PHR_OFFSET],
2195                                                                           true,
2196                                                                           true);
2197 
2198     nrf_802154_stat_totals_increment(total_transmit_time, t_transmit);
2199 #endif
2200 
2201     uint8_t * p_received_data = mp_current_rx_buffer->data;
2202 
2203     // Current buffer used for receive operation will be passed to the application
2204     mp_current_rx_buffer->free = false;
2205 
2206     state_set(RADIO_STATE_RX);
2207 
2208     rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2209 
2210     received_frame_notify_and_nesting_allow(p_received_data);
2211 
2212     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2213 }
2214 
nrf_802154_trx_transmit_frame_transmitted(void)2215 void nrf_802154_trx_transmit_frame_transmitted(void)
2216 {
2217     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2218 
2219 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
2220     uint32_t t_listening = 0U;
2221     uint32_t t_transmit  = 0U;
2222 
2223 #endif
2224 
2225 #if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
2226     uint64_t ts = timer_coord_timestamp_get();
2227 
2228     // ts holds now timestamp of the PHYEND event
2229     nrf_802154_stat_timestamp_write(last_tx_end_timestamp, ts);
2230 
2231     if (m_flags.tx_with_cca)
2232     {
2233         m_flags.tx_diminished_prio = false;
2234 
2235         // We calculate the timestamp when ccaidle must happened.
2236         ts -= nrf_802154_frame_duration_get(mp_tx_data[0], true, true) + RX_TX_TURNAROUND_TIME;
2237 
2238         nrf_802154_stat_timestamp_write(last_cca_idle_timestamp, ts);
2239 
2240 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
2241         uint64_t cca_start_ts;
2242 
2243         nrf_802154_stat_timestamp_read(&cca_start_ts, last_cca_start_timestamp);
2244 
2245         t_listening += RX_RAMP_UP_TIME + (uint32_t)(ts - cca_start_ts);
2246         t_transmit  += RX_TX_TURNAROUND_TIME;
2247 #endif
2248     }
2249     else
2250     {
2251 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
2252         t_transmit += TX_RAMP_UP_TIME;
2253 #endif
2254     }
2255 
2256 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
2257     t_transmit += nrf_802154_frame_duration_get(mp_tx_data[PHR_OFFSET], true, true);
2258 
2259     nrf_802154_stat_totals_increment(total_listening_time, t_listening);
2260     nrf_802154_stat_totals_increment(total_transmit_time, t_transmit);
2261 #endif
2262 #endif
2263 
2264     if (ack_is_requested(mp_tx_data))
2265     {
2266         state_set(RADIO_STATE_RX_ACK);
2267 
2268         bool rx_buffer_free = rx_buffer_is_available();
2269 
2270         nrf_802154_trx_receive_buffer_set(rx_buffer_get());
2271 
2272 #if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
2273 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
2274         // Configure the timer coordinator to get a timestamp of the END event which
2275         // fires several cycles after CRCOK or CRCERROR events.
2276         nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_end_event_handle_get());
2277 #else
2278         // Configure the timer coordinator to get a timestamp of the CRCOK event.
2279         nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_crcok_event_handle_get());
2280 #endif
2281 #endif
2282 
2283         nrf_802154_trx_receive_ack();
2284 
2285 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
2286         m_listening_start_hp_timestamp = nrf_802154_hp_timer_current_time_get();
2287 #endif
2288 
2289         if (!rx_buffer_free)
2290         {
2291             rx_buffer_in_use_set(nrf_802154_rx_buffer_free_find());
2292 
2293             nrf_802154_trx_receive_buffer_set(rx_buffer_get());
2294         }
2295     }
2296     else
2297     {
2298         state_set(RADIO_STATE_RX);
2299 
2300         rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2301 
2302         transmitted_frame_notify(NULL, 0, 0);
2303     }
2304 
2305     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2306 }
2307 
ack_match_check_version_not_2(const uint8_t * p_tx_data,const uint8_t * p_ack_data)2308 static bool ack_match_check_version_not_2(const uint8_t * p_tx_data, const uint8_t * p_ack_data)
2309 {
2310     // Frame Version != 2
2311 
2312     // Check: Phy length
2313     if (p_ack_data[PHR_OFFSET] != IMM_ACK_LENGTH)
2314     {
2315         return false;
2316     }
2317 
2318     // Check if Frame version is 0 or 1.
2319     switch (p_ack_data[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK)
2320     {
2321         case FRAME_VERSION_0:
2322         case FRAME_VERSION_1:
2323             break;
2324 
2325         default:
2326             return false;
2327     }
2328 
2329     // Check: Sequence number match
2330     if (p_ack_data[DSN_OFFSET] != p_tx_data[DSN_OFFSET])
2331     {
2332         return false;
2333     }
2334 
2335     return true;
2336 }
2337 
ack_match_check_version_2(const uint8_t * p_tx_frame,const uint8_t * p_ack_frame)2338 static bool ack_match_check_version_2(const uint8_t * p_tx_frame, const uint8_t * p_ack_frame)
2339 {
2340     nrf_802154_frame_parser_data_t tx_data;
2341     nrf_802154_frame_parser_data_t ack_data;
2342     bool                           parse_result;
2343 
2344     parse_result = nrf_802154_frame_parser_data_init(p_tx_frame,
2345                                                      p_tx_frame[PHR_OFFSET] + PHR_SIZE,
2346                                                      PARSE_LEVEL_ADDRESSING_END,
2347                                                      &tx_data);
2348     if (!parse_result)
2349     {
2350         return false;
2351     }
2352 
2353     parse_result = nrf_802154_frame_parser_data_init(p_ack_frame,
2354                                                      p_ack_frame[PHR_OFFSET] + PHR_SIZE,
2355                                                      PARSE_LEVEL_ADDRESSING_END,
2356                                                      &ack_data);
2357 
2358     if (nrf_802154_frame_parser_frame_version_get(&ack_data) != FRAME_VERSION_2)
2359     {
2360         return false;
2361     }
2362 
2363     // Transmitted frame was Version 2
2364     // For frame version 2 sequence number bit may be suppressed and its check fails.
2365     // Verify ACK frame using its destination address.
2366 
2367     const uint8_t * p_tx_src_addr     = nrf_802154_frame_parser_src_addr_get(&tx_data);
2368     const uint8_t * p_ack_dst_addr    = nrf_802154_frame_parser_dst_addr_get(&ack_data);
2369     uint8_t         tx_src_addr_size  = nrf_802154_frame_parser_src_addr_size_get(&tx_data);
2370     uint8_t         ack_dst_addr_size = nrf_802154_frame_parser_dst_addr_size_get(&ack_data);
2371 
2372     if (!parse_result ||
2373         (p_tx_src_addr == NULL) ||
2374         (p_ack_dst_addr == NULL) ||
2375         (tx_src_addr_size != ack_dst_addr_size) ||
2376         (0 != memcmp(p_tx_src_addr,
2377                      p_ack_dst_addr,
2378                      tx_src_addr_size)))
2379     {
2380         // Mismatch
2381         return false;
2382     }
2383 
2384     return true;
2385 }
2386 
ack_match_check(const uint8_t * p_tx_data,const uint8_t * p_ack_data)2387 static bool ack_match_check(const uint8_t * p_tx_data, const uint8_t * p_ack_data)
2388 {
2389     if ((p_tx_data == NULL) || (p_ack_data == NULL))
2390     {
2391         return false;
2392     }
2393 
2394     // Check: Frame Control Field -> Frame type
2395     if ((p_ack_data[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) != FRAME_TYPE_ACK)
2396     {
2397         return false; // This is not an ACK frame
2398     }
2399 
2400     // Check: Frame Control Field -> Frame version
2401     if ((p_tx_data[FRAME_VERSION_OFFSET] & FRAME_VERSION_MASK) == FRAME_VERSION_2)
2402     {
2403         return ack_match_check_version_2(p_tx_data, p_ack_data);
2404     }
2405 
2406     return ack_match_check_version_not_2(p_tx_data, p_ack_data);
2407 }
2408 
on_bad_ack(void)2409 static void on_bad_ack(void)
2410 {
2411     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2412 
2413     // We received either a frame with incorrect CRC or not an ACK frame or not matching ACK
2414     state_set(RADIO_STATE_RX);
2415 
2416     rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2417 
2418     nrf_802154_transmit_done_metadata_t metadata = {};
2419 
2420     nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props);
2421     transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_INVALID_ACK, &metadata);
2422 
2423     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2424 }
2425 
nrf_802154_trx_receive_ack_received(void)2426 void nrf_802154_trx_receive_ack_received(void)
2427 {
2428     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2429 
2430     // CRC of received frame is correct
2431     uint8_t * p_ack_data = mp_current_rx_buffer->data;
2432 
2433 #if NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED
2434     uint32_t receive_end_hp_timestamp     = nrf_802154_hp_timer_timestamp_get();
2435     uint32_t listening_start_hp_timestamp = m_listening_start_hp_timestamp;
2436 
2437     update_total_times_on_receive_end(listening_start_hp_timestamp,
2438                                       receive_end_hp_timestamp,
2439                                       mp_current_rx_buffer->data[PHR_OFFSET]);
2440 #endif
2441 
2442     if (ack_match_check(mp_tx_data, p_ack_data))
2443     {
2444 #if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
2445         uint64_t ts = timer_coord_timestamp_get();
2446 
2447         nrf_802154_stat_timestamp_write(last_ack_end_timestamp, ts);
2448 #endif
2449 
2450         rx_buffer_t * p_ack_buffer = mp_current_rx_buffer;
2451 
2452         mp_current_rx_buffer->free = false;
2453 
2454         state_set(RADIO_STATE_RX);
2455         rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2456 
2457         transmitted_frame_notify(p_ack_buffer->data,           // phr + psdu
2458                                  rssi_last_measurement_get(),  // rssi
2459                                  lqi_get(p_ack_buffer->data)); // lqi;
2460     }
2461     else
2462     {
2463         on_bad_ack();
2464     }
2465 
2466     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2467 }
2468 
nrf_802154_trx_standalone_cca_finished(bool channel_was_idle)2469 void nrf_802154_trx_standalone_cca_finished(bool channel_was_idle)
2470 {
2471     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2472 
2473     state_set(RADIO_STATE_RX);
2474     rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2475 
2476     cca_notify(channel_was_idle);
2477 
2478     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2479 }
2480 
nrf_802154_trx_transmit_frame_ccastarted(void)2481 void nrf_802154_trx_transmit_frame_ccastarted(void)
2482 {
2483     // This handler provided by trx is never called because parameter notifications_mask
2484     // of the nrf_802154_trx_transmit_frame does not contain TRX_TRANSMIT_NOTIFICATION_CCASTARTED.
2485     assert(false);
2486 }
2487 
nrf_802154_trx_transmit_frame_ccaidle(void)2488 void nrf_802154_trx_transmit_frame_ccaidle(void)
2489 {
2490     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2491 
2492     assert(m_state == RADIO_STATE_CCA_TX);
2493     assert(m_trx_transmit_frame_notifications_mask & TRX_TRANSMIT_NOTIFICATION_CCAIDLE);
2494 
2495 #if (NRF_802154_FRAME_TIMESTAMP_ENABLED)
2496     uint64_t ts = timer_coord_timestamp_get();
2497 
2498     // Configure the timer coordinator to get a timestamp of the PHYEND event.
2499     nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_phyend_event_handle_get());
2500 
2501     // Update stat timestamp of CCASTART event
2502     nrf_802154_stat_timestamp_write(last_cca_start_timestamp, ts);
2503 #endif
2504 
2505     if (m_coex_tx_request_mode == NRF_802154_COEX_TX_REQUEST_MODE_CCA_DONE)
2506     {
2507         nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_TX);
2508         m_flags.tx_diminished_prio = false;
2509     }
2510 
2511     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2512 }
2513 
nrf_802154_trx_transmit_frame_ccabusy(void)2514 void nrf_802154_trx_transmit_frame_ccabusy(void)
2515 {
2516     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2517 
2518     nrf_802154_stat_counter_increment(cca_failed_attempts);
2519 
2520 #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED)
2521     uint32_t t_listening = RX_RAMP_UP_TIME + PHY_US_TIME_FROM_SYMBOLS(A_CCA_DURATION_SYMBOLS);
2522 
2523     nrf_802154_stat_totals_increment(total_listening_time, t_listening);
2524 #endif
2525 
2526     state_set(RADIO_STATE_RX);
2527     rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2528 
2529     nrf_802154_transmit_done_metadata_t metadata = {};
2530 
2531     nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props);
2532     transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_BUSY_CHANNEL, &metadata);
2533 
2534     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2535 }
2536 
nrf_802154_trx_energy_detection_finished(uint8_t ed_sample)2537 void nrf_802154_trx_energy_detection_finished(uint8_t ed_sample)
2538 {
2539     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2540 
2541     if (m_ed_result < ed_sample)
2542     {
2543         // Collect maximum value of samples provided by trx
2544         m_ed_result = ed_sample;
2545     }
2546 
2547     if (m_ed_time_left >= ED_ITER_DURATION)
2548     {
2549         uint32_t trx_ed_count = 0U;
2550 
2551         if (ed_iter_setup(&m_ed_time_left, &trx_ed_count))
2552         {
2553             nrf_802154_trx_energy_detection(trx_ed_count);
2554         }
2555         else
2556         {
2557             /* There is too little time in current timeslot, just wait for timeslot end.
2558              * Operation will be resumed in next timeslot */
2559         }
2560     }
2561     else if (nrf_802154_sl_ant_div_energy_detection_finished_notify())
2562     {
2563         ed_init();
2564     }
2565     else
2566     {
2567         nrf_802154_trx_channel_set(nrf_802154_pib_channel_get());
2568 
2569         state_set(RADIO_STATE_RX);
2570         rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2571 
2572         energy_detected_notify(nrf_802154_rssi_ed_sample_convert(m_ed_result));
2573 
2574     }
2575 
2576     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2577 }
2578 
2579 /***************************************************************************************************
2580  * @section API functions
2581  **************************************************************************************************/
2582 
nrf_802154_core_init(void)2583 void nrf_802154_core_init(void)
2584 {
2585     m_state                    = RADIO_STATE_SLEEP;
2586     m_rsch_timeslot_is_granted = false;
2587     m_rx_prestarted_trig_count = 0;
2588 
2589     nrf_802154_sl_timer_init(&m_rx_prestarted_timer);
2590 
2591     nrf_802154_trx_init();
2592     nrf_802154_ack_generator_init();
2593 }
2594 
nrf_802154_core_deinit(void)2595 void nrf_802154_core_deinit(void)
2596 {
2597     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2598 
2599     if (timeslot_is_granted())
2600     {
2601         nrf_802154_trx_disable();
2602     }
2603 
2604     mpsl_fem_cleanup();
2605 
2606     nrf_802154_irq_disable(nrfx_get_irq_number(NRF_RADIO));
2607     nrf_802154_irq_clear_pending(nrfx_get_irq_number(NRF_RADIO));
2608 
2609     nrf_802154_sl_timer_deinit(&m_rx_prestarted_timer);
2610 
2611     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2612 }
2613 
nrf_802154_core_state_get(void)2614 radio_state_t nrf_802154_core_state_get(void)
2615 {
2616     return m_state;
2617 }
2618 
nrf_802154_core_sleep(nrf_802154_term_t term_lvl)2619 bool nrf_802154_core_sleep(nrf_802154_term_t term_lvl)
2620 {
2621     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2622 
2623     bool result = nrf_802154_critical_section_enter();
2624 
2625     if (result)
2626     {
2627         if ((m_state != RADIO_STATE_SLEEP) && (m_state != RADIO_STATE_FALLING_ASLEEP))
2628         {
2629             result = current_operation_terminate(term_lvl, REQ_ORIG_CORE, true);
2630 
2631             if (result)
2632             {
2633                 // The order of calls in the following blocks is inverted to avoid RAAL races.
2634                 if (timeslot_is_granted())
2635                 {
2636                     state_set(RADIO_STATE_FALLING_ASLEEP);
2637                     falling_asleep_init();
2638                 }
2639                 else
2640                 {
2641                     sleep_init();
2642                     state_set(RADIO_STATE_SLEEP);
2643                 }
2644             }
2645         }
2646 
2647         nrf_802154_critical_section_exit();
2648     }
2649 
2650     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2651 
2652     return result;
2653 }
2654 
nrf_802154_core_receive(nrf_802154_term_t term_lvl,req_originator_t req_orig,nrf_802154_notification_func_t notify_function,bool notify_abort,uint32_t id)2655 bool nrf_802154_core_receive(nrf_802154_term_t              term_lvl,
2656                              req_originator_t               req_orig,
2657                              nrf_802154_notification_func_t notify_function,
2658                              bool                           notify_abort,
2659                              uint32_t                       id)
2660 {
2661     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2662 
2663     bool result = nrf_802154_critical_section_enter();
2664 
2665     if (result)
2666     {
2667         if ((m_state != RADIO_STATE_RX) && (m_state != RADIO_STATE_TX_ACK))
2668         {
2669             if (critical_section_can_be_processed_now())
2670             {
2671                 result = current_operation_terminate(term_lvl, req_orig, notify_abort);
2672 
2673                 if (result)
2674                 {
2675                     m_trx_receive_frame_notifications_mask =
2676                         make_trx_frame_receive_notification_mask();
2677 
2678                     m_rx_window_id = id;
2679                     state_set(RADIO_STATE_RX);
2680 
2681                     bool abort_shall_follow = false;
2682 
2683                     rx_init(ramp_up_mode_choose(req_orig), &abort_shall_follow);
2684 
2685                     if (abort_shall_follow)
2686                     {
2687                         nrf_802154_trx_abort();
2688 
2689                         // HW triggering failed, fallback is SW trigger.
2690                         // (fallback immunizes against the rare case of spurious lptimer firing)
2691                         rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2692                     }
2693                 }
2694             }
2695             else
2696             {
2697                 result = false;
2698             }
2699         }
2700 
2701         if (notify_function != NULL)
2702         {
2703             notify_function(result);
2704         }
2705 
2706         nrf_802154_critical_section_exit();
2707     }
2708     else
2709     {
2710         if (notify_function != NULL)
2711         {
2712             notify_function(false);
2713         }
2714     }
2715 
2716     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2717 
2718     return result;
2719 }
2720 
nrf_802154_core_transmit(nrf_802154_term_t term_lvl,req_originator_t req_orig,uint8_t * p_data,nrf_802154_transmit_params_t * p_params,nrf_802154_notification_func_t notify_function)2721 bool nrf_802154_core_transmit(nrf_802154_term_t              term_lvl,
2722                               req_originator_t               req_orig,
2723                               uint8_t                      * p_data,
2724                               nrf_802154_transmit_params_t * p_params,
2725                               nrf_802154_notification_func_t notify_function)
2726 {
2727     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2728 
2729     bool result = critical_section_enter_and_verify_timeslot_length();
2730 
2731     if (result)
2732     {
2733         if (nrf_802154_core_hooks_pre_transmission(p_data, p_params, &transmit_failed_notify))
2734         {
2735             result = current_operation_terminate(term_lvl, req_orig, true);
2736 
2737             if (result)
2738             {
2739                 nrf_802154_tx_work_buffer_reset(&p_params->frame_props);
2740                 result = nrf_802154_core_hooks_tx_setup(p_data, p_params, &transmit_failed_notify);
2741             }
2742 
2743             if (result)
2744             {
2745                 m_coex_tx_request_mode                  = nrf_802154_pib_coex_tx_request_mode_get();
2746                 m_trx_transmit_frame_notifications_mask =
2747                     make_trx_frame_transmit_notification_mask(p_params->cca);
2748                 m_flags.tx_diminished_prio =
2749                     m_coex_tx_request_mode == NRF_802154_COEX_TX_REQUEST_MODE_CCA_DONE;
2750 
2751                 state_set(p_params->cca ? RADIO_STATE_CCA_TX : RADIO_STATE_TX);
2752                 mp_tx_data = p_data;
2753                 m_tx_power = p_params->tx_power;
2754 
2755                 // coverity[check_return]
2756                 result = tx_init(p_data, ramp_up_mode_choose(req_orig), p_params->cca);
2757 
2758                 if (p_params->immediate)
2759                 {
2760                     if (!result)
2761                     {
2762                         state_set(RADIO_STATE_RX);
2763                         rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2764                     }
2765                 }
2766                 else
2767                 {
2768                     result = true;
2769                 }
2770             }
2771         }
2772 
2773         if (notify_function != NULL)
2774         {
2775             notify_function(result);
2776         }
2777 
2778         nrf_802154_critical_section_exit();
2779     }
2780     else
2781     {
2782         if (notify_function != NULL)
2783         {
2784             notify_function(false);
2785         }
2786     }
2787 
2788     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2789 
2790     return result;
2791 }
2792 
nrf_802154_core_energy_detection(nrf_802154_term_t term_lvl,uint32_t time_us)2793 bool nrf_802154_core_energy_detection(nrf_802154_term_t term_lvl, uint32_t time_us)
2794 {
2795     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2796 
2797     bool result = critical_section_enter_and_verify_timeslot_length();
2798 
2799     if (result)
2800     {
2801         result = current_operation_terminate(term_lvl, REQ_ORIG_CORE, true);
2802 
2803         if (result)
2804         {
2805             if (time_us < ED_ITER_DURATION)
2806             {
2807                 time_us = ED_ITER_DURATION;
2808             }
2809 
2810             m_ed_time_left = time_us;
2811             m_ed_result    = 0;
2812 
2813             state_set(RADIO_STATE_ED);
2814             ed_init();
2815         }
2816 
2817         nrf_802154_critical_section_exit();
2818     }
2819 
2820     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2821 
2822     return result;
2823 }
2824 
nrf_802154_core_cca(nrf_802154_term_t term_lvl)2825 bool nrf_802154_core_cca(nrf_802154_term_t term_lvl)
2826 {
2827     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2828 
2829     bool result = critical_section_enter_and_verify_timeslot_length();
2830 
2831     if (result)
2832     {
2833         result = current_operation_terminate(term_lvl, REQ_ORIG_CORE, true);
2834 
2835         if (result)
2836         {
2837             state_set(RADIO_STATE_CCA);
2838             cca_init();
2839         }
2840 
2841         nrf_802154_critical_section_exit();
2842     }
2843 
2844     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2845 
2846     return result;
2847 }
2848 
2849 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
2850 
nrf_802154_core_continuous_carrier(nrf_802154_term_t term_lvl)2851 bool nrf_802154_core_continuous_carrier(nrf_802154_term_t term_lvl)
2852 {
2853     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2854 
2855     bool result = critical_section_enter_and_verify_timeslot_length();
2856 
2857     if (result)
2858     {
2859         result = current_operation_terminate(term_lvl, REQ_ORIG_CORE, true);
2860 
2861         if (result)
2862         {
2863             state_set(RADIO_STATE_CONTINUOUS_CARRIER);
2864             continuous_carrier_init();
2865         }
2866 
2867         nrf_802154_critical_section_exit();
2868     }
2869 
2870     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2871 
2872     return result;
2873 }
2874 
nrf_802154_core_modulated_carrier(nrf_802154_term_t term_lvl,const uint8_t * p_data)2875 bool nrf_802154_core_modulated_carrier(nrf_802154_term_t term_lvl,
2876                                        const uint8_t   * p_data)
2877 {
2878     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2879 
2880     bool result = critical_section_enter_and_verify_timeslot_length();
2881 
2882     if (result)
2883     {
2884         result = current_operation_terminate(term_lvl, REQ_ORIG_CORE, true);
2885 
2886         if (result)
2887         {
2888             state_set(RADIO_STATE_MODULATED_CARRIER);
2889             mp_tx_data = (uint8_t *)p_data;
2890             modulated_carrier_init(p_data);
2891         }
2892 
2893         nrf_802154_critical_section_exit();
2894     }
2895 
2896     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2897 
2898     return result;
2899 }
2900 
2901 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
2902 
nrf_802154_core_notify_buffer_free(uint8_t * p_data)2903 bool nrf_802154_core_notify_buffer_free(uint8_t * p_data)
2904 {
2905     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2906 
2907     rx_buffer_t * p_buffer     = (rx_buffer_t *)p_data;
2908     bool          in_crit_sect = critical_section_enter_and_verify_timeslot_length();
2909 
2910     p_buffer->free = true;
2911 
2912     if (in_crit_sect)
2913     {
2914         if (timeslot_is_granted())
2915         {
2916             if (nrf_802154_trx_receive_is_buffer_missing())
2917             {
2918                 rx_buffer_in_use_set(p_buffer);
2919                 nrf_802154_trx_receive_buffer_set(rx_buffer_get());
2920             }
2921         }
2922 
2923         nrf_802154_critical_section_exit();
2924     }
2925 
2926     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2927 
2928     return true;
2929 }
2930 
nrf_802154_core_channel_update(req_originator_t req_orig)2931 bool nrf_802154_core_channel_update(req_originator_t req_orig)
2932 {
2933     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2934 
2935     bool result = critical_section_enter_and_verify_timeslot_length();
2936 
2937     if (result)
2938     {
2939         if (timeslot_is_granted())
2940         {
2941             nrf_802154_trx_channel_set(nrf_802154_pib_channel_get());
2942         }
2943 
2944         switch (m_state)
2945         {
2946             case RADIO_STATE_RX:
2947                 if (current_operation_terminate(NRF_802154_TERM_802154, req_orig, true))
2948                 {
2949                     rx_init(TRX_RAMP_UP_SW_TRIGGER, NULL);
2950                 }
2951                 break;
2952 
2953 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
2954             case RADIO_STATE_CONTINUOUS_CARRIER:
2955                 if (timeslot_is_granted())
2956                 {
2957                     nrf_802154_trx_continuous_carrier_restart();
2958                 }
2959                 break;
2960 
2961             case RADIO_STATE_MODULATED_CARRIER:
2962                 if (timeslot_is_granted())
2963                 {
2964                     nrf_802154_trx_modulated_carrier_restart();
2965                 }
2966                 break;
2967 
2968 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
2969             default:
2970                 // Don't perform any additional action in any other state.
2971                 break;
2972         }
2973 
2974         nrf_802154_critical_section_exit();
2975     }
2976 
2977     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2978 
2979     return result;
2980 }
2981 
nrf_802154_core_cca_cfg_update(void)2982 bool nrf_802154_core_cca_cfg_update(void)
2983 {
2984     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
2985 
2986     bool result = critical_section_enter_and_verify_timeslot_length();
2987 
2988     if (result)
2989     {
2990         if (timeslot_is_granted())
2991         {
2992             nrf_802154_trx_cca_configuration_update();
2993         }
2994 
2995         nrf_802154_critical_section_exit();
2996     }
2997 
2998     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
2999 
3000     return result;
3001 }
3002 
nrf_802154_core_rssi_measure(void)3003 bool nrf_802154_core_rssi_measure(void)
3004 {
3005     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
3006 
3007     bool result = critical_section_enter_and_verify_timeslot_length();
3008 
3009     if (result)
3010     {
3011         if (timeslot_is_granted() && (m_state == RADIO_STATE_RX))
3012         {
3013             result = nrf_802154_trx_rssi_measure();
3014         }
3015         else
3016         {
3017             result = false;
3018         }
3019 
3020         nrf_802154_critical_section_exit();
3021     }
3022 
3023     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
3024 
3025     return result;
3026 }
3027 
nrf_802154_core_last_rssi_measurement_get(int8_t * p_rssi)3028 bool nrf_802154_core_last_rssi_measurement_get(int8_t * p_rssi)
3029 {
3030     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
3031 
3032     bool result       = false;
3033     bool in_crit_sect = false;
3034     bool rssi_started = nrf_802154_trx_rssi_measure_is_started();
3035 
3036     if (rssi_started)
3037     {
3038         in_crit_sect = critical_section_enter_and_verify_timeslot_length();
3039     }
3040 
3041     if (rssi_started && in_crit_sect)
3042     {
3043         // Checking if a timeslot is granted is valid only in a critical section
3044         if (timeslot_is_granted())
3045         {
3046             rssi_started = nrf_802154_trx_rssi_measure_is_started();
3047             if (rssi_started)
3048             {
3049                 rssi_measurement_wait();
3050                 *p_rssi = rssi_last_measurement_get();
3051                 result  = true;
3052             }
3053         }
3054     }
3055 
3056     if (in_crit_sect)
3057     {
3058         nrf_802154_critical_section_exit();
3059     }
3060 
3061     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
3062 
3063     return result;
3064 }
3065 
nrf_802154_core_last_frame_rssi_get(void)3066 int8_t  nrf_802154_core_last_frame_rssi_get(void)
3067 {
3068     return m_last_rssi;
3069 }
3070 
nrf_802154_core_last_frame_lqi_get(void)3071 uint8_t nrf_802154_core_last_frame_lqi_get(void)
3072 {
3073     return m_last_lqi;
3074 }
3075 
nrf_802154_core_antenna_update(void)3076 bool nrf_802154_core_antenna_update(void)
3077 {
3078     nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW);
3079 
3080     bool result = critical_section_enter_and_verify_timeslot_length();
3081 
3082     if (result)
3083     {
3084         if (timeslot_is_granted())
3085         {
3086             nrf_802154_trx_antenna_update();
3087         }
3088 
3089         nrf_802154_critical_section_exit();
3090     }
3091 
3092     nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW);
3093 
3094     return result;
3095 }
3096 
nrf_802154_sl_ant_div_rssi_measure_get(void)3097 int8_t nrf_802154_sl_ant_div_rssi_measure_get(void)
3098 {
3099     int8_t result = NRF_802154_RSSI_INVALID;
3100 
3101     // This function is supposed to be called after detecting frame prestarted event, but before
3102     // detecting valid frame address. This means that we're currently in critical section, but the
3103     // timeslot is not yet extended due to detecting valid frame. To avoid invalid timeslot extension
3104     // due to blocking rssi measurements, antenna check can be aborted here if timeslot is about to end.
3105     // Antenna switching takes 200 ns (250 ns with safety margin), while rssi measurement - 250,
3106     // which gives total time of 750 ns.
3107     // 750 ns is less than safety margin, so timeslot us left different than 0 is sufficient.
3108     if (!nrf_802154_rsch_timeslot_us_left_get())
3109     {
3110         return result;
3111     }
3112 
3113     nrf_802154_trx_rssi_measure();
3114 
3115     if (nrf_802154_trx_rssi_measure_is_started())
3116     {
3117         while (!nrf_802154_trx_rssi_sample_is_available())
3118         {
3119             // Intentionally empty: This function is called from a critical section.
3120             // WFE would not be waken up by a RADIO event.
3121         }
3122 
3123         uint8_t rssi_sample = nrf_802154_trx_rssi_last_sample_get();
3124 
3125         rssi_sample = nrf_802154_rssi_sample_corrected_get(rssi_sample);
3126 
3127         result = -((int8_t)rssi_sample);
3128     }
3129 
3130     return result;
3131 }
3132