@@ -69,8 +69,8 @@ typedef enum
69
69
{
70
70
CSMA_CA_STATE_IDLE , ///< The CSMA-CA procedure is inactive.
71
71
CSMA_CA_STATE_BACKOFF , ///< The CSMA-CA procedure is in backoff stage.
72
- CSMA_CA_STATE_ONGOING , ///< The frame is being sent .
73
- CSMA_CA_STATE_ABORTED ///< The CSMA-CA procedure is being aborted .
72
+ CSMA_CA_STATE_ATTEMPTING_CCATX , ///< The frame transmit attempt is in progress .
73
+ CSMA_CA_STATE_TRANSMITTING , ///< The frame has begun transmission .
74
74
} csma_ca_state_t ;
75
75
76
76
static uint8_t m_nb ; ///< The number of times the CSMA-CA algorithm was required to back off while attempting the current transmission.
@@ -85,17 +85,29 @@ static bool m_tx_timestamp_encode; ///< Tx timestamp requ
85
85
#endif
86
86
static csma_ca_state_t m_state ; ///< The current state of the CSMA-CA procedure.
87
87
88
- /**
89
- * @brief Perform appropriate actions for busy channel conditions.
90
- *
91
- * According to CSMA-CA description in 802.15.4 specification, when channel is busy NB and BE shall
92
- * be incremented and the device shall wait random delay before next CCA procedure. If NB reaches
93
- * macMaxCsmaBackoffs procedure fails.
94
- *
95
- * @retval true Procedure failed and TX failure should be notified to the next higher layer.
96
- * @retval false Procedure is still ongoing and TX failure should be handled internally.
97
- */
98
- static bool channel_busy (void );
88
+ static bool csma_ca_can_abort (nrf_802154_term_t term_lvl ,
89
+ req_originator_t req_orig ,
90
+ const nrf_802154_tx_client_t * p_client );
91
+ static void csma_ca_failed (uint8_t * p_frame ,
92
+ nrf_802154_tx_error_t error ,
93
+ const nrf_802154_transmit_done_metadata_t * p_metadata ,
94
+ const nrf_802154_tx_client_t * p_client );
95
+ static void csma_ca_tx_started (const nrf_802154_tx_client_t * p_client );
96
+
97
+ static void csma_ca_tx_done (uint8_t * p_frame ,
98
+ const nrf_802154_transmit_done_metadata_t * p_metadata ,
99
+ const nrf_802154_tx_client_t * p_client );
100
+
101
+ static const nrf_802154_tx_client_interface_t m_csma_ca_tx_client_iface = {
102
+ .can_abort = csma_ca_can_abort ,
103
+ .failed = csma_ca_failed ,
104
+ .started = csma_ca_tx_started ,
105
+ .done = csma_ca_tx_done ,
106
+ };
107
+
108
+ static nrf_802154_tx_client_t m_csma_ca_tx_client = {
109
+ .p_iface = & m_csma_ca_tx_client_iface ,
110
+ };
99
111
100
112
static bool csma_ca_state_set (csma_ca_state_t expected , csma_ca_state_t desired )
101
113
{
@@ -137,44 +149,6 @@ static void priority_leverage(void)
137
149
nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_HIGH );
138
150
}
139
151
140
- /**
141
- * @brief Notify MAC layer that CSMA-CA failed
142
- *
143
- * @param[in] error The error that caused the failure
144
- */
145
- static void notify_failed (nrf_802154_tx_error_t error )
146
- {
147
- // core rejected attempt, use my current frame_props
148
- nrf_802154_transmit_done_metadata_t metadata = {};
149
-
150
- metadata .frame_props = m_data_props ;
151
-
152
- nrf_802154_notify_transmit_failed (m_frame .p_frame , error , & metadata );
153
- }
154
-
155
- /**
156
- * @brief Notify MAC layer that channel is busy if tx request failed and there are no retries left.
157
- *
158
- * @param[in] result Result of TX request.
159
- */
160
- static void notify_busy_channel (bool result )
161
- {
162
- nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_HIGH );
163
-
164
- nrf_802154_rsch_delayed_timeslot_cancel (NRF_802154_RESERVED_CSMACA_ID , true);
165
-
166
- // The 802.15.4 specification requires CSMA-CA to continue until m_nb is strictly greater
167
- // than nrf_802154_pib_csmaca_max_backoffs_get(), but at the moment this function is executed
168
- // the value of m_nb has not yet been incremented to reflect the latest attempt. Therefore
169
- // the comparison uses `greater or equal` instead of `greater than`.
170
- if (!result && (m_nb >= nrf_802154_pib_csmaca_max_backoffs_get ()))
171
- {
172
- notify_failed (NRF_802154_TX_ERROR_BUSY_CHANNEL );
173
- }
174
-
175
- nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_HIGH );
176
- }
177
-
178
152
/**
179
153
* @brief Perform CCA procedure followed by frame transmission.
180
154
*
@@ -190,7 +164,9 @@ static void frame_transmit(rsch_dly_ts_id_t dly_ts_id)
190
164
191
165
nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
192
166
193
- if (csma_ca_state_set (CSMA_CA_STATE_BACKOFF , CSMA_CA_STATE_ONGOING ))
167
+ nrf_802154_tx_error_t result = NRF_802154_TX_ERROR_NONE ;
168
+
169
+ if (csma_ca_state_set (CSMA_CA_STATE_BACKOFF , CSMA_CA_STATE_ATTEMPTING_CCATX ))
194
170
{
195
171
priority_leverage ();
196
172
@@ -208,19 +184,28 @@ static void frame_transmit(rsch_dly_ts_id_t dly_ts_id)
208
184
#else
209
185
.tx_timestamp_encode = false,
210
186
#endif
187
+ .p_client = & m_csma_ca_tx_client ,
188
+ .rsch_timeslot_id = dly_ts_id ,
211
189
};
212
190
213
- if (!nrf_802154_request_transmit (NRF_802154_TERM_NONE ,
214
- REQ_ORIG_CSMA_CA ,
215
- & params ,
216
- notify_busy_channel ))
217
- {
218
- (void )channel_busy ();
219
- }
191
+ result = nrf_802154_request_transmit (NRF_802154_TERM_NONE ,
192
+ REQ_ORIG_CSMA_CA ,
193
+ & params );
220
194
}
221
195
else
222
196
{
223
- nrf_802154_rsch_delayed_timeslot_cancel (dly_ts_id , true);
197
+ bool cancel_status = nrf_802154_rsch_delayed_timeslot_cancel (dly_ts_id , true);
198
+
199
+ NRF_802154_ASSERT (cancel_status );
200
+ (void )cancel_status ;
201
+ }
202
+
203
+ if (result != NRF_802154_TX_ERROR_NONE )
204
+ {
205
+ nrf_802154_transmit_done_metadata_t metadata = {};
206
+
207
+ metadata .frame_props = m_data_props ;
208
+ csma_ca_failed (m_frame .p_frame , result , & metadata , & m_csma_ca_tx_client );
224
209
}
225
210
226
211
nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_LOW );
@@ -322,13 +307,23 @@ static void random_backoff_start(void)
322
307
nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_HIGH );
323
308
}
324
309
310
+ /**
311
+ * @brief Perform appropriate actions for busy channel conditions.
312
+ *
313
+ * According to CSMA-CA description in 802.15.4 specification, when channel is busy NB and BE shall
314
+ * be incremented and the device shall wait random delay before next CCA procedure. If NB reaches
315
+ * macMaxCsmaBackoffs procedure fails.
316
+ *
317
+ * @retval true Procedure failed and TX failure should be notified to the next higher layer.
318
+ * @retval false Procedure is still ongoing and TX failure should be handled internally.
319
+ */
325
320
static bool channel_busy (void )
326
321
{
327
322
bool result = true;
328
323
329
324
nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
330
325
331
- if (csma_ca_state_set (CSMA_CA_STATE_ONGOING , CSMA_CA_STATE_BACKOFF ))
326
+ if (csma_ca_state_set (CSMA_CA_STATE_ATTEMPTING_CCATX , CSMA_CA_STATE_BACKOFF ))
332
327
{
333
328
m_nb ++ ;
334
329
@@ -339,7 +334,6 @@ static bool channel_busy(void)
339
334
340
335
if (m_nb > nrf_802154_pib_csmaca_max_backoffs_get ())
341
336
{
342
- nrf_802154_frame_parser_data_clear (& m_frame );
343
337
bool ret = csma_ca_state_set (CSMA_CA_STATE_BACKOFF , CSMA_CA_STATE_IDLE );
344
338
345
339
NRF_802154_ASSERT (ret );
@@ -395,14 +389,17 @@ bool nrf_802154_csma_ca_start(const nrf_802154_frame_t * p_f
395
389
return true;
396
390
}
397
391
398
- bool nrf_802154_csma_ca_abort (nrf_802154_term_t term_lvl , req_originator_t req_orig )
392
+ static bool csma_ca_can_abort (nrf_802154_term_t term_lvl ,
393
+ req_originator_t req_orig ,
394
+ const nrf_802154_tx_client_t * p_client )
399
395
{
400
396
nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
401
397
398
+ (void )p_client ;
399
+
402
400
bool result = true;
403
401
404
- if (((req_orig != REQ_ORIG_CORE ) && (req_orig != REQ_ORIG_HIGHER_LAYER )) ||
405
- (CSMA_CA_STATE_IDLE == nrf_802154_sl_atomic_load_u8 ((uint8_t * )& m_state )))
402
+ if ((req_orig != REQ_ORIG_CORE ) && (req_orig != REQ_ORIG_HIGHER_LAYER ))
406
403
{
407
404
// The request does not originate from core or the higher layer or the procedure
408
405
// is stopped already. Ignore the abort request and return success, no matter
@@ -411,10 +408,7 @@ bool nrf_802154_csma_ca_abort(nrf_802154_term_t term_lvl, req_originator_t req_o
411
408
else if (term_lvl >= NRF_802154_TERM_802154 )
412
409
{
413
410
// The procedure is active and the termination level allows the abort
414
- // request to be executed. Force aborted state. Don't clear the frame
415
- // pointer - it might be needed to notify failure.
416
- nrf_802154_sl_atomic_store_u8 ((uint8_t * )& m_state , CSMA_CA_STATE_ABORTED );
417
- nrf_802154_rsch_delayed_timeslot_cancel (NRF_802154_RESERVED_CSMACA_ID , false);
411
+ // request to be executed.
418
412
}
419
413
else
420
414
{
@@ -428,70 +422,69 @@ bool nrf_802154_csma_ca_abort(nrf_802154_term_t term_lvl, req_originator_t req_o
428
422
return result ;
429
423
}
430
424
431
- bool nrf_802154_csma_ca_tx_failed_hook (uint8_t * p_frame , nrf_802154_tx_error_t error )
425
+ static void csma_ca_failed (uint8_t * p_frame ,
426
+ nrf_802154_tx_error_t error ,
427
+ const nrf_802154_transmit_done_metadata_t * p_metadata ,
428
+ const nrf_802154_tx_client_t * p_client )
432
429
{
433
- bool result = true;
434
-
435
430
nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
436
431
432
+ (void )p_client ;
433
+
437
434
switch (error )
438
435
{
439
- // Below errors mean a failure occurred during the frame processing and the frame cannot be
440
- // transmitted unless a higher layer takes appropriate actions, hence the CSMA-CA procedure
441
- // shall be stopped.
442
- case NRF_802154_TX_ERROR_TIMESTAMP_ENCODING_ERROR :
443
- case NRF_802154_TX_ERROR_KEY_ID_INVALID :
444
- /* Fallthrough. */
445
- case NRF_802154_TX_ERROR_FRAME_COUNTER_ERROR :
446
- if (m_frame .p_frame == p_frame )
436
+ case NRF_802154_TX_ERROR_TIMESLOT_DENIED :
437
+ case NRF_802154_TX_ERROR_BUSY_CHANNEL :
438
+ case NRF_802154_TX_ERROR_TIMESLOT_ENDED :
439
+ if (channel_busy ())
447
440
{
448
- nrf_802154_frame_parser_data_clear (& m_frame );
449
441
nrf_802154_sl_atomic_store_u8 ((uint8_t * )& m_state , CSMA_CA_STATE_IDLE );
442
+ nrf_802154_frame_parser_data_clear (& m_frame );
443
+ nrf_802154_notify_transmit_failed (p_frame ,
444
+ NRF_802154_TX_ERROR_BUSY_CHANNEL ,
445
+ p_metadata );
450
446
}
451
447
break ;
452
448
453
449
default :
454
- if (csma_ca_state_set (CSMA_CA_STATE_ABORTED , CSMA_CA_STATE_IDLE ))
455
- {
456
- // The procedure was successfully aborted.
457
-
458
- if (p_frame != m_frame .p_frame )
459
- {
460
- // The procedure was aborted while another operation was holding
461
- // frame pointer in the core - hence p_frame points to a different
462
- // frame than mp_data. CSMA-CA failure must be notified directly.
463
- notify_failed (error );
464
- }
465
- }
466
- else if (p_frame == m_frame .p_frame )
467
- {
468
- // The procedure is active and transmission attempt failed. Try again
469
- result = channel_busy ();
470
- }
471
- else
472
- {
473
- // Intentionally empty.
474
- }
450
+ nrf_802154_sl_atomic_store_u8 ((uint8_t * )& m_state , CSMA_CA_STATE_IDLE );
451
+ nrf_802154_frame_parser_data_clear (& m_frame );
452
+ nrf_802154_notify_transmit_failed (p_frame , error , p_metadata );
475
453
break ;
476
454
}
477
455
478
456
nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_LOW );
457
+ }
479
458
480
- return result ;
459
+ static void csma_ca_tx_started (const nrf_802154_tx_client_t * p_client )
460
+ {
461
+ nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
462
+
463
+ (void )p_client ;
464
+
465
+ bool result = csma_ca_state_set (CSMA_CA_STATE_ATTEMPTING_CCATX , CSMA_CA_STATE_TRANSMITTING );
466
+
467
+ NRF_802154_ASSERT (result );
468
+
469
+ nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_LOW );
481
470
}
482
471
483
- bool nrf_802154_csma_ca_tx_started_hook (uint8_t * p_frame )
472
+ static void csma_ca_tx_done (uint8_t * p_frame ,
473
+ const nrf_802154_transmit_done_metadata_t * p_metadata ,
474
+ const nrf_802154_tx_client_t * p_client )
484
475
{
485
476
nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
486
477
487
- if (m_frame .p_frame == p_frame )
488
- {
489
- nrf_802154_frame_parser_data_clear (& m_frame );
490
- nrf_802154_sl_atomic_store_u8 ((uint8_t * )& m_state , CSMA_CA_STATE_IDLE );
491
- }
478
+ (void )p_client ;
479
+
480
+ bool result = csma_ca_state_set (CSMA_CA_STATE_TRANSMITTING , CSMA_CA_STATE_IDLE );
481
+
482
+ NRF_802154_ASSERT (result );
483
+
484
+ nrf_802154_frame_parser_data_clear (& m_frame );
485
+ nrf_802154_notify_transmitted (p_frame , p_metadata );
492
486
493
487
nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_LOW );
494
- return true;
495
488
}
496
489
497
490
#endif // NRF_802154_CSMA_CA_ENABLED
0 commit comments