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