@@ -69,8 +69,8 @@ typedef enum
6969{
7070 CSMA_CA_STATE_IDLE , ///< The CSMA-CA procedure is inactive.
7171 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 .
7474} csma_ca_state_t ;
7575
7676static 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
8585#endif
8686static csma_ca_state_t m_state ; ///< The current state of the CSMA-CA procedure.
8787
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+ };
99111
100112static bool csma_ca_state_set (csma_ca_state_t expected , csma_ca_state_t desired )
101113{
@@ -137,44 +149,6 @@ static void priority_leverage(void)
137149 nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_HIGH );
138150}
139151
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-
178152/**
179153 * @brief Perform CCA procedure followed by frame transmission.
180154 *
@@ -190,7 +164,9 @@ static void frame_transmit(rsch_dly_ts_id_t dly_ts_id)
190164
191165 nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
192166
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 ))
194170 {
195171 priority_leverage ();
196172
@@ -208,19 +184,28 @@ static void frame_transmit(rsch_dly_ts_id_t dly_ts_id)
208184#else
209185 .tx_timestamp_encode = false,
210186#endif
187+ .p_client = & m_csma_ca_tx_client ,
188+ .rsch_timeslot_id = dly_ts_id ,
211189 };
212190
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 );
220194 }
221195 else
222196 {
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 );
224209 }
225210
226211 nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_LOW );
@@ -322,13 +307,23 @@ static void random_backoff_start(void)
322307 nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_HIGH );
323308}
324309
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+ */
325320static bool channel_busy (void )
326321{
327322 bool result = true;
328323
329324 nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
330325
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 ))
332327 {
333328 m_nb ++ ;
334329
@@ -339,7 +334,6 @@ static bool channel_busy(void)
339334
340335 if (m_nb > nrf_802154_pib_csmaca_max_backoffs_get ())
341336 {
342- nrf_802154_frame_parser_data_clear (& m_frame );
343337 bool ret = csma_ca_state_set (CSMA_CA_STATE_BACKOFF , CSMA_CA_STATE_IDLE );
344338
345339 NRF_802154_ASSERT (ret );
@@ -395,14 +389,17 @@ bool nrf_802154_csma_ca_start(const nrf_802154_frame_t * p_f
395389 return true;
396390}
397391
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 )
399395{
400396 nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
401397
398+ (void )p_client ;
399+
402400 bool result = true;
403401
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 ))
406403 {
407404 // The request does not originate from core or the higher layer or the procedure
408405 // 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
411408 else if (term_lvl >= NRF_802154_TERM_802154 )
412409 {
413410 // 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.
418412 }
419413 else
420414 {
@@ -428,70 +422,69 @@ bool nrf_802154_csma_ca_abort(nrf_802154_term_t term_lvl, req_originator_t req_o
428422 return result ;
429423}
430424
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 )
432429{
433- bool result = true;
434-
435430 nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
436431
432+ (void )p_client ;
433+
437434 switch (error )
438435 {
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 ())
447440 {
448- nrf_802154_frame_parser_data_clear (& m_frame );
449441 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 );
450446 }
451447 break ;
452448
453449 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 );
475453 break ;
476454 }
477455
478456 nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_LOW );
457+ }
479458
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 );
481470}
482471
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 )
484475{
485476 nrf_802154_log_function_enter (NRF_802154_LOG_VERBOSITY_LOW );
486477
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 );
492486
493487 nrf_802154_log_function_exit (NRF_802154_LOG_VERBOSITY_LOW );
494- return true;
495488}
496489
497490#endif // NRF_802154_CSMA_CA_ENABLED
0 commit comments