1 /*
2  * Copyright (c) 2017, 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 requests to the driver triggered by the MAC layer through SWI.
38  *
39  */
40 
41 #include "nrf_802154_request.h"
42 
43 #if NRF_802154_REQUEST_IMPL == NRF_802154_REQUEST_IMPL_SWI
44 
45 #include "nrf_802154_assert.h"
46 #include <stdbool.h>
47 #include <stdint.h>
48 
49 #include "nrf_802154_config.h"
50 #include "nrf_802154_core.h"
51 #include "nrf_802154_critical_section.h"
52 #include "nrf_802154_peripherals.h"
53 #include "nrf_802154_queue.h"
54 #include "nrf_802154_rx_buffer.h"
55 #include "nrf_802154_swi.h"
56 #include "nrf_802154_utils.h"
57 #include "mac_features/nrf_802154_csma_ca.h"
58 #include "hal/nrf_radio.h"
59 #include "hal/nrf_egu.h"
60 #include "mac_features/nrf_802154_delayed_trx.h"
61 #include "platform/nrf_802154_irq.h"
62 
63 #include <nrfx.h>
64 
65 /** Size of requests queue.
66  *
67  * Two is minimal queue size. It is not expected in current implementation to queue a few requests.
68  */
69 #define REQ_QUEUE_SIZE 2
70 
71 #define REQ_INT        NRFX_CONCAT_2(NRF_EGU_INT_TRIGGERED, NRF_802154_EGU_REQUEST_CHANNEL_NO)
72 #define REQ_TASK       NRFX_CONCAT_2(NRF_EGU_TASK_TRIGGER, NRF_802154_EGU_REQUEST_CHANNEL_NO)
73 #define REQ_EVENT      NRFX_CONCAT_2(NRF_EGU_EVENT_TRIGGERED, NRF_802154_EGU_REQUEST_CHANNEL_NO)
74 
75 /// Type of requests in request queue.
76 typedef enum
77 {
78     REQ_TYPE_SLEEP,
79     REQ_TYPE_RECEIVE,
80     REQ_TYPE_TRANSMIT,
81     REQ_TYPE_ACK_TIMEOUT_HANDLE,
82     REQ_TYPE_ENERGY_DETECTION,
83     REQ_TYPE_CCA,
84     REQ_TYPE_CONTINUOUS_CARRIER,
85     REQ_TYPE_MODULATED_CARRIER,
86     REQ_TYPE_BUFFER_FREE,
87     REQ_TYPE_CHANNEL_UPDATE,
88     REQ_TYPE_CCA_CFG_UPDATE,
89     REQ_TYPE_RSSI_MEASURE,
90     REQ_TYPE_RSSI_GET,
91     REQ_TYPE_ANTENNA_UPDATE,
92     REQ_TYPE_TRANSMIT_AT,
93     REQ_TYPE_TRANSMIT_AT_CANCEL,
94     REQ_TYPE_RECEIVE_AT,
95     REQ_TYPE_RECEIVE_AT_CANCEL,
96     REQ_TYPE_CSMA_CA_START,
97 } nrf_802154_req_type_t;
98 
99 /// Request data in request queue.
100 typedef struct
101 {
102     nrf_802154_req_type_t type; ///< Type of the request.
103 
104     union
105     {
106         struct
107         {
108             nrf_802154_term_t term_lvl; ///< Request priority.
109             bool            * p_result; ///< Sleep request result.
110         } sleep;                        ///< Sleep request details.
111 
112         struct
113         {
114             nrf_802154_notification_func_t notif_func;  ///< Error notified in case of success.
115             nrf_802154_term_t              term_lvl;    ///< Request priority.
116             req_originator_t               req_orig;    ///< Request originator.
117             bool                           notif_abort; ///< If function termination should be notified.
118             uint32_t                       id;          ///< Identifier of a reception window.
119             bool                         * p_result;    ///< Receive request result.
120         } receive;                                      ///< Receive request details.
121 
122         struct
123         {
124             nrf_802154_notification_func_t notif_func; ///< Error notified in case of success.
125             nrf_802154_term_t              term_lvl;   ///< Request priority.
126             req_originator_t               req_orig;   ///< Request originator.
127             uint8_t                      * p_data;     ///< Pointer to a buffer containing PHR and PSDU of the frame to transmit.
128             nrf_802154_transmit_params_t * p_params;   ///< Pointer to transmission parameters.
129             bool                         * p_result;   ///< Transmit request result.
130         } transmit;                                    ///< Transmit request details.
131 
132         struct
133         {
134             const nrf_802154_ack_timeout_handle_params_t * p_param;
135             bool                                         * p_result;
136         } ack_timeout_handle;
137 
138         struct
139         {
140             nrf_802154_term_t term_lvl; ///< Request priority.
141             bool            * p_result; ///< Energy detection request result.
142             uint32_t          time_us;  ///< Requested time of energy detection procedure.
143         } energy_detection;             ///< Energy detection request details.
144 
145         struct
146         {
147             nrf_802154_term_t term_lvl; ///< Request priority.
148             bool            * p_result; ///< CCA request result.
149         } cca;                          ///< CCA request details.
150 
151 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
152         struct
153         {
154             nrf_802154_term_t term_lvl; ///< Request priority.
155             bool            * p_result; ///< Continuous carrier request result.
156         } continuous_carrier;           ///< Continuous carrier request details.
157 
158         struct
159         {
160             nrf_802154_term_t term_lvl; ///< Request priority.
161             const uint8_t   * p_data;   ///< Pointer to a buffer to modulate the carrier wave with.
162             bool            * p_result; ///< Modulated carrier request result.
163         } modulated_carrier;            ///< Modulated carrier request details.
164 #endif  // NRF_802154_CARRIER_FUNCTIONS_ENABLED
165 
166         struct
167         {
168             uint8_t * p_data;   ///< Pointer to receive buffer to free.
169             bool    * p_result; ///< Buffer free request result.
170         } buffer_free;          ///< Buffer free request details.
171 
172         struct
173         {
174             req_originator_t req_orig; ///< Request originator.
175             bool           * p_result; ///< Channel update request result.
176         } channel_update;              ///< Channel update request details.
177 
178         struct
179         {
180             bool * p_result; ///< CCA config update request result.
181         } cca_cfg_update;    ///< CCA config update request details.
182 
183         struct
184         {
185             bool * p_result; ///< RSSI measurement request result.
186         } rssi_measure;      ///< RSSI measurement request details.
187 
188         struct
189         {
190             int8_t * p_rssi;   ///< RSSI measurement result.
191             bool   * p_result; ///< RSSI measurement status.
192         } rssi_get;            ///< Details of the getter that retrieves the RSSI measurement result.
193 
194         struct
195         {
196             bool * p_result; ///< Antenna update request result.
197         } antenna_update;    ///< Antenna update request details.
198 
199 #if NRF_802154_DELAYED_TRX_ENABLED
200         struct
201         {
202             uint8_t                                 * p_data;
203             uint64_t                                  tx_time;
204             const nrf_802154_transmit_at_metadata_t * p_metadata;
205             bool                                    * p_result;
206         } transmit_at;
207 
208         struct
209         {
210             bool * p_result;
211         } transmit_at_cancel;
212 
213         struct
214         {
215             uint64_t rx_time;
216             uint32_t timeout;
217             uint8_t  channel;
218             uint32_t id;
219             bool   * p_result;
220         } receive_at;
221 
222         struct
223         {
224             uint32_t id;
225             bool   * p_result;
226         } receive_at_cancel;
227 
228 #endif // NRF_802154_DELAYED_TRX_ENABLED
229 
230         struct
231         {
232             uint8_t                                      * p_data;
233             const nrf_802154_transmit_csma_ca_metadata_t * p_metadata;
234             bool                                         * p_result;
235         } csma_ca_start; ///< Antenna update request details.
236 
237     } data;              ///< Request data depending on its type.
238 } nrf_802154_req_data_t;
239 
240 /**@brief Instance of a requests queue */
241 static nrf_802154_queue_t m_requests_queue;
242 
243 /**@brief Memory holding requests queue items */
244 static nrf_802154_req_data_t m_requests_queue_memory[REQ_QUEUE_SIZE];
245 
246 /**@brief State of the MCU critical section */
247 static volatile nrf_802154_mcu_critical_state_t m_mcu_cs;
248 
249 /**
250  * Enter request block.
251  *
252  * This is a helper function used in all request functions to atomically
253  * find an empty slot in request queue and allow atomic slot update.
254  *
255  * @return Pointer to an empty slot in the request queue.
256  */
req_enter(void)257 static nrf_802154_req_data_t * req_enter(void)
258 {
259     nrf_802154_mcu_critical_enter(m_mcu_cs);
260 
261     NRF_802154_ASSERT(!nrf_802154_queue_is_full(&m_requests_queue));
262 
263     return (nrf_802154_req_data_t *)nrf_802154_queue_push_begin(&m_requests_queue);
264 }
265 
266 /**
267  * Exit request block.
268  *
269  * This is a helper function used in all request functions to end atomic slot update
270  * and trigger SWI to process the request from the slot.
271  */
req_exit(void)272 static void req_exit(void)
273 {
274     nrf_802154_queue_push_commit(&m_requests_queue);
275 
276     nrf_egu_task_trigger(NRF_802154_EGU_INSTANCE, REQ_TASK);
277 
278     nrf_802154_mcu_critical_exit(m_mcu_cs);
279 }
280 
281 /** Assert if SWI interrupt is disabled. */
assert_interrupt_status(void)282 static inline void assert_interrupt_status(void)
283 {
284     NRF_802154_ASSERT(nrf_802154_irq_is_enabled(nrfx_get_irq_number(NRF_802154_EGU_INSTANCE)));
285 }
286 
287 #define REQUEST_FUNCTION(func_core, func_swi, ...) \
288     bool result = false;                           \
289                                                    \
290     if (active_vector_priority_is_high())          \
291     {                                              \
292         result = func_core(__VA_ARGS__);           \
293     }                                              \
294     else                                           \
295     {                                              \
296         assert_interrupt_status();                 \
297         func_swi(__VA_ARGS__, &result);            \
298     }                                              \
299                                                    \
300     return result;
301 
302 #define REQUEST_FUNCTION_NO_ARGS(func_core, func_swi) \
303     bool result = false;                              \
304                                                       \
305     if (active_vector_priority_is_high())             \
306     {                                                 \
307         result = func_core();                         \
308     }                                                 \
309     else                                              \
310     {                                                 \
311         assert_interrupt_status();                    \
312         func_swi(&result);                            \
313     }                                                 \
314                                                       \
315     return result;
316 
317 /** Check if active vector priority is high enough to call requests directly.
318  *
319  *  @retval  true   Active vector priority is greater or equal to SWI priority.
320  *  @retval  false  Active vector priority is lower than SWI priority.
321  */
active_vector_priority_is_high(void)322 static bool active_vector_priority_is_high(void)
323 {
324 
325     return nrf_802154_critical_section_active_vector_priority_get() <=
326            nrf_802154_irq_priority_get(nrfx_get_irq_number(NRF_802154_EGU_INSTANCE));
327 }
328 
329 /**
330  * @brief Requests entering the @ref RADIO_STATE_SLEEP state from the SWI priority.
331  *
332  * @param[in]   term_lvl  Termination level of this request. Selects procedures to abort.
333  * @param[out]  p_result  Result of entering the sleep state.
334  */
swi_sleep(nrf_802154_term_t term_lvl,bool * p_result)335 static void swi_sleep(nrf_802154_term_t term_lvl, bool * p_result)
336 {
337     nrf_802154_req_data_t * p_slot = req_enter();
338 
339     p_slot->type                = REQ_TYPE_SLEEP;
340     p_slot->data.sleep.term_lvl = term_lvl;
341     p_slot->data.sleep.p_result = p_result;
342 
343     req_exit();
344 }
345 
346 /**
347  * @brief Requests entering the @ref RADIO_STATE_RX state from the SWI priority.
348  *
349  * @param[in]   term_lvl         Termination level of this request. Selects procedures to abort.
350  * @param[in]   req_orig         Module that originates this request.
351  * @param[in]   notify_function  Function called to notify the status of the procedure. May be NULL.
352  * @param[in]   notify_abort     If abort notification should be triggered automatically.
353  * @param[in]   id               Identifier of the reception window.
354  * @param[out]  p_result         Result of entering the receive state.
355  */
swi_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,bool * p_result)356 static void swi_receive(nrf_802154_term_t              term_lvl,
357                         req_originator_t               req_orig,
358                         nrf_802154_notification_func_t notify_function,
359                         bool                           notify_abort,
360                         uint32_t                       id,
361                         bool                         * p_result)
362 {
363     nrf_802154_req_data_t * p_slot = req_enter();
364 
365     p_slot->type                     = REQ_TYPE_RECEIVE;
366     p_slot->data.receive.term_lvl    = term_lvl;
367     p_slot->data.receive.req_orig    = req_orig;
368     p_slot->data.receive.notif_func  = notify_function;
369     p_slot->data.receive.notif_abort = notify_abort;
370     p_slot->data.receive.id          = id;
371     p_slot->data.receive.p_result    = p_result;
372 
373     req_exit();
374 }
375 
376 /**
377  * @biref Requests entering the @ref RADIO_STATE_TX state from the SWI priority.
378  *
379  * @param[in]   term_lvl         Termination level of this request. Selects procedures to abort.
380  * @param[in]   req_orig         Module that originates this request.
381  * @param[in]   p_data           Pointer to a buffer that contains PHR and PSDU of the frame to be
382  *                               transmitted.
383  * @param[in]   p_params         Pointer to transmission parameters.
384  * @param[in]   notify_function  Function called to notify the status of this procedure instead of
385  *                               the default notification. If NULL, the default notification
386  *                               is used.
387  * @param[out]  p_result         Result of entering the transmit state.
388  */
swi_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,bool * p_result)389 static void swi_transmit(nrf_802154_term_t              term_lvl,
390                          req_originator_t               req_orig,
391                          uint8_t                      * p_data,
392                          nrf_802154_transmit_params_t * p_params,
393                          nrf_802154_notification_func_t notify_function,
394                          bool                         * p_result)
395 {
396     nrf_802154_req_data_t * p_slot = req_enter();
397 
398     p_slot->type                     = REQ_TYPE_TRANSMIT;
399     p_slot->data.transmit.term_lvl   = term_lvl;
400     p_slot->data.transmit.req_orig   = req_orig;
401     p_slot->data.transmit.p_data     = p_data;
402     p_slot->data.transmit.p_params   = p_params;
403     p_slot->data.transmit.notif_func = notify_function;
404     p_slot->data.transmit.p_result   = p_result;
405 
406     req_exit();
407 }
408 
swi_ack_timeout_handle(const nrf_802154_ack_timeout_handle_params_t * p_param,bool * p_result)409 static void swi_ack_timeout_handle(const nrf_802154_ack_timeout_handle_params_t * p_param,
410                                    bool                                         * p_result)
411 {
412     nrf_802154_req_data_t * p_slot = req_enter();
413 
414     p_slot->type                             = REQ_TYPE_ACK_TIMEOUT_HANDLE;
415     p_slot->data.ack_timeout_handle.p_param  = p_param;
416     p_slot->data.ack_timeout_handle.p_result = p_result;
417 
418     req_exit();
419 }
420 
421 /**
422  * @brief Requests entering the @ref RADIO_STATE_ED state from the SWI priority.
423  *
424  * @param[in]   term_lvl  Termination level of this request. Selects procedures to abort.
425  * @param[in]   time_us   Requested duration of the energy detection procedure.
426  * @param[out]  p_result  Result of entering the energy detection state.
427  */
swi_energy_detection(nrf_802154_term_t term_lvl,uint32_t time_us,bool * p_result)428 static void swi_energy_detection(nrf_802154_term_t term_lvl,
429                                  uint32_t          time_us,
430                                  bool            * p_result)
431 {
432     nrf_802154_req_data_t * p_slot = req_enter();
433 
434     p_slot->type                           = REQ_TYPE_ENERGY_DETECTION;
435     p_slot->data.energy_detection.term_lvl = term_lvl;
436     p_slot->data.energy_detection.time_us  = time_us;
437     p_slot->data.energy_detection.p_result = p_result;
438 
439     req_exit();
440 }
441 
442 /**
443  * @brief Requests entering the @ref RADIO_STATE_CCA state from the SWI priority.
444  *
445  * @param[in]   term_lvl  Termination level of this request. Selects procedures to abort.
446  * @param[out]  p_result  Result of entering the CCA state.
447  */
swi_cca(nrf_802154_term_t term_lvl,bool * p_result)448 static void swi_cca(nrf_802154_term_t term_lvl, bool * p_result)
449 {
450     nrf_802154_req_data_t * p_slot = req_enter();
451 
452     p_slot->type              = REQ_TYPE_CCA;
453     p_slot->data.cca.term_lvl = term_lvl;
454     p_slot->data.cca.p_result = p_result;
455 
456     req_exit();
457 }
458 
459 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
460 
461 /**
462  * @brief Requests entering the @ref RADIO_STATE_CONTINUOUS_CARRIER state from the SWI priority.
463  *
464  * @param[in]   term_lvl  Termination level of this request. Selects procedures to abort.
465  * @param[out]  p_result  Result of entering the continuous carrier state.
466  */
swi_continuous_carrier(nrf_802154_term_t term_lvl,bool * p_result)467 static void swi_continuous_carrier(nrf_802154_term_t term_lvl, bool * p_result)
468 {
469     nrf_802154_req_data_t * p_slot = req_enter();
470 
471     p_slot->type                             = REQ_TYPE_CONTINUOUS_CARRIER;
472     p_slot->data.continuous_carrier.term_lvl = term_lvl;
473     p_slot->data.continuous_carrier.p_result = p_result;
474 
475     req_exit();
476 }
477 
478 /**
479  * @brief Requests entering the @ref RADIO_STATE_MODULATED_CARRIER state from the SWI priority.
480  *
481  * @param[in]   term_lvl  Termination level of this request. Selects procedures to abort.
482  * @param[in]   p_data    Pointer to the data buffer to modulate the carrier wave with.
483  * @param[out]  p_result  Result of entering the modulated carrier state.
484  */
swi_modulated_carrier(nrf_802154_term_t term_lvl,const uint8_t * p_data,bool * p_result)485 static void swi_modulated_carrier(nrf_802154_term_t term_lvl,
486                                   const uint8_t   * p_data,
487                                   bool            * p_result)
488 {
489     nrf_802154_req_data_t * p_slot = req_enter();
490 
491     p_slot->type                            = REQ_TYPE_MODULATED_CARRIER;
492     p_slot->data.modulated_carrier.term_lvl = term_lvl;
493     p_slot->data.modulated_carrier.p_data   = p_data;
494     p_slot->data.modulated_carrier.p_result = p_result;
495 
496     req_exit();
497 }
498 
499 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
500 
501 /**
502  * @brief Notifies the core module that the given buffer is not used anymore and can be freed.
503  *
504  * @param[in]  p_data   Pointer to the buffer to be freed.
505  * @param[out] p_result Pointer where the result to be returned by
506  *                      nrf_802154_request_buffer_free should be written by the swi handler.
507  */
swi_buffer_free(uint8_t * p_data,bool * p_result)508 static void swi_buffer_free(uint8_t * p_data, bool * p_result)
509 {
510     nrf_802154_req_data_t * p_slot = req_enter();
511 
512     p_slot->type                      = REQ_TYPE_BUFFER_FREE;
513     p_slot->data.buffer_free.p_data   = p_data;
514     p_slot->data.buffer_free.p_result = p_result;
515 
516     req_exit();
517 }
518 
519 /**
520  * @brief Notifies the core module that the next higher layer has requested an antenna change.
521  *
522  * @param[out] p_result Pointer where the result to be returned by
523  *                      nrf_802154_request_antenna_update should be written by the swi handler.
524  */
swi_antenna_update(bool * p_result)525 static void swi_antenna_update(bool * p_result)
526 {
527     nrf_802154_req_data_t * p_slot = req_enter();
528 
529     p_slot->type                         = REQ_TYPE_ANTENNA_UPDATE;
530     p_slot->data.antenna_update.p_result = p_result;
531 
532     req_exit();
533 }
534 
535 /**
536  * @brief Notifies the core module that the next higher layer has requested a channel change.
537  *
538  * @param[out] p_result Pointer where the result to be returned by
539  *                      nrf_802154_request_channel_update should be written by the swi handler.
540  */
swi_channel_update(req_originator_t req_orig,bool * p_result)541 static void swi_channel_update(req_originator_t req_orig, bool * p_result)
542 {
543     nrf_802154_req_data_t * p_slot = req_enter();
544 
545     p_slot->type                         = REQ_TYPE_CHANNEL_UPDATE;
546     p_slot->data.channel_update.p_result = p_result;
547     p_slot->data.channel_update.req_orig = req_orig;
548 
549     req_exit();
550 }
551 
552 /**
553  * @brief Notifies the core module that the next higher layer has requested a CCA configuration
554  * change.
555  * @param[out] p_result Pointer where the result to be returned by
556  *                      nrf_802154_request_cca_cfg_update should be written by the swi handler.
557  */
swi_cca_cfg_update(bool * p_result)558 static void swi_cca_cfg_update(bool * p_result)
559 {
560     nrf_802154_req_data_t * p_slot = req_enter();
561 
562     p_slot->type                         = REQ_TYPE_CCA_CFG_UPDATE;
563     p_slot->data.cca_cfg_update.p_result = p_result;
564 
565     req_exit();
566 }
567 
568 /**
569  * @brief Notifies the core module that the next higher layer requested the RSSI measurement.
570  *
571  * @param[out] p_result Pointer where the result to be returned by
572  *                      nrf_802154_request_rssi_measure should be written by the swi handler.
573  */
swi_rssi_measure(bool * p_result)574 static void swi_rssi_measure(bool * p_result)
575 {
576     nrf_802154_req_data_t * p_slot = req_enter();
577 
578     p_slot->type                       = REQ_TYPE_RSSI_MEASURE;
579     p_slot->data.rssi_measure.p_result = p_result;
580 
581     req_exit();
582 }
583 
584 /**
585  * @brief Gets the last RSSI measurement result from the core module.
586  *
587  * @param[out] p_rssi   Pointer where RSSI measurement value will be stored.
588  * @param[out] p_result Pointer where the result to be returned by
589  *                      nrf_802154_request_rssi_measurement_get should be written by the swi handler.
590  */
swi_rssi_measurement_get(int8_t * p_rssi,bool * p_result)591 static void swi_rssi_measurement_get(int8_t * p_rssi, bool * p_result)
592 {
593     nrf_802154_req_data_t * p_slot = req_enter();
594 
595     p_slot->type                   = REQ_TYPE_RSSI_GET;
596     p_slot->data.rssi_get.p_rssi   = p_rssi;
597     p_slot->data.rssi_get.p_result = p_result;
598 
599     req_exit();
600 }
601 
602 #if NRF_802154_DELAYED_TRX_ENABLED
swi_transmit_at(uint8_t * p_data,uint64_t tx_time,const nrf_802154_transmit_at_metadata_t * p_metadata,bool * p_result)603 static void swi_transmit_at(uint8_t                                 * p_data,
604                             uint64_t                                  tx_time,
605                             const nrf_802154_transmit_at_metadata_t * p_metadata,
606                             bool                                    * p_result)
607 {
608     nrf_802154_req_data_t * p_slot = req_enter();
609 
610     p_slot->type                        = REQ_TYPE_TRANSMIT_AT;
611     p_slot->data.transmit_at.p_data     = p_data;
612     p_slot->data.transmit_at.tx_time    = tx_time;
613     p_slot->data.transmit_at.p_metadata = p_metadata;
614     p_slot->data.transmit_at.p_result   = p_result;
615 
616     req_exit();
617 }
618 
swi_transmit_at_cancel(bool * p_result)619 static void swi_transmit_at_cancel(bool * p_result)
620 {
621     nrf_802154_req_data_t * p_slot = req_enter();
622 
623     p_slot->type                             = REQ_TYPE_TRANSMIT_AT_CANCEL;
624     p_slot->data.transmit_at_cancel.p_result = p_result;
625 
626     req_exit();
627 }
628 
swi_receive_at(uint64_t rx_time,uint32_t timeout,uint8_t channel,uint32_t id,bool * p_result)629 static void swi_receive_at(uint64_t rx_time,
630                            uint32_t timeout,
631                            uint8_t  channel,
632                            uint32_t id,
633                            bool   * p_result)
634 {
635     nrf_802154_req_data_t * p_slot = req_enter();
636 
637     p_slot->type                     = REQ_TYPE_RECEIVE_AT;
638     p_slot->data.receive_at.rx_time  = rx_time;
639     p_slot->data.receive_at.timeout  = timeout;
640     p_slot->data.receive_at.channel  = channel;
641     p_slot->data.receive_at.id       = id;
642     p_slot->data.receive_at.p_result = p_result;
643 
644     req_exit();
645 }
646 
swi_receive_at_cancel(uint32_t id,bool * p_result)647 static void swi_receive_at_cancel(uint32_t id, bool * p_result)
648 {
649     nrf_802154_req_data_t * p_slot = req_enter();
650 
651     p_slot->type                            = REQ_TYPE_RECEIVE_AT_CANCEL;
652     p_slot->data.receive_at_cancel.id       = id;
653     p_slot->data.receive_at_cancel.p_result = p_result;
654 
655     req_exit();
656 }
657 
658 #endif // NRF_802154_DELAYED_TRX_ENABLED
659 
swi_csma_ca_start(uint8_t * p_data,const nrf_802154_transmit_csma_ca_metadata_t * p_metadata,bool * p_result)660 static void swi_csma_ca_start(uint8_t                                      * p_data,
661                               const nrf_802154_transmit_csma_ca_metadata_t * p_metadata,
662                               bool                                         * p_result)
663 {
664     nrf_802154_req_data_t * p_slot = req_enter();
665 
666     p_slot->type                          = REQ_TYPE_CSMA_CA_START;
667     p_slot->data.csma_ca_start.p_data     = p_data;
668     p_slot->data.csma_ca_start.p_metadata = p_metadata;
669     p_slot->data.csma_ca_start.p_result   = p_result;
670     req_exit();
671 }
672 
nrf_802154_request_init(void)673 void nrf_802154_request_init(void)
674 {
675     nrf_802154_queue_init(&m_requests_queue,
676                           m_requests_queue_memory,
677                           sizeof(m_requests_queue_memory),
678                           sizeof(m_requests_queue_memory[0]));
679 
680     nrf_egu_int_enable(NRF_802154_EGU_INSTANCE, REQ_INT);
681 
682     nrf_802154_swi_init();
683 }
684 
nrf_802154_request_sleep(nrf_802154_term_t term_lvl)685 bool nrf_802154_request_sleep(nrf_802154_term_t term_lvl)
686 {
687     REQUEST_FUNCTION(nrf_802154_core_sleep, swi_sleep, term_lvl)
688 }
689 
nrf_802154_request_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)690 bool nrf_802154_request_receive(nrf_802154_term_t              term_lvl,
691                                 req_originator_t               req_orig,
692                                 nrf_802154_notification_func_t notify_function,
693                                 bool                           notify_abort,
694                                 uint32_t                       id)
695 {
696     REQUEST_FUNCTION(nrf_802154_core_receive,
697                      swi_receive,
698                      term_lvl,
699                      req_orig,
700                      notify_function,
701                      notify_abort,
702                      id)
703 }
704 
nrf_802154_request_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)705 bool nrf_802154_request_transmit(nrf_802154_term_t              term_lvl,
706                                  req_originator_t               req_orig,
707                                  uint8_t                      * p_data,
708                                  nrf_802154_transmit_params_t * p_params,
709                                  nrf_802154_notification_func_t notify_function)
710 {
711     REQUEST_FUNCTION(nrf_802154_core_transmit,
712                      swi_transmit,
713                      term_lvl,
714                      req_orig,
715                      p_data,
716                      p_params,
717                      notify_function)
718 }
719 
nrf_802154_request_ack_timeout_handle(const nrf_802154_ack_timeout_handle_params_t * p_param)720 bool nrf_802154_request_ack_timeout_handle(const nrf_802154_ack_timeout_handle_params_t * p_param)
721 {
722     REQUEST_FUNCTION(nrf_802154_core_ack_timeout_handle, swi_ack_timeout_handle, p_param);
723 }
724 
nrf_802154_request_energy_detection(nrf_802154_term_t term_lvl,uint32_t time_us)725 bool nrf_802154_request_energy_detection(nrf_802154_term_t term_lvl,
726                                          uint32_t          time_us)
727 {
728     REQUEST_FUNCTION(nrf_802154_core_energy_detection,
729                      swi_energy_detection,
730                      term_lvl,
731                      time_us)
732 }
733 
nrf_802154_request_cca(nrf_802154_term_t term_lvl)734 bool nrf_802154_request_cca(nrf_802154_term_t term_lvl)
735 {
736     REQUEST_FUNCTION(nrf_802154_core_cca, swi_cca, term_lvl)
737 }
738 
739 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl)740 bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl)
741 {
742     REQUEST_FUNCTION(nrf_802154_core_continuous_carrier,
743                      swi_continuous_carrier,
744                      term_lvl)
745 }
746 
nrf_802154_request_modulated_carrier(nrf_802154_term_t term_lvl,const uint8_t * p_data)747 bool nrf_802154_request_modulated_carrier(nrf_802154_term_t term_lvl,
748                                           const uint8_t   * p_data)
749 {
750     REQUEST_FUNCTION(nrf_802154_core_modulated_carrier,
751                      swi_modulated_carrier,
752                      term_lvl,
753                      p_data)
754 }
755 
756 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
757 
nrf_802154_request_buffer_free(uint8_t * p_data)758 bool nrf_802154_request_buffer_free(uint8_t * p_data)
759 {
760     REQUEST_FUNCTION(nrf_802154_core_notify_buffer_free, swi_buffer_free, p_data)
761 }
762 
nrf_802154_request_antenna_update(void)763 bool nrf_802154_request_antenna_update(void)
764 {
765     REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_antenna_update, swi_antenna_update)
766 }
767 
nrf_802154_request_channel_update(req_originator_t req_orig)768 bool nrf_802154_request_channel_update(req_originator_t req_orig)
769 {
770     REQUEST_FUNCTION(nrf_802154_core_channel_update, swi_channel_update, req_orig)
771 }
772 
nrf_802154_request_cca_cfg_update(void)773 bool nrf_802154_request_cca_cfg_update(void)
774 {
775     REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_cca_cfg_update, swi_cca_cfg_update)
776 }
777 
nrf_802154_request_rssi_measure(void)778 bool nrf_802154_request_rssi_measure(void)
779 {
780     REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_rssi_measure, swi_rssi_measure)
781 }
782 
nrf_802154_request_rssi_measurement_get(int8_t * p_rssi)783 bool nrf_802154_request_rssi_measurement_get(int8_t * p_rssi)
784 {
785     REQUEST_FUNCTION(nrf_802154_core_last_rssi_measurement_get,
786                      swi_rssi_measurement_get,
787                      p_rssi)
788 }
789 
790 #if NRF_802154_DELAYED_TRX_ENABLED
nrf_802154_request_transmit_raw_at(uint8_t * p_data,uint64_t tx_time,const nrf_802154_transmit_at_metadata_t * p_metadata)791 bool nrf_802154_request_transmit_raw_at(uint8_t                                 * p_data,
792                                         uint64_t                                  tx_time,
793                                         const nrf_802154_transmit_at_metadata_t * p_metadata)
794 {
795     REQUEST_FUNCTION(nrf_802154_delayed_trx_transmit, swi_transmit_at, p_data, tx_time, p_metadata);
796 }
797 
nrf_802154_request_transmit_at_cancel(void)798 bool nrf_802154_request_transmit_at_cancel(void)
799 {
800     REQUEST_FUNCTION_NO_ARGS(nrf_802154_delayed_trx_transmit_cancel, swi_transmit_at_cancel);
801 }
802 
nrf_802154_request_receive_at(uint64_t rx_time,uint32_t timeout,uint8_t channel,uint32_t id)803 bool nrf_802154_request_receive_at(uint64_t rx_time,
804                                    uint32_t timeout,
805                                    uint8_t  channel,
806                                    uint32_t id)
807 {
808     REQUEST_FUNCTION(nrf_802154_delayed_trx_receive, swi_receive_at, rx_time, timeout, channel, id);
809 }
810 
nrf_802154_request_receive_at_cancel(uint32_t id)811 bool nrf_802154_request_receive_at_cancel(uint32_t id)
812 {
813     REQUEST_FUNCTION(nrf_802154_delayed_trx_receive_cancel, swi_receive_at_cancel, id);
814 }
815 
nrf_802154_request_csma_ca_start(uint8_t * p_data,const nrf_802154_transmit_csma_ca_metadata_t * p_metadata)816 bool nrf_802154_request_csma_ca_start(uint8_t                                      * p_data,
817                                       const nrf_802154_transmit_csma_ca_metadata_t * p_metadata)
818 {
819     REQUEST_FUNCTION(nrf_802154_csma_ca_start,
820                      swi_csma_ca_start,
821                      p_data,
822                      p_metadata);
823 }
824 
825 #endif // NRF_802154_DELAYED_TRX_ENABLED
826 
827 /**@brief Handles REQ_EVENT on NRF_802154_EGU_INSTANCE */
irq_handler_req_event(void)828 static void irq_handler_req_event(void)
829 {
830     while (!nrf_802154_queue_is_empty(&m_requests_queue))
831     {
832         nrf_802154_req_data_t * p_slot =
833             (nrf_802154_req_data_t *)nrf_802154_queue_pop_begin(&m_requests_queue);
834 
835         switch (p_slot->type)
836         {
837             case REQ_TYPE_SLEEP:
838                 *(p_slot->data.sleep.p_result) =
839                     nrf_802154_core_sleep(p_slot->data.sleep.term_lvl);
840                 break;
841 
842             case REQ_TYPE_RECEIVE:
843                 *(p_slot->data.receive.p_result) =
844                     nrf_802154_core_receive(p_slot->data.receive.term_lvl,
845                                             p_slot->data.receive.req_orig,
846                                             p_slot->data.receive.notif_func,
847                                             p_slot->data.receive.notif_abort,
848                                             p_slot->data.receive.id);
849                 break;
850 
851             case REQ_TYPE_TRANSMIT:
852                 *(p_slot->data.transmit.p_result) =
853                     nrf_802154_core_transmit(p_slot->data.transmit.term_lvl,
854                                              p_slot->data.transmit.req_orig,
855                                              p_slot->data.transmit.p_data,
856                                              p_slot->data.transmit.p_params,
857                                              p_slot->data.transmit.notif_func);
858                 break;
859 
860             case REQ_TYPE_ACK_TIMEOUT_HANDLE:
861                 *(p_slot->data.ack_timeout_handle.p_result) =
862                     nrf_802154_core_ack_timeout_handle(p_slot->data.ack_timeout_handle.p_param);
863                 break;
864 
865             case REQ_TYPE_ENERGY_DETECTION:
866                 *(p_slot->data.energy_detection.p_result) =
867                     nrf_802154_core_energy_detection(
868                         p_slot->data.energy_detection.term_lvl,
869                         p_slot->data.energy_detection.time_us);
870                 break;
871 
872             case REQ_TYPE_CCA:
873                 *(p_slot->data.cca.p_result) = nrf_802154_core_cca(p_slot->data.cca.term_lvl);
874                 break;
875 
876 #if NRF_802154_CARRIER_FUNCTIONS_ENABLED
877 
878             case REQ_TYPE_CONTINUOUS_CARRIER:
879                 *(p_slot->data.continuous_carrier.p_result) =
880                     nrf_802154_core_continuous_carrier(
881                         p_slot->data.continuous_carrier.term_lvl);
882                 break;
883 
884             case REQ_TYPE_MODULATED_CARRIER:
885                 *(p_slot->data.modulated_carrier.p_result) =
886                     nrf_802154_core_modulated_carrier(p_slot->data.modulated_carrier.term_lvl,
887                                                       p_slot->data.modulated_carrier.p_data);
888                 break;
889 
890 #endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED
891 
892             case REQ_TYPE_BUFFER_FREE:
893                 *(p_slot->data.buffer_free.p_result) =
894                     nrf_802154_core_notify_buffer_free(p_slot->data.buffer_free.p_data);
895                 break;
896 
897             case REQ_TYPE_CHANNEL_UPDATE:
898                 *(p_slot->data.channel_update.p_result) =
899                     nrf_802154_core_channel_update(p_slot->data.channel_update.req_orig);
900                 break;
901 
902             case REQ_TYPE_CCA_CFG_UPDATE:
903                 *(p_slot->data.cca_cfg_update.p_result) = nrf_802154_core_cca_cfg_update();
904                 break;
905 
906             case REQ_TYPE_RSSI_MEASURE:
907                 *(p_slot->data.rssi_measure.p_result) = nrf_802154_core_rssi_measure();
908                 break;
909 
910             case REQ_TYPE_RSSI_GET:
911                 *(p_slot->data.rssi_get.p_result) =
912                     nrf_802154_core_last_rssi_measurement_get(p_slot->data.rssi_get.p_rssi);
913                 break;
914 
915             case REQ_TYPE_ANTENNA_UPDATE:
916                 *(p_slot->data.antenna_update.p_result) = nrf_802154_core_antenna_update();
917                 break;
918 
919 #if NRF_802154_DELAYED_TRX_ENABLED
920             case REQ_TYPE_TRANSMIT_AT:
921                 *(p_slot->data.transmit_at.p_result) =
922                     nrf_802154_delayed_trx_transmit(p_slot->data.transmit_at.p_data,
923                                                     p_slot->data.transmit_at.tx_time,
924                                                     p_slot->data.transmit_at.p_metadata);
925                 break;
926 
927             case REQ_TYPE_TRANSMIT_AT_CANCEL:
928                 *(p_slot->data.transmit_at_cancel.p_result) =
929                     nrf_802154_delayed_trx_transmit_cancel();
930                 break;
931 
932             case REQ_TYPE_RECEIVE_AT:
933                 *(p_slot->data.receive_at.p_result) =
934                     nrf_802154_delayed_trx_receive(p_slot->data.receive_at.rx_time,
935                                                    p_slot->data.receive_at.timeout,
936                                                    p_slot->data.receive_at.channel,
937                                                    p_slot->data.receive_at.id);
938                 break;
939 
940             case REQ_TYPE_RECEIVE_AT_CANCEL:
941                 *(p_slot->data.receive_at_cancel.p_result) =
942                     nrf_802154_delayed_trx_receive_cancel(p_slot->data.receive_at_cancel.id);
943                 break;
944 
945             case REQ_TYPE_CSMA_CA_START:
946                 *(p_slot->data.csma_ca_start.p_result) =
947                     nrf_802154_csma_ca_start(p_slot->data.csma_ca_start.p_data,
948                                              p_slot->data.csma_ca_start.p_metadata);
949                 break;
950 #endif // NRF_802154_DELAYED_TRX_ENABLED
951 
952             default:
953                 NRF_802154_ASSERT(false);
954         }
955 
956         nrf_802154_queue_pop_commit(&m_requests_queue);
957     }
958 }
959 
nrf_802154_request_swi_irq_handler(void)960 void nrf_802154_request_swi_irq_handler(void)
961 {
962     if (nrf_egu_event_check(NRF_802154_EGU_INSTANCE, REQ_EVENT))
963     {
964         nrf_egu_event_clear(NRF_802154_EGU_INSTANCE, REQ_EVENT);
965 
966         irq_handler_req_event();
967     }
968 }
969 
970 #endif /* NRF_802154_REQUEST_IMPL == NRF_802154_REQUEST_IMPL_SWI */
971