diff --git a/examples/platforms/nrf52840/radio.c b/examples/platforms/nrf52840/radio.c index 890311382..038ca1146 100644 --- a/examples/platforms/nrf52840/radio.c +++ b/examples/platforms/nrf52840/radio.c @@ -99,6 +99,7 @@ typedef enum kPendingEventTransmit, // Frame is queued for transmission. kPendingEventFrameTransmitted, // Transmitted frame and received ACK (if requested). kPendingEventChannelAccessFailure, // Failed to transmit frame (channel busy). + kPendingEventInvalidAck, // Failed to transmit frame (received invalid ACK). kPendingEventEnergyDetectionStart, // Requested to start Energy Detection procedure. kPendingEventEnergyDetected, // Energy Detection finished. } RadioPendingEvents; @@ -166,6 +167,7 @@ static inline void clearPendingEvents(void) bitsToRemain &= ~(1UL << kPendingEventFrameTransmitted); bitsToRemain &= ~(1UL << kPendingEventChannelAccessFailure); + bitsToRemain &= ~(1UL << kPendingEventInvalidAck); bitsToRemain &= ~(1UL << kPendingEventSleep); @@ -592,6 +594,23 @@ void nrf5RadioProcess(otInstance *aInstance) resetPendingEvent(kPendingEventChannelAccessFailure); } + if (isPendingEventSet(kPendingEventInvalidAck)) + { +#if OPENTHREAD_ENABLE_DIAG + + if (otPlatDiagModeGet()) + { + otPlatDiagRadioTransmitDone(aInstance, &sTransmitFrame, OT_ERROR_NO_ACK); + } + else +#endif + { + otPlatRadioTxDone(aInstance, &sTransmitFrame, NULL, OT_ERROR_NO_ACK); + } + + resetPendingEvent(kPendingEventInvalidAck); + } + if (isPendingEventSet(kPendingEventEnergyDetected)) { otPlatRadioEnergyScanDone(aInstance, sEnergyDetected); @@ -665,9 +684,20 @@ void nrf_drv_radio802154_transmitted_raw(uint8_t *aAckPsdu, int8_t aPower, int8_ setPendingEvent(kPendingEventFrameTransmitted); } -void nrf_drv_radio802154_busy_channel(void) +void nrf_drv_radio802154_transmit_failed(nrf_drv_radio802154_tx_error_t error) { - setPendingEvent(kPendingEventChannelAccessFailure); + switch (error) + { + case NRF_DRV_RADIO802154_TX_ERROR_BUSY_CHANNEL: + case NRF_DRV_RADIO802154_TX_ERROR_TIMESLOT_ENDED: + setPendingEvent(kPendingEventChannelAccessFailure); + break; + + case NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK: + case NRF_DRV_RADIO802154_TX_ERROR_NO_MEM: + setPendingEvent(kPendingEventInvalidAck); + break; + } } void nrf_drv_radio802154_energy_detected(uint8_t result) diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c index f6a2f81a6..b9fbc8b1c 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.c @@ -407,6 +407,11 @@ __WEAK void nrf_drv_radio802154_rx_started(void) // Intentionally empty } +__WEAK void nrf_drv_radio802154_tx_ack_started(void) +{ + // Intentionally empty +} + __WEAK void nrf_drv_radio802154_received(uint8_t * p_data, uint8_t length, int8_t power, int8_t lqi) { (void) length; @@ -424,11 +429,21 @@ __WEAK void nrf_drv_radio802154_received_raw(uint8_t * p_data, int8_t power, int lqi); } +__WEAK void nrf_drv_radio802154_receive_failed(nrf_drv_radio802154_rx_error_t error) +{ + (void) error; +} + __WEAK void nrf_drv_radio802154_tx_started(void) { // Intentionally empty } +__WEAK void nrf_drv_radio802154_rx_ack_started(void) +{ + // Intentionally empty +} + __WEAK void nrf_drv_radio802154_transmitted(uint8_t * p_ack, uint8_t length, int8_t power, int8_t lqi) { (void) length; @@ -449,9 +464,9 @@ __WEAK void nrf_drv_radio802154_transmitted_raw(uint8_t * p_ack, int8_t power, i lqi); } -__WEAK void nrf_drv_radio802154_busy_channel(void) +__WEAK void nrf_drv_radio802154_transmit_failed(nrf_drv_radio802154_tx_error_t error) { - // Intentionally empty + (void) error; } __WEAK void nrf_drv_radio802154_energy_detected(uint8_t result) diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h index f007c2a61..ded99f2cd 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154.h @@ -64,15 +64,38 @@ typedef enum NRF_DRV_RADIO802154_STATE_CONTINUOUS_CARRIER, } nrf_drv_radio802154_state_t; +/** + * Errors reported during frame transmission. + */ +typedef enum +{ + NRF_DRV_RADIO802154_TX_ERROR_BUSY_CHANNEL, /**< CCA reported busy channel prior to transmission. */ + NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK, /**< Received ACK frame is other than expected. */ + NRF_DRV_RADIO802154_TX_ERROR_NO_MEM, /**< No receive buffer are available to receive an ACK. */ + NRF_DRV_RADIO802154_TX_ERROR_TIMESLOT_ENDED, /**< Radio timeslot ended during transmission procedure. */ +} nrf_drv_radio802154_tx_error_t; + +/** + * @brief Possible errors during frame reception. + */ +typedef enum +{ + NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME, /**< Received a malformed frame */ + NRF_DRV_RADIO802154_RX_ERROR_INVALID_FCS, /**< Received a frame with invalid checksum. */ + NRF_DRV_RADIO802154_RX_ERROR_INVALID_DEST_ADDR, /**< Received a frame with mismatched destination address. */ + NRF_DRV_RADIO802154_RX_ERROR_RUNTIME, /**< A runtime error occured (e.g. CPU was hold for too long.) */ + NRF_DRV_RADIO802154_RX_ERROR_TIMESLOT_ENDED, /**< Radio timeslot ended during frame reception. */ +} nrf_drv_radio802154_rx_error_t; + /** * @brief Structure for configuring CCA. */ typedef struct { - nrf_radio_cca_mode_t mode; ///< CCA mode. - uint8_t ed_threshold; ///< CCA Energy Busy Threshold. Not used in NRF_RADIO_CCA_MODE_CARRIER. - uint8_t corr_threshold; ///< CCA Correlator Busy Threshold. Not used in NRF_RADIO_CCA_MODE_ED. - uint8_t corr_limit; ///< Limit of occurrences above CCA Correlator Busy Threshold. Not used in NRF_RADIO_CCA_MODE_ED. + nrf_radio_cca_mode_t mode; /**< CCA mode. */ + uint8_t ed_threshold; /**< CCA Energy Busy Threshold. Not used in NRF_RADIO_CCA_MODE_CARRIER. */ + uint8_t corr_threshold; /**< CCA Correlator Busy Threshold. Not used in NRF_RADIO_CCA_MODE_ED. */ + uint8_t corr_limit; /**< Limit of occurrences above CCA Correlator Busy Threshold. Not used in NRF_RADIO_CCA_MODE_ED. */ } nrf_drv_radio802154_cca_cfg_t; /** @@ -262,7 +285,7 @@ void nrf_drv_radio802154_receive(void); * @note This function should be called in Receive state. In other states transmission will not be * scheduled. * @note If the CPU was halted or interrupted during performing this function - * @sa nrf_drv_radio802154_transmitted() or @sa nrf_drv_radio802154_busy_channel() may be + * @sa nrf_drv_radio802154_transmitted() or @sa nrf_drv_radio802154_transmit_failed() may be * called before nrf_drv_radio802154_transmit_raw() returns result. * @note This function is implemented in zero-copy fashion. It passes given buffer pointer to * the RADIO peripheral. @@ -271,7 +294,7 @@ void nrf_drv_radio802154_receive(void); * Radio driver waits infinitely for ACK frame. Higher layer is responsible to call * @sa nrf_radio802154_receive() after ACK timeout. * Transmission result is reported to higher layer by @sa nrf_radio802154_transmitted() or - * @sa nrf_radio802154_busy_channel() calls. + * @sa nrf_radio802154_transmit_failed() calls. * * p_data * v @@ -298,7 +321,7 @@ bool nrf_drv_radio802154_transmit_raw(const uint8_t *p_data, bool cca); * @note This function should be called in Receive state. In other states transmission will not be * scheduled. * @note If the CPU was halted or interrupted during performing this function - * @sa nrf_drv_radio802154_transmitted() or @sa nrf_drv_radio802154_busy_channel() may be + * @sa nrf_drv_radio802154_transmitted() or @sa nrf_drv_radio802154_transmit_failed() may be * called before nrf_drv_radio802154_transmit() returns result. * @note This function makes copy of given buffer. There is an internal buffer maintained by this * function. It is used to make a frame copy. To prevent unnecessary memory consumption and @@ -309,7 +332,7 @@ bool nrf_drv_radio802154_transmit_raw(const uint8_t *p_data, bool cca); * Radio driver waits infinitely for ACK frame. Higher layer is responsible to call * @sa nrf_radio802154_receive() after ACK timeout. * Transmission result is reported to higher layer by @sa nrf_radio802154_transmitted() or - * @sa nrf_radio802154_busy_channel() calls. + * @sa nrf_radio802154_transmit_failed() calls. * * p_data * v @@ -390,6 +413,13 @@ bool nrf_drv_radio802154_continuous_carrier(void); */ extern void nrf_drv_radio802154_rx_started(void); +/** + * @brief Notify that transmitting ACK frame has started. + * + * @note This function should be very short to prevent dropping frames by the driver. + */ +extern void nrf_drv_radio802154_tx_ack_started(void); + /** * @brief Notify that frame was received. * @@ -442,6 +472,13 @@ extern void nrf_drv_radio802154_received_raw(uint8_t * p_data, int8_t power, int */ extern void nrf_drv_radio802154_received(uint8_t * p_data, uint8_t length, int8_t power, int8_t lqi); +/** + * @brief Notify that reception of a frame failed. + * + * @param[in] error An error code that indicates reason of the failure. + */ +extern void nrf_drv_radio802154_receive_failed(nrf_drv_radio802154_rx_error_t error); + /** * @brief Notify that transmitting frame has started. * @@ -451,6 +488,15 @@ extern void nrf_drv_radio802154_received(uint8_t * p_data, uint8_t length, int8_ */ extern void nrf_drv_radio802154_tx_started(void); +/** + * @brief Notify that receiving ACK frame has started. + * + * @note It is possible that the frame being received is not expected ACK and + * @sa nrf_drv_radio802154_transmitted won't be called. + * @note This function should be very short to prevent dropping frames by the driver. + */ +extern void nrf_drv_radio802154_rx_ack_started(void); + /** * @brief Notify that frame was transmitted. * @@ -501,9 +547,11 @@ extern void nrf_drv_radio802154_transmitted(uint8_t * p_ack, uint8_t length, int /** * @brief Notify that frame was not transmitted due to busy channel. * - * This function is called if CCA procedure (performed just before transmission) fails. + * This function is called if transmission procedure fails. + * + * @param[in] error Reason of the failure. */ -extern void nrf_drv_radio802154_busy_channel(void); +extern void nrf_drv_radio802154_transmit_failed(nrf_drv_radio802154_tx_error_t error); /** * @brief Notify that Energy Detection procedure finished. diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c index dd4fb9502..35da5d900 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_fsm.c @@ -633,7 +633,13 @@ void nrf_raal_timeslot_ended(void) case RADIO_STATE_CCA_BEFORE_TX: case RADIO_STATE_TX_FRAME: case RADIO_STATE_RX_ACK: - nrf_drv_radio802154_notify_busy_channel(); + nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_TIMESLOT_ENDED); + break; + + case RADIO_STATE_RX_HEADER: + case RADIO_STATE_RX_FRAME: + case RADIO_STATE_TX_ACK: + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_TIMESLOT_ENDED); break; default: @@ -689,6 +695,7 @@ static inline void irq_framestart_state_waiting_rx_frame(void) nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); nrf_radio_event_clear(NRF_RADIO_EVENT_END); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME); } else { @@ -718,6 +725,7 @@ static inline void irq_framestart_state_waiting_rx_frame(void) nrf_radio_event_clear(NRF_RADIO_EVENT_BCMATCH); nrf_radio_event_clear(NRF_RADIO_EVENT_END); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_RUNTIME); break; default: @@ -733,7 +741,7 @@ static inline void irq_framestart_state_rx_ack(void) if ((mp_current_rx_buffer->psdu[0] < ACK_LENGTH) || (mp_current_rx_buffer->psdu[0] > MAX_PACKET_SIZE)) { - nrf_drv_radio802154_notify_busy_channel(); + nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK); frame_rx_start_after_ack_rx(); nrf_radio_event_clear(NRF_RADIO_EVENT_END); // In case frame ended before task DISABLE @@ -741,6 +749,8 @@ static inline void irq_framestart_state_rx_ack(void) else { nrf_radio_task_trigger(NRF_RADIO_TASK_RSSISTART); + + nrf_drv_radio802154_rx_ack_started(); } } @@ -750,6 +760,12 @@ static inline void irq_framestart_state_tx_frame(void) nrf_drv_radio802154_tx_started(); } +/// This event is handled when the radio starts transmitting an ACK frame. +static inline void irq_framestart_state_tx_ack(void) +{ + nrf_drv_radio802154_tx_ack_started(); +} + /// This event is handled when MHR is received static inline void irq_bcmatch_mhr(void) { @@ -758,8 +774,10 @@ static inline void irq_bcmatch_mhr(void) mp_current_rx_buffer->psdu[0], ack_is_requested(mp_current_rx_buffer->psdu)))) { + uint8_t frame_type = mp_current_rx_buffer->psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK; + // Check Frame Control field. - switch (mp_current_rx_buffer->psdu[FRAME_TYPE_OFFSET] & FRAME_TYPE_MASK) + switch (frame_type) { case FRAME_TYPE_BEACON: // Beacon is broadcast frame. @@ -786,6 +804,7 @@ static inline void irq_bcmatch_mhr(void) auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); nrf_radio_event_clear(NRF_RADIO_EVENT_END); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME); } break; @@ -804,6 +823,11 @@ static inline void irq_bcmatch_mhr(void) auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); nrf_radio_event_clear(NRF_RADIO_EVENT_END); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); + // Do not count received ACK as an error. + if (frame_type != FRAME_TYPE_ACK) + { + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME); + } } } } @@ -813,6 +837,8 @@ static inline void irq_bcmatch_mhr(void) nrf_radio_reset(); state_set(RADIO_STATE_WAITING_TIMESLOT); + + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_TIMESLOT_ENDED); } } @@ -836,6 +862,7 @@ static inline void irq_bcmatch_address(void) auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); nrf_radio_event_clear(NRF_RADIO_EVENT_END); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_DEST_ADDR); } } } @@ -878,6 +905,7 @@ static inline void irq_bcmatch_state_rx_header(void) auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); nrf_radio_event_clear(NRF_RADIO_EVENT_END); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_RUNTIME); break; default: @@ -913,6 +941,7 @@ static inline void irq_end_state_rx_header(void) // Frame ended before header was received. auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FRAME); } /// This event is generated when radio peripheral ends receiving of a complete frame. @@ -947,6 +976,7 @@ static inline void irq_end_state_rx_frame(void) { auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_INVALID_FCS); } break; @@ -955,6 +985,7 @@ static inline void irq_end_state_rx_frame(void) // CPU was hold too long. auto_ack_abort(RADIO_STATE_WAITING_RX_FRAME); nrf_radio_event_clear(NRF_RADIO_EVENT_READY); + nrf_drv_radio802154_notify_receive_failed(NRF_DRV_RADIO802154_RX_ERROR_RUNTIME); break; default: @@ -1026,7 +1057,7 @@ static inline void irq_end_state_rx_ack(void) } else { - nrf_drv_radio802154_notify_busy_channel(); + nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_INVALID_ACK); } frame_rx_start_after_ack_rx(); @@ -1255,7 +1286,7 @@ static inline void irq_ready_state_rx_ack(void) if (mp_current_rx_buffer == NULL || (!mp_current_rx_buffer->free)) { - nrf_drv_radio802154_notify_busy_channel(); + nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_NO_MEM); frame_rx_start_after_ack_rx(); } else @@ -1317,7 +1348,7 @@ static inline void irq_ccabusy_state_tx_frame(void) shorts_disable(); - nrf_drv_radio802154_notify_busy_channel(); + nrf_drv_radio802154_notify_transmit_failed(NRF_DRV_RADIO802154_TX_ERROR_BUSY_CHANNEL); state_set(RADIO_STATE_WAITING_RX_FRAME); nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); @@ -1387,11 +1418,14 @@ static inline void irq_handler(void) break; case RADIO_STATE_TX_FRAME: + case RADIO_STATE_CCA_BEFORE_TX: // This could happen at the beginning of transmission procedure. irq_framestart_state_tx_frame(); break; case RADIO_STATE_TX_ACK: - case RADIO_STATE_CCA_BEFORE_TX: // This could happen at the beginning of transmission procedure. + irq_framestart_state_tx_ack(); + break; + case RADIO_STATE_WAITING_TIMESLOT: break; diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification.h b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification.h index 137902743..f8cdb711e 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification.h @@ -34,6 +34,8 @@ #include #include +#include "nrf_drv_radio802154.h" + #ifdef __cplusplus extern "C" { #endif @@ -59,6 +61,13 @@ void nrf_drv_radio802154_notification_init(void); */ void nrf_drv_radio802154_notify_received(uint8_t * p_data, int8_t power, int8_t lqi); +/** + * @brief Notify next higher layer that reception of a frame failed. + * + * @param[in] error An error code that indicates reason of the failure. + */ +void nrf_drv_radio802154_notify_receive_failed(nrf_drv_radio802154_rx_error_t error); + /** * @brief Notify next higher layer that a frame was transmitted. * @@ -70,8 +79,10 @@ void nrf_drv_radio802154_notify_transmitted(uint8_t * p_ack, int8_t power, int8_ /** * @brief Notify next higher layer that a frame was not transmitted. + * + * @param[in] error An error code indicating reason of the failure. */ -void nrf_drv_radio802154_notify_busy_channel(void); +void nrf_drv_radio802154_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error); /** * @brief Notify next higher layer that energy detection procedure ended. diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c index e4eee1f42..94b8be246 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_direct.c @@ -51,14 +51,19 @@ void nrf_drv_radio802154_notify_received(uint8_t * p_data, int8_t power, int8_t nrf_drv_radio802154_received_raw(p_data, power, lqi); } +void nrf_drv_radio802154_notify_receive_failed(nrf_drv_radio802154_rx_error_t error) +{ + nrf_drv_radio802154_receive_failed(error); +} + void nrf_drv_radio802154_notify_transmitted(uint8_t * p_ack, int8_t power, int8_t lqi) { nrf_drv_radio802154_transmitted_raw(p_ack, power, lqi); } -void nrf_drv_radio802154_notify_busy_channel(void) +void nrf_drv_radio802154_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error) { - nrf_drv_radio802154_busy_channel(); + nrf_drv_radio802154_transmit_failed(error); } void nrf_drv_radio802154_notify_energy_detected(uint8_t result) diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_swi.c index d01dd7ab2..ef99ad7ec 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_swi.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_notification_swi.c @@ -39,6 +39,7 @@ #include #include +#include "nrf_drv_radio802154.h" #include "nrf_drv_radio802154_swi.h" #include "raal/nrf_raal_api.h" @@ -52,14 +53,19 @@ void nrf_drv_radio802154_notify_received(uint8_t * p_data, int8_t power, int8_t nrf_drv_radio802154_swi_notify_received(p_data, power, lqi); } +void nrf_drv_radio802154_notify_receive_failed(nrf_drv_radio802154_rx_error_t error) +{ + nrf_drv_radio802154_swi_notify_receive_failed(error); +} + void nrf_drv_radio802154_notify_transmitted(uint8_t * p_ack, int8_t power, int8_t lqi) { nrf_drv_radio802154_swi_notify_transmitted(p_ack, power, lqi); } -void nrf_drv_radio802154_notify_busy_channel(void) +void nrf_drv_radio802154_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error) { - nrf_drv_radio802154_swi_notify_busy_channel(); + nrf_drv_radio802154_swi_notify_transmit_failed(error); } void nrf_drv_radio802154_notify_energy_detected(uint8_t result) diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c index 75484e4d0..5627b75a7 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.c @@ -82,8 +82,9 @@ typedef enum { NTF_TYPE_RECEIVED, ///< Frame received + NTF_TYPE_RECEIVE_FAILED, ///< Frame reception failed NTF_TYPE_TRANSMITTED, ///< Frame transmitted - NTF_TYPE_CHANNEL_BUSY, ///< Frame transmission failure + NTF_TYPE_TRANSMIT_FAILED, ///< Frame transmission failure NTF_TYPE_ENERGY_DETECTED, ///< Energy detection procedure ended NTF_TYPE_CCA, ///< CCA procedure ended } nrf_drv_radio802154_ntf_type_t; @@ -96,28 +97,38 @@ typedef struct { struct { - uint8_t * p_psdu; ///< Pointer to received frame PSDU. - int8_t power; ///< RSSI of received frame. - int8_t lqi; ///< LQI of received frame. - } received; ///< Received frame details. + uint8_t * p_psdu; ///< Pointer to received frame PSDU. + int8_t power; ///< RSSI of received frame. + int8_t lqi; ///< LQI of received frame. + } received; ///< Received frame details. struct { - uint8_t * p_psdu; ///< Pointer to received ACK PSDU or NULL. - int8_t power; ///< RSSI of received ACK or 0. - int8_t lqi; ///< LQI of received ACK or 0. - } transmitted; ///< Transmitted frame details. + uint8_t * p_psdu; ///< Pointer to received ACK PSDU or NULL. + int8_t power; ///< RSSI of received ACK or 0. + int8_t lqi; ///< LQI of received ACK or 0. + } transmitted; ///< Transmitted frame details. struct { - int8_t result; ///< Energy detection result. - } energy_detected; ///< Energy detection details. + nrf_drv_radio802154_tx_error_t error; ///< An error code that indicates reason of the failure. + } transmit_failed; struct { - bool result; ///< CCA result. - } cca; ///< CCA details. - } data; ///< Notification data depending on it's type. + nrf_drv_radio802154_rx_error_t error; ///< An error code that indicates reason of the failure. + } receive_failed; + + struct + { + int8_t result; ///< Energy detection result. + } energy_detected; ///< Energy detection details. + + struct + { + bool result; ///< CCA result. + } cca; ///< CCA details. + } data; ///< Notification data depending on it's type. } nrf_drv_radio802154_ntf_data_t; /// Type of requests in request queue. @@ -372,6 +383,20 @@ void nrf_drv_radio802154_swi_notify_received(uint8_t * p_data, int8_t power, int nrf_egu_task_trigger(SWI_EGU, NTF_TASK); } +void nrf_drv_radio802154_swi_notify_receive_failed(nrf_drv_radio802154_rx_error_t error) +{ + assert(!ntf_queue_is_full()); + + nrf_drv_radio802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; + + p_slot->type = NTF_TYPE_RECEIVE_FAILED; + p_slot->data.receive_failed.error = error; + + ntf_queue_ptr_increment(&m_ntf_w_ptr); + + nrf_egu_task_trigger(SWI_EGU, NTF_TASK); +} + void nrf_drv_radio802154_swi_notify_transmitted(uint8_t * p_data, int8_t power, int8_t lqi) { assert(!ntf_queue_is_full()); @@ -388,13 +413,14 @@ void nrf_drv_radio802154_swi_notify_transmitted(uint8_t * p_data, int8_t power, nrf_egu_task_trigger(SWI_EGU, NTF_TASK); } -void nrf_drv_radio802154_swi_notify_busy_channel(void) +void nrf_drv_radio802154_swi_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error) { assert(!ntf_queue_is_full()); nrf_drv_radio802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; - p_slot->type = NTF_TYPE_CHANNEL_BUSY; + p_slot->type = NTF_TYPE_TRANSMIT_FAILED; + p_slot->data.transmit_failed.error = error; ntf_queue_ptr_increment(&m_ntf_w_ptr); @@ -545,14 +571,18 @@ void SWI_IRQHandler(void) p_slot->data.received.lqi); break; + case NTF_TYPE_RECEIVE_FAILED: + nrf_drv_radio802154_receive_failed(p_slot->data.receive_failed.error); + break; + case NTF_TYPE_TRANSMITTED: nrf_drv_radio802154_transmitted_raw(p_slot->data.transmitted.p_psdu, p_slot->data.transmitted.power, p_slot->data.transmitted.lqi); break; - case NTF_TYPE_CHANNEL_BUSY: - nrf_drv_radio802154_busy_channel(); + case NTF_TYPE_TRANSMIT_FAILED: + nrf_drv_radio802154_transmit_failed(p_slot->data.transmit_failed.error); break; case NTF_TYPE_ENERGY_DETECTED: diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.h b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.h index e6124deee..2b08180ca 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_drv_radio802154_swi.h @@ -34,6 +34,8 @@ #include #include +#include "nrf_drv_radio802154.h" + #ifdef __cplusplus extern "C" { #endif @@ -59,6 +61,13 @@ void nrf_drv_radio802154_swi_init(void); */ void nrf_drv_radio802154_swi_notify_received(uint8_t * p_data, int8_t power, int8_t lqi); +/** + * @brief Notify next higher layer that reception of a frame failed. + * + * @param[in] error An error code that indicates reason of the failure. + */ +void nrf_drv_radio802154_swi_notify_receive_failed(nrf_drv_radio802154_rx_error_t error); + /** * @brief Notify next higher layer that a frame was transmitted from SWI priority level. * @@ -70,8 +79,10 @@ void nrf_drv_radio802154_swi_notify_transmitted(uint8_t * p_data, int8_t power, /** * @brief Notify next higher layer that a frame was not transmitted from SWI priority level. + * + * @param[in] error Reason of the transmission failure. */ -void nrf_drv_radio802154_swi_notify_busy_channel(void); +void nrf_drv_radio802154_swi_notify_transmit_failed(nrf_drv_radio802154_tx_error_t error); /** * @brief Notify next higher layer that energy detection procedure ended from SWI priority level.