diff --git a/examples/platforms/nrf52840/radio.c b/examples/platforms/nrf52840/radio.c index 98d894801..515fb88c6 100644 --- a/examples/platforms/nrf52840/radio.c +++ b/examples/platforms/nrf52840/radio.c @@ -742,6 +742,9 @@ void nrf_802154_transmit_failed(const uint8_t *aFrame, nrf_802154_tx_error_t err case NRF_802154_TX_ERROR_NO_MEM: setPendingEvent(kPendingEventInvalidOrNoAck); break; + + default: + assert(false); } } diff --git a/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c index c92922a93..7aaf40556 100644 --- a/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c +++ b/third_party/NordicSemiconductor/drivers/radio/mac_features/nrf_802154_filter.c @@ -370,7 +370,7 @@ static bool dst_extended_addr_check(const uint8_t *p_psdu) nrf_802154_rx_error_t nrf_802154_filter_frame_part(const uint8_t * p_psdu, uint8_t * p_num_bytes) { - nrf_802154_rx_error_t result; + nrf_802154_rx_error_t result = NRF_802154_RX_ERROR_INVALID_FRAME; switch (*p_num_bytes) { diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.c index e0e8305c4..8c6dc38b5 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.c @@ -150,6 +150,11 @@ int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level) return ED_MIN_DBM + (energy_level / ED_RESULT_FACTOR); } +uint8_t nrf_802154_ccaedthres_from_dbm_calculate(int8_t dbm) +{ + return dbm - ED_MIN_DBM; +} + uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t psdu_length) { uint32_t frame_symbols = PHY_SHR_DURATION; @@ -334,15 +339,33 @@ void nrf_802154_buffer_free_raw(uint8_t * p_data) rx_buffer_t * p_buffer = (rx_buffer_t *)p_data; assert(p_buffer->free == false); + (void)p_buffer; nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_BUFFER_FREE); result = nrf_802154_request_buffer_free(p_data); assert(result); + (void)result; nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_BUFFER_FREE); } +bool nrf_802154_buffer_free_immediately_raw(uint8_t * p_data) +{ + bool result; + rx_buffer_t * p_buffer = (rx_buffer_t *)p_data; + + assert(p_buffer->free == false); + (void)p_buffer; + + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_BUFFER_FREE); + + result = nrf_802154_request_buffer_free(p_data); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_BUFFER_FREE); + return result; +} + #else // NRF_802154_USE_RAW_API void nrf_802154_buffer_free(uint8_t * p_data) @@ -351,15 +374,33 @@ void nrf_802154_buffer_free(uint8_t * p_data) rx_buffer_t * p_buffer = (rx_buffer_t *)(p_data - RAW_PAYLOAD_OFFSET); assert(p_buffer->free == false); + (void)p_buffer; nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_BUFFER_FREE); result = nrf_802154_request_buffer_free(p_data - RAW_PAYLOAD_OFFSET); assert(result); + (void)result; nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_BUFFER_FREE); } +bool nrf_802154_buffer_free_immediately(uint8_t * p_data) +{ + bool result; + rx_buffer_t * p_buffer = (rx_buffer_t *)(p_data - RAW_PAYLOAD_OFFSET); + + assert(p_buffer->free == false); + (void)p_buffer; + + nrf_802154_log(EVENT_TRACE_ENTER, FUNCTION_BUFFER_FREE); + + result = nrf_802154_request_buffer_free(p_data - RAW_PAYLOAD_OFFSET); + + nrf_802154_log(EVENT_TRACE_EXIT, FUNCTION_BUFFER_FREE); + return result; +} + #endif // NRF_802154_USE_RAW_API int8_t nrf_802154_rssi_last_get(void) diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h index b9185cc32..4cab60c27 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154.h @@ -74,8 +74,8 @@ void nrf_802154_deinit(void); * @note If NRF_802154_INTERNAL_RADIO_IRQ_HANDLING is enabled, the driver internally handles the * RADIO IRQ, and this function shall not be called. * - * This function should be used in an operating system environment where the OS handles IRQ - * and indirectly passes it to the driver, or with a RAAL implementation that indirectly passes radio + * This function should be used in an operating system environment where the OS handles IRQ and + * indirectly passes it to the driver, or with a RAAL implementation that indirectly passes radio * IRQ to the driver (i.e. SoftDevice). */ void nrf_802154_radio_irq_handler(void); @@ -211,6 +211,16 @@ void nrf_802154_short_address_set(const uint8_t *p_short_address); */ int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level); +/** + * @brief Calculate the CCA energy detection threshold value from a given dBm level. + * + * @param[in] dbm Energy level in dBm used to calculate the CCAEDTHRES value. + * + * @return Energy level value corresponding to the given dBm level that should be written to + * the CCACTRL register. + */ +uint8_t nrf_802154_ccaedthres_from_dbm_calculate(int8_t dbm); + /** * @brief Calculate the timestamp of the first symbol of the preamble in a received frame. * @@ -236,11 +246,12 @@ nrf_802154_state_t nrf_802154_state_get(void); /** * @brief Change radio state to sleep. * - * Sleep state is the lowest power state. In this state, the radio cannot transmit or receive frames. - * It is the only state in which the driver releases the high-frequency clock and does not request - * timeslots from a radio arbiter. + * Sleep state is the lowest power state. In this state, the radio cannot transmit or receive + * frames. It is the only state in which the driver releases the high-frequency clock and does not + * request timeslots from a radio arbiter. * - * @note If another module requests it, the high-frequency clock may be enabled even in radio sleep state. + * @note If another module requests it, the high-frequency clock may be enabled even in radio sleep + * state. * * @retval true If the radio changes its state to low power mode. * @retval false If the driver could not schedule changing state. @@ -250,8 +261,9 @@ bool nrf_802154_sleep(void); /** * @brief Change radio state to receive. * - * In receive state, the radio receives frames and may automatically send ACK frames when appropriate. - * The received frame is reported to higher layer by a call to @ref nrf_802154_received. + * In receive state, the radio receives frames and may automatically send ACK frames when + * appropriate. The received frame is reported to higher layer by a call to + * @ref nrf_802154_received. * * @retval true If the radio enters receive state. * @retval false If the driver could not enter receive state. @@ -263,18 +275,18 @@ bool nrf_802154_receive(void); * @brief Change radio state to transmit. * * @note If the CPU is halted or interrupted while this function is executed, - * @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed may be - * called before this function returns a result. + * @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed may be called before this + * function returns a result. * @note This function is implemented in zero-copy fashion. It passes the given buffer pointer to * the RADIO peripheral. * * In transmit state, the radio transmits a given frame. If requested, it waits for an ACK frame. * Depending on @ref NRF_802154_ACK_TIMEOUT_ENABLED, the radio driver automatically - * stops waiting for an ACK frame or waits indefinitely for an ACK frame. If it is configured to wait, - * the MAC layer is responsible for calling @ref nrf_802154_receive or + * stops waiting for an ACK frame or waits indefinitely for an ACK frame. If it is configured to + * wait, the MAC layer is responsible for calling @ref nrf_802154_receive or * @ref nrf_802154_sleep after the ACK time-out. - * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted or - * @ref nrf_802154_transmit_failed. + * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted + * or @ref nrf_802154_transmit_failed. * * @verbatim * p_data @@ -286,11 +298,11 @@ bool nrf_802154_receive(void); * | <---------------------------- PHR -----------------------------------> | * @endverbatim * - * @param[in] p_data Pointer to array containing data to transmit. First byte should contain - * frame length (including PHR and FCS). Following bytes should contain data. - * CRC is computed automatically by radio hardware. Therefore, the FCS - * field can contain any bytes. - * @param[in] cca If the driver should perform a CCA procedure before transmission. + * @param[in] p_data Pointer to array containing data to transmit. First byte should contain frame + * length (including PHR and FCS). Following bytes should contain data. CRC is + * computed automatically by radio hardware. Therefore, the FCS field can + * contain any bytes. + * @param[in] cca If the driver should perform a CCA procedure before transmission. * * @retval true If the transmission procedure was scheduled. * @retval false If the driver could not schedule the transmission procedure. @@ -303,19 +315,19 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca); * @brief Change radio state to transmit. * * @note If the CPU is halted or interrupted while this function is executed, - * @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed must be - * called before this function returns a result. - * @note This function copies the given buffer. It maintains an internal buffer, which - * is used to make a frame copy. To prevent unnecessary memory consumption and - * to perform zero-copy transmission, use @ref nrf_802154_transmit_raw instead. + * @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed must be called before this + * function returns a result. + * @note This function copies the given buffer. It maintains an internal buffer, which is used to + * make a frame copy. To prevent unnecessary memory consumption and to perform zero-copy + * transmission, use @ref nrf_802154_transmit_raw instead. * * In transmit state, the radio transmits a given frame. If requested, it waits for an ACK frame. * Depending on @ref NRF_802154_ACK_TIMEOUT_ENABLED, the radio driver automatically - * stops waiting for an ACK frame or waits indefinitely for an ACK frame. If it is configured to wait, - * the MAC layer is responsible for calling @ref nrf_802154_receive or + * stops waiting for an ACK frame or waits indefinitely for an ACK frame. If it is configured to + * wait, the MAC layer is responsible for calling @ref nrf_802154_receive or * @ref nrf_802154_sleep after the ACK time-out. - * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted or - * @ref nrf_802154_transmit_failed. + * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted + * or @ref nrf_802154_transmit_failed. * * @verbatim * p_data @@ -327,11 +339,11 @@ bool nrf_802154_transmit_raw(const uint8_t * p_data, bool cca); * | <------------------ length -----------------------------> | * @endverbatim * - * @param[in] p_data Pointer to array containing payload of data to transmit. The array - * should exclude PHR or FCS fields of the 802.15.4 frame. - * @param[in] length Length of the given frame. This value shall exclude PHR and FCS fields from - * the given frame (exact size of buffer pointed to by @p p_data). - * @param[in] cca If the driver should perform a CCA procedure before transmission. + * @param[in] p_data Pointer to array containing payload of data to transmit. The array should + * exclude PHR or FCS fields of the 802.15.4 frame. + * @param[in] length Length of the given frame. This value shall exclude PHR and FCS fields from + * the given frame (exact size of buffer pointed to by @p p_data). + * @param[in] cca If the driver should perform a CCA procedure before transmission. * * @retval true If the transmission procedure was scheduled. * @retval false If the driver could not schedule the transmission procedure. @@ -343,15 +355,15 @@ bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, bool cca); /** * @brief Change radio state to energy detection. * - * In energy detection state, the radio detects the maximum energy for a given time. The result of the detection - * is reported to the higher layer by @ref nrf_802154_energy_detected. + * In energy detection state, the radio detects the maximum energy for a given time. The result of + * the detection is reported to the higher layer by @ref nrf_802154_energy_detected. * * @note @ref nrf_802154_energy_detected may be called before this function returns a result. - * @note Performing the energy detection procedure make take longer time than requested in @p time_us. - * The procedure is performed only during timeslots granted by a radio arbiter. It may be - * interrupted by other protocols using the radio hardware. If the procedure is interrupted, it is - * automatically continued and the sum of time periods during which the procedure is carried - * out is not less than the requested @p time_us. + * @note Performing the energy detection procedure make take longer time than requested in + * @p time_us. The procedure is performed only during timeslots granted by a radio arbiter. + * It may be interrupted by other protocols using the radio hardware. If the procedure is + * interrupted, it is automatically continued and the sum of time periods during which the + * procedure is carried out is not less than the requested @p time_us. * * @param[in] time_us Duration of energy detection procedure. The given value is rounded up to * multiplication of 8s (128 us). @@ -366,8 +378,8 @@ bool nrf_802154_energy_detection(uint32_t time_us); * * @note @ref nrf_802154_cca_done may be called before this function returns a result. * - * In CCA state, the radio verifies if the channel is clear. The result of the verification is reported to the higher - * layer by @ref nrf_802154_cca_done. + * In CCA state, the radio verifies if the channel is clear. The result of the verification is + * reported to the higher layer by @ref nrf_802154_cca_done. * * @retval true If the CCA procedure was scheduled. * @retval false If the driver could not schedule the CCA procedure. @@ -377,9 +389,9 @@ bool nrf_802154_cca(void); /** * @brief Change radio state to continuous carrier. * - * @note When the radio is emitting continuous carrier signals, it blocks all transmissions on the selected channel. - * This function should be called only during radio tests. It should not be used during - * normal device operation. + * @note When the radio is emitting continuous carrier signals, it blocks all transmissions on the + * selected channel. This function should be called only during radio tests. It should not be + * used during normal device operation. * @note This function works correctly only with a single-PHY arbiter. It should not be used with * any other arbiter. * @@ -407,8 +419,8 @@ extern void nrf_802154_tx_ack_started(void); /** * @brief Notify that a frame was received. * - * @note The buffer pointed to by @p p_data is not modified by the radio driver (and cannot - * be used to receive a frame) until @ref nrf_802154_buffer_free_raw is called. + * @note The buffer pointed to by @p p_data is not modified by the radio driver (and cannot be used + * to receive a frame) until @ref nrf_802154_buffer_free_raw is called. * @note The buffer pointed to by @p p_data may be modified by the function handler (and other * modules) until @ref nrf_802154_buffer_free_raw is called. * @@ -423,9 +435,9 @@ extern void nrf_802154_tx_ack_started(void); * @endverbatim * * @param[in] p_data Pointer to the buffer containing received data (PHR + PSDU). First byte in - * the buffer is length of the frame (PHR). The following bytes contain the frame - * itself (PSDU). The length byte (PHR) includes FCS. FCS is already verified by - * the hardware and may be modified by the hardware. + * the buffer is length of the frame (PHR). The following bytes contain the + * frame itself (PSDU). The length byte (PHR) includes FCS. FCS is already + * verified by the hardware and may be modified by the hardware. * @param[in] power RSSI of received frame. * @param[in] lqi LQI of received frame. */ @@ -451,7 +463,8 @@ extern void nrf_802154_received_raw(uint8_t * p_data, int8_t power, uint8_t lqi) * | <------------------ length -----------------------------> | * @endverbatim * - * @param[in] p_data Pointer to the buffer containing the payload of the received frame (PSDU without FCS). + * @param[in] p_data Pointer to the buffer containing the payload of the received frame (PSDU + * without FCS). * @param[in] length Length of received payload. * @param[in] power RSSI of received frame. * @param[in] lqi LQI of received frame. @@ -469,15 +482,15 @@ extern void nrf_802154_received(uint8_t * p_data, uint8_t length, int8_t power, * list. * * @note @p timestamp may be inaccurate due to software latency (IRQ handling). - * @note @p timestamp granularity depends on the granularity of the timer driver in the platform/timer - * directory. - * @note Including the timestamp for received frames uses resources like CPU time and memory. If the timestamp - * is not required, use @ref nrf_802154_received_raw instead. + * @note @p timestamp granularity depends on the granularity of the timer driver in the + * platform/timer directory. + * @note Including the timestamp for received frames uses resources like CPU time and memory. If the + * timestamp is not required, use @ref nrf_802154_received_raw instead. * * @param[in] p_data Pointer to the buffer containing received data (PHR + PSDU). First byte in - * the buffer is length of the frame (PHR). The following bytes contain the frame - * itself (PSDU). The length byte (PHR) includes FCS. FCS is already verified by - * the hardware and may be modified by the hardware. + * the buffer is length of the frame (PHR). The following bytes contain the + * frame itself (PSDU). The length byte (PHR) includes FCS. FCS is already + * verified by the hardware and may be modified by the hardware. * @param[in] power RSSI of received frame. * @param[in] lqi LQI of received frame. * @param[in] time Timestamp taken when the last symbol of the frame was received (in us). @@ -495,12 +508,13 @@ extern void nrf_802154_received_timestamp_raw(uint8_t * p_data, * This functions works like @ref nrf_802154_received and adds a timestamp to the parameter list. * * @note @p timestamp may be inaccurate due to software latency (IRQ handling). - * @note @p timestamp granularity depends on the granularity of the timer driver in the platform/timer - * directory. - * @note Including the timestamp for received frames uses resources like CPU time and memory. If the timestamp - * is not required, use @ref nrf_802154_received instead. + * @note @p timestamp granularity depends on the granularity of the timer driver in the + * platform/timer directory. + * @note Including the timestamp for received frames uses resources like CPU time and memory. If the + * timestamp is not required, use @ref nrf_802154_received instead. * - * @param[in] p_data Pointer to the buffer containing the payload of the received frame (PSDU without FCS). + * @param[in] p_data Pointer to the buffer containing the payload of the received frame (PSDU + * without FCS). * @param[in] length Length of received payload. * @param[in] power RSSI of received frame. * @param[in] lqi LQI of received frame. @@ -539,19 +553,19 @@ extern void nrf_802154_tx_started(const uint8_t * p_frame); /** * @brief Notify that a frame was transmitted. * - * @note If ACK was requested for the transmitted frame, this function is called after a proper ACK is - * received. If ACK was not requested, this function is called just after transmission has + * @note If ACK was requested for the transmitted frame, this function is called after a proper ACK + * is received. If ACK was not requested, this function is called just after transmission has * ended. - * @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot - * be used to receive a frame) until @ref nrf_802154_buffer_free_raw is called. + * @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot be used + * to receive a frame) until @ref nrf_802154_buffer_free_raw is called. * @note The buffer pointed to by @p p_ack may be modified by the function handler (and other * modules) until @ref nrf_802154_buffer_free_raw is called. * * @param[in] p_frame Pointer to the buffer containing PHR and PSDU of the transmitted frame. - * @param[in] p_ack Pointer to the received ACK buffer. First byte in the buffer is the length of the - * frame (PHR). The following bytes contain the ACK frame itself (PSDU). The length byte - * (PHR) includes FCS. FCS is already verified by the hardware and may be - * modified by the hardware. + * @param[in] p_ack Pointer to the received ACK buffer. First byte in the buffer is the length + * of the frame (PHR). The following bytes contain the ACK frame itself (PSDU). + * The length byte (PHR) includes FCS. FCS is already verified by the hardware + * and may be modified by the hardware. * If ACK was not requested, @p p_ack is set to NULL. * @param[in] power RSSI of received frame or 0 if ACK was not requested. * @param[in] lqi LQI of received frame or 0 if ACK was not requested. @@ -566,8 +580,8 @@ extern void nrf_802154_transmitted_raw(const uint8_t * p_frame, /** * @brief Notify that a frame was transmitted. * - * @note If ACK was requested for the transmitted frame, this function is called after a proper ACK is - * received. If ACK was not requested, this function is called just after transmission has + * @note If ACK was requested for the transmitted frame, this function is called after a proper ACK + * is received. If ACK was not requested, this function is called just after transmission has * ended. * @note The buffer pointed to by @p p_ack is not modified by the radio driver (and cannot * be used to receive a frame) until @ref nrf_802154_buffer_free is @@ -578,8 +592,9 @@ extern void nrf_802154_transmitted_raw(const uint8_t * p_frame, * @ref nrf_802154_transmitted_raw. It should not handle both functions. * * @param[in] p_frame Pointer to the buffer containing PSDU of the transmitted frame. - * @param[in] p_ack Pointer to the buffer containing the received ACK payload (PHR excluding FCS). - * If ACK was not requested, @p p_ack is set to NULL. + * @param[in] p_ack Pointer to the buffer containing the received ACK payload (PHR excluding + * FCS). + * If ACK was not requested, @p p_ack is set to NULL. * @param[in] length Length of the received ACK payload or 0 if ACK was not requested. * @param[in] power RSSI of received frame or 0 if ACK was not requested. * @param[in] lqi LQI of received frame or 0 if ACK was not requested. @@ -602,16 +617,16 @@ extern void nrf_802154_transmitted(const uint8_t * p_frame, * list. * * @note @p timestamp may be inaccurate due to software latency (IRQ handling). - * @note @p timestamp granularity depends on the granularity of the timer driver in the platform/timer - * directory. - * @note Including a timestamp for received frames uses resources like CPU time and memory. If the timestamp - * is not required, use @ref nrf_802154_received instead. + * @note @p timestamp granularity depends on the granularity of the timer driver in the + * platform/timer directory. + * @note Including a timestamp for received frames uses resources like CPU time and memory. If the + * timestamp is not required, use @ref nrf_802154_received instead. * * @param[in] p_frame Pointer to the buffer containing PSDU of the transmitted frame. - * @param[in] p_ack Pointer to the received ACK buffer. First byte in the buffer is the length of the - * frame (PHR). The following bytes contain the ACK frame itself (PSDU). The length byte - * (PHR) includes FCS. FCS is already verified by the hardware and may be - * modified by the hardware. + * @param[in] p_ack Pointer to the received ACK buffer. First byte in the buffer is the length + * of the frame (PHR). The following bytes contain the ACK frame itself (PSDU). + * The length byte (PHR) includes FCS. FCS is already verified by the hardware + * and may be modified by the hardware. * If ACK was not requested, @p p_ack is set to NULL. * @param[in] power RSSI of received frame or 0 if ACK was not requested. * @param[in] lqi LQI of received frame or 0 if ACK was not requested. @@ -635,8 +650,8 @@ extern void nrf_802154_transmitted_timestamp_raw(const uint8_t * p_frame, * @note @p timestamp may be inaccurate due to software latency (IRQ handling). * @note @p timestamp granularity depends on the granularity of the timer driver in the platform/timer * directory. - * @note Including a timestamp for received frames uses resources like CPU time and memory. If the timestamp - * is not required, use @ref nrf_802154_received instead. + * @note Including a timestamp for received frames uses resources like CPU time and memory. If the + * timestamp is not required, use @ref nrf_802154_received instead. * * @param[in] p_frame Pointer to the buffer containing PSDU of the transmitted frame. * @param[in] p_ack Pointer to the buffer containing the received ACK payload (PHR excluding FCS). @@ -713,24 +728,60 @@ extern void nrf_802154_cca_failed(nrf_802154_cca_error_t error); * @brief Notify the driver that the buffer containing the received frame is not used anymore. * * @note The buffer pointed to by @p p_data may be modified by this function. + * @note This function can be safely called only from the main context. To free the buffer from + * a callback or IRQ context, use @ref nrf_802154_buffer_free_immediately_raw. * - * @param[in] p_data A pointer to the buffer containing the received data that is no longer needed by - * the higher layer. + * @param[in] p_data A pointer to the buffer containing the received data that is no longer needed + * by the higher layer. */ void nrf_802154_buffer_free_raw(uint8_t * p_data); +/** + * @brief Notify the driver that the buffer containing the received frame is not used anymore. + * + * @note The buffer pointed to by @p p_data may be modified by this function. + * @note This function can be safely called from any context. If the driver is busy processing + * a request called from a context with lower priority, this function returns false and + * the caller should free the buffer later. + * + * @param[in] p_data A pointer to the buffer containing the received data that is no longer needed + * by the higher layer. + * + * @retval true Buffer was freed successfully. + * @retval false Buffer cannot be freed right now due to ongoing operation. + */ +bool nrf_802154_buffer_free_immediately_raw(uint8_t * p_data); + #else // NRF_802154_USE_RAW_API /** * @brief Notify the driver that the buffer containing the received frame is not used anymore. * * @note The buffer pointed to by @p p_data may be modified by this function. + * @note This function can be safely called only from the main context. To free the buffer from + * a callback or IRQ context, use @ref nrf_802154_buffer_free_immediately. * - * @param[in] p_data A pointer to the buffer containing the received data that is no longer needed by - * the higher layer. + * @param[in] p_data A pointer to the buffer containing the received data that is no longer needed + * by the higher layer. */ void nrf_802154_buffer_free(uint8_t * p_data); +/** + * @brief Notify the driver that the buffer containing the received frame is not used anymore. + * + * @note The buffer pointed to by @p p_data may be modified by this function. + * @note This function can be safely called from any context. If the driver is busy processing + * a request called from a context with lower priority, this function returns false and + * the caller should free the buffer later. + * + * @param[in] p_data A pointer to the buffer containing the received data that is no longer needed + * by the higher layer. + * + * @retval true Buffer was freed successfully. + * @retval false Buffer cannot be freed right now due to ongoing operation. + */ +bool nrf_802154_buffer_free_immediately(uint8_t * p_data); + #endif // NRF_802154_USE_RAW_API @@ -771,8 +822,9 @@ int8_t nrf_802154_rssi_last_get(void); * * In promiscuous mode, the driver notifies the higher layer that it received any frame (regardless * frame type or destination address). - * In normal mode (not promiscuous), the higher layer is not notified about ACK frames and frames with - * unknown type. Also frames with a destination address not matching the device address are ignored. + * In normal mode (not promiscuous), the higher layer is not notified about ACK frames and frames + * with unknown type. Also frames with a destination address not matching the device address are + * ignored. * * @param[in] enabled If promiscuous mode should be enabled. */ @@ -799,13 +851,13 @@ bool nrf_802154_promiscuous_get(void); * @note Auto ACK is enabled by default. * * If auto ACK is enabled, the driver prepares and sends ACK frames automatically - * aTurnaroundTime (192 us) after the proper frame is received. The driver sets the sequence number in - * the ACK frame and a pending bit according to the auto pending bit feature settings. When auto ACK - * is enabled, the driver notifies the next higher layer about the received frame after the ACK + * aTurnaroundTime (192 us) after the proper frame is received. The driver sets the sequence number + * in the ACK frame and a pending bit according to the auto pending bit feature settings. When auto + * ACK is enabled, the driver notifies the next higher layer about the received frame after the ACK * frame is transmitted. - * If auto ACK is disabled, the driver does not transmit ACK frames. It notifies the next - * higher layer about received frames when a frame is received. In this mode, the next higher layer - * is responsible for sending the ACK frame. ACK frames should be sent using @ref nrf_802154_transmit. + * If auto ACK is disabled, the driver does not transmit ACK frames. It notifies the next higher + * layer about received frames when a frame is received. In this mode, the next higher layer is + * responsible for sending the ACK frame. ACK frames should be sent using @ref nrf_802154_transmit. * * @param[in] enabled If auto ACK should be enabled. */ @@ -824,13 +876,14 @@ bool nrf_802154_auto_ack_get(void); * * @note Setting a pending bit in automatically transmitted ACK frames is enabled by default. * - * The radio driver automatically sends ACK frames in response frames destined to this node with the ACK - * Request bit set. The pending bit in the ACK frame can be set or cleared regarding data in the indirect queue - * destined to ACK destination. + * The radio driver automatically sends ACK frames in response frames destined to this node with the + * ACK Request bit set. The pending bit in the ACK frame can be set or cleared regarding data in the + * indirect queue destined to ACK destination. * * If setting a pending bit in ACK frames is disabled, the pending bit in every ACK frame is set. * If setting a pending bit in ACK frames is enabled, the radio driver checks if there is data - * in the indirect queue destined to ACK destination. If there is no such data, the pending bit is cleared. + * in the indirect queue destined to ACK destination. If there is no such data, the pending bit is + * cleared. * * @note Due to ISR latency, the radio driver might not be able to verify if there is data in * the indirect queue before ACK is sent. In this case, the pending bit is set. @@ -866,7 +919,8 @@ bool nrf_802154_pending_bit_for_addr_clear(const uint8_t *p_addr, bool extended) /** * @brief Remove all addresses of a given type from the pending bit list. * - * @param[in] extended If the function should remove all extended MAC addresses or all short addresses. + * @param[in] extended If the function should remove all extended MAC addresses or all short + * addresses. */ void nrf_802154_pending_bit_for_addr_reset(bool extended); @@ -905,14 +959,15 @@ void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg); * The end of the CSMA-CA procedure is notified by @ref nrf_802154_transmitted_raw or * @ref nrf_802154_transmit_failed. * - * @note The driver may be configured to automatically time out waiting for an ACK frame depending on - * @ref NRF_802154_ACK_TIMEOUT_ENABLED. If automatic ACK time-out is - * disabled, the CSMA-CA procedure does not time out waiting for an ACK frame if a frame with the ACK - * request bit set was transmitted. The MAC layer should manage the timer to time out waiting for the ACK - * frame. This timer can be started by @ref nrf_802154_tx_started. When the timer - * expires, the MAC layer should call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop - * waiting for the ACK frame. - * @note Before the CSMA-CA procedure is used, the application should initialize a random seed with srand. + * @note The driver may be configured to automatically time out waiting for an ACK frame depending + * on @ref NRF_802154_ACK_TIMEOUT_ENABLED. If automatic ACK time-out is disabled, the CSMA-CA + * procedure does not time out waiting for an ACK frame if a frame with the ACK request bit + * set was transmitted. The MAC layer should manage the timer to time out waiting for the ACK + * frame. This timer can be started by @ref nrf_802154_tx_started. When the timer expires, + * the MAC layer should call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting + * for the ACK frame. + * @note Before the CSMA-CA procedure is used, the application should initialize a random seed with + * srand. * * @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw. */ @@ -926,14 +981,15 @@ void nrf_802154_transmit_csma_ca_raw(const uint8_t * p_data); * The end of the CSMA-CA procedure is notified by @ref nrf_802154_transmitted or * @ref nrf_802154_transmit_failed. * - * @note The driver may be configured to automatically time out waiting for an ACK frame depending on - * @ref NRF_802154_ACK_TIMEOUT_ENABLED. If automatic ACK time-out is - * disabled, the CSMA-CA procedure does not time out waiting for an ACK frame if a frame with the ACK - * request bit set was transmitted. The MAC layer should manage the timer to time out waiting for the ACK - * frame. This timer can be started by @ref nrf_802154_tx_started. When the timer - * expires, the MAC layer should call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop - * waiting for the ACK frame. - * @note Before the CSMA-CA procedure is used, the application should initialize a random seed with srand. + * @note The driver may be configured to automatically time out waiting for an ACK frame depending + * on @ref NRF_802154_ACK_TIMEOUT_ENABLED. If automatic ACK time-out is disabled, the CSMA-CA + * procedure does not time out waiting for an ACK frame if a frame with the ACK request bit + * set was transmitted. The MAC layer should manage the timer to time out waiting for the ACK + * frame. This timer can be started by @ref nrf_802154_tx_started. When the timer expires, + * the MAC layer should call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting + * for the ACK frame. + * @note Before the CSMA-CA procedure is used, the application should initialize a random seed with + * srand. * * @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit. * @param[in] length Length of the given frame. See also @ref nrf_802154_transmit. diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.c index 482b162e1..d81eff006 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_core.c @@ -180,6 +180,7 @@ static uint32_t m_ed_time_left; ///< Remaining time of curren static uint8_t m_ed_result; ///< Result of current energy detection procedure. static volatile radio_state_t m_state = RADIO_STATE_SLEEP; ///< State of the radio driver +static volatile bool m_timeslot_is_granted; ///< Indicates if RAAL reported that timeslot is granted. typedef struct { @@ -251,14 +252,32 @@ static uint8_t lqi_get(const uint8_t * p_data) return (uint8_t)lqi; } -/** Notify MAC layer that a frame was received. */ +/** Check if RAAL reported that timeslot is granted. + * + * @note This function may return other value than @ref nrf_raal_timeslot_is_granted, because + * in critical sections RAAL reports are delayed. + * + * @retval true RAAL reported that timeslot is granted. + * @retval false RAAL reported that timeslot is not granted. + */ +static bool timeslot_is_granted(void) +{ + return m_timeslot_is_granted; +} + static void received_frame_notify(uint8_t * p_psdu) { - nrf_802154_critical_section_nesting_allow(); - nrf_802154_notify_received(p_psdu, // data rssi_last_measurement_get(), // rssi lqi_get(p_psdu)); // lqi +} + +/** Allow nesting critical sections and notify MAC layer that a frame was received. */ +static void received_frame_notify_and_nesting_allow(uint8_t * p_psdu) +{ + nrf_802154_critical_section_nesting_allow(); + + received_frame_notify(p_psdu); nrf_802154_critical_section_nesting_deny(); } @@ -610,7 +629,7 @@ static bool ed_iter_setup(uint32_t time_us) } else { - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { irq_deinit(); nrf_radio_reset(); @@ -857,12 +876,19 @@ static void rx_restart(bool set_shorts) /** Terminate Falling Asleep procedure. */ static void falling_asleep_terminate(void) { - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { nrf_radio_int_disable(NRF_RADIO_INT_DISABLED_MASK); } } +/** Terminate Sleep procedure. */ +static void sleep_terminate(void) +{ + nrf_802154_priority_drop_timeslot_exit_terminate(); + nrf_raal_continuous_mode_enter(); +} + /** Terminate RX procedure. */ static void rx_terminate(void) { @@ -898,7 +924,7 @@ static void rx_terminate(void) nrf_timer_shorts_disable(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE1_STOP_MASK); #endif // NRF_802154_DISABLE_BCC_MATCHING - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { #if !NRF_802154_DISABLE_BCC_MATCHING || NRF_802154_NOTIFY_CRCERROR ints_to_disable |= NRF_RADIO_INT_CRCERROR_MASK; @@ -943,7 +969,7 @@ static void tx_ack_terminate(void) nrf_timer_shorts_disable(NRF_802154_COUNTER_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE1_STOP_MASK); #endif // NRF_802154_DISABLE_BCC_MATCHING - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { ints_to_disable = nrf_802154_revision_has_phyend_event() ? NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK; @@ -970,7 +996,7 @@ static void tx_terminate(void) nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { ints_to_disable = nrf_802154_revision_has_phyend_event() ? NRF_RADIO_INT_PHYEND_MASK : NRF_RADIO_INT_END_MASK; @@ -996,7 +1022,7 @@ static void rx_ack_terminate(void) nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { nrf_radio_int_disable(NRF_RADIO_INT_END_MASK); nrf_radio_shorts_set(SHORTS_IDLE); @@ -1017,7 +1043,7 @@ static void ed_terminate(void) nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { nrf_radio_int_disable(NRF_RADIO_INT_EDEND_MASK); nrf_radio_shorts_set(SHORTS_IDLE); @@ -1036,7 +1062,7 @@ static void cca_terminate(void) nrf_ppi_channel_remove_from_group(PPI_EGU_RAMP_UP, PPI_CHGRP0); nrf_ppi_fork_endpoint_setup(PPI_EGU_RAMP_UP, 0); - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { nrf_radio_int_disable(NRF_RADIO_INT_CCABUSY_MASK | NRF_RADIO_INT_CCAIDLE_MASK); nrf_radio_shorts_set(SHORTS_IDLE); @@ -1052,7 +1078,7 @@ static void continuous_carrier_terminate(void) fem_for_pa_reset(); - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); } @@ -1085,9 +1111,8 @@ static bool current_operation_terminate(nrf_802154_term_t term_lvl, case RADIO_STATE_SLEEP: if (req_orig != REQ_ORIG_RAAL) { - // Enter continuous mode unless terminating current operation is requested by - // RAAL during timeslot end procedure. - nrf_raal_continuous_mode_enter(); + // Terminate sleep state unless it is requested by RAAL during timeslot end. + sleep_terminate(); } break; @@ -1124,6 +1149,12 @@ static bool current_operation_terminate(nrf_802154_term_t term_lvl, if (term_lvl >= NRF_802154_TERM_802154) { tx_ack_terminate(); + + if (notify_abort) + { + mp_current_rx_buffer->free = false; + received_frame_notify(mp_current_rx_buffer->psdu); + } } else { @@ -1216,12 +1247,13 @@ static bool current_operation_terminate(nrf_802154_term_t term_lvl, static void sleep_init(void) { nrf_802154_priority_drop_timeslot_exit(); + m_timeslot_is_granted = false; } /** Initialize Falling Asleep operation. */ static void falling_asleep_init(void) { - if (!nrf_raal_timeslot_is_granted()) + if (!timeslot_is_granted()) { state_set(RADIO_STATE_SLEEP); sleep_init(); @@ -1248,7 +1280,7 @@ static void rx_init(bool disabled_was_triggered) uint32_t lna_target_time; uint32_t pa_target_time; - if (!nrf_raal_timeslot_is_granted()) + if (!timeslot_is_granted()) { return; } @@ -1532,7 +1564,7 @@ static void cca_init(bool disabled_was_triggered) /** Initialize Continuous Carrier operation. */ static void continuous_carrier_init(bool disabled_was_triggered) { - if (!nrf_raal_timeslot_is_granted()) + if (!timeslot_is_granted()) { return; } @@ -1568,6 +1600,11 @@ void nrf_raal_timeslot_started(void) nrf_radio_init(); irq_init(); + if (m_state != RADIO_STATE_SLEEP) + { + m_timeslot_is_granted = true; + } + assert(nrf_radio_shorts_get() == SHORTS_IDLE); switch (m_state) @@ -1628,6 +1665,9 @@ void nrf_raal_timeslot_ended(void) result = current_operation_terminate(NRF_802154_TERM_802154, REQ_ORIG_RAAL, false); assert(result); + (void)result; + + m_timeslot_is_granted = false; switch (m_state) { @@ -1650,7 +1690,8 @@ void nrf_raal_timeslot_ended(void) case RADIO_STATE_TX_ACK: state_set(RADIO_STATE_RX); - receive_failed_notify(NRF_802154_RX_ERROR_TIMESLOT_ENDED); + mp_current_rx_buffer->free = false; + received_frame_notify_and_nesting_allow(mp_current_rx_buffer->psdu); break; case RADIO_STATE_CCA_TX: @@ -1823,7 +1864,7 @@ static void irq_crcok_state_rx(void) nrf_802154_pib_promiscuous_get()) { mp_current_rx_buffer->free = false; - received_frame_notify(p_received_psdu); + received_frame_notify_and_nesting_allow(p_received_psdu); } return; @@ -1941,7 +1982,7 @@ static void irq_crcok_state_rx(void) rx_terminate(); rx_init(true); - received_frame_notify(p_received_psdu); + received_frame_notify_and_nesting_allow(p_received_psdu); } } else @@ -1967,7 +2008,7 @@ static void irq_crcok_state_rx(void) } } - received_frame_notify(p_received_psdu); + received_frame_notify_and_nesting_allow(p_received_psdu); } else { @@ -2101,7 +2142,7 @@ static void irq_phyend_state_tx_ack(void) rx_flags_clear(); - received_frame_notify(p_received_psdu); + received_frame_notify_and_nesting_allow(p_received_psdu); } static void irq_phyend_state_tx_frame(void) @@ -2545,7 +2586,7 @@ void nrf_802154_core_deinit(void) { current_operation_terminate(NRF_802154_TERM_802154, REQ_ORIG_HIGHER_LAYER, true); - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { nrf_radio_reset(); } @@ -2681,7 +2722,7 @@ bool nrf_802154_core_notify_buffer_free(uint8_t * p_data) p_buffer->free = true; - if (!nrf_raal_timeslot_is_granted()) + if (!timeslot_is_granted()) { return true; } @@ -2734,7 +2775,7 @@ bool nrf_802154_core_channel_update(void) { bool result; - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { channel_set(nrf_802154_pib_channel_get()); } @@ -2750,7 +2791,7 @@ bool nrf_802154_core_channel_update(void) } case RADIO_STATE_CONTINUOUS_CARRIER: - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { channel_set(nrf_802154_pib_channel_get()); nrf_radio_task_trigger(NRF_RADIO_TASK_DISABLE); @@ -2763,7 +2804,7 @@ bool nrf_802154_core_channel_update(void) case RADIO_STATE_TX: case RADIO_STATE_RX_ACK: case RADIO_STATE_CCA: - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { channel_set(nrf_802154_pib_channel_get()); } @@ -2782,7 +2823,7 @@ bool nrf_802154_core_channel_update(void) bool nrf_802154_core_cca_cfg_update(void) { - if (nrf_raal_timeslot_is_granted()) + if (timeslot_is_granted()) { cca_configuration_update(); } diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.c index 7b39b360b..e0dc56a50 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_critical_section.c @@ -149,6 +149,7 @@ void nrf_802154_critical_section_forcefully_enter(void) { bool critical_section_entered = critical_section_enter(true); assert(critical_section_entered); + (void)critical_section_entered; } void nrf_802154_critical_section_exit(void) @@ -167,6 +168,7 @@ void nrf_802154_critical_section_exit(void) if (cnt == 1) { assert(!exiting_crit_sect); + (void)exiting_crit_sect; exiting_crit_sect = true; // RAAL critical section shall be exited before RADIO IRQ handler is enabled. In other diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop.h index 7558c2ec0..14de19f08 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop.h @@ -55,6 +55,15 @@ void nrf_802154_priority_drop_init(void); */ void nrf_802154_priority_drop_timeslot_exit(void); +/** + * @brief Terminate requesting of timeslot discarding. + * + * Function used to to terminate timeslot exit procedure requested by previous call to + * @rev nrf_802154_priority_drop_timeslot_exit. Timeslot discarding is terminated only if it has + * not been started. + */ +void nrf_802154_priority_drop_timeslot_exit_terminate(void); + /** *@} **/ diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_direct.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_direct.c index 3277b7237..0930e39de 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_direct.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_direct.c @@ -49,3 +49,9 @@ void nrf_802154_priority_drop_timeslot_exit(void) nrf_raal_continuous_mode_exit(); } +void nrf_802154_priority_drop_timeslot_exit_terminate(void) +{ + // Intentionally empty: + // nrf_802154_priority_drop_timeslot_exit is synchronous and cannot be terminated. +} + diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_swi.c index 44b8cb764..e6e36bcfa 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_swi.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_priority_drop_swi.c @@ -49,3 +49,8 @@ void nrf_802154_priority_drop_timeslot_exit(void) nrf_802154_swi_timeslot_exit(); } +void nrf_802154_priority_drop_timeslot_exit_terminate(void) +{ + nrf_802154_swi_timeslot_exit_terminate(); +} + diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c index 8c07a9c92..34a580298 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_direct.c @@ -43,39 +43,25 @@ #include "nrf_802154_critical_section.h" #include "hal/nrf_radio.h" -#define REQUEST_FUNCTION(func_core, params_core) \ +#define REQUEST_FUNCTION_WITH_FAIL_INSTR(func_core, fail_instr, ...) \ bool result; \ \ if (nrf_802154_critical_section_enter()) \ { \ - result = func_core params_core; \ + result = func_core(__VA_ARGS__); \ nrf_802154_critical_section_exit(); \ } \ else \ { \ + fail_instr \ result = false; \ } \ \ return result; +#define REQUEST_FUNCTION(func_core, ...) \ + REQUEST_FUNCTION_WITH_FAIL_INSTR(func_core, , __VA_ARGS__) -#define REQUEST_FUNCTION_NO_ARGS(func_core) \ - REQUEST_FUNCTION(func_core, ()) - -#define REQUEST_FUNCTION_1_ARG(func_core, arg) \ - REQUEST_FUNCTION(func_core, (arg)) - -#define REQUEST_FUNCTION_2_ARGS(func_core, arg1, arg2) \ - REQUEST_FUNCTION(func_core, (arg1, arg2)) - -#define REQUEST_FUNCTION_3_ARGS(func_core, arg1, arg2, arg3) \ - REQUEST_FUNCTION(func_core, (arg1, arg2, arg3)) - -#define REQUEST_FUNCTION_4_ARGS(func_core, arg1, arg2, arg3, arg4) \ - REQUEST_FUNCTION(func_core, (arg1, arg2, arg3, arg4)) - -#define REQUEST_FUNCTION_5_ARGS(func_core, arg1, arg2, arg3, arg4, arg5) \ - REQUEST_FUNCTION(func_core, (arg1, arg2, arg3, arg4, arg5)) void nrf_802154_request_init(void) { @@ -84,14 +70,18 @@ void nrf_802154_request_init(void) bool nrf_802154_request_sleep(nrf_802154_term_t term_lvl) { - REQUEST_FUNCTION_1_ARG(nrf_802154_core_sleep, term_lvl) + REQUEST_FUNCTION(nrf_802154_core_sleep, term_lvl) } bool nrf_802154_request_receive(nrf_802154_term_t term_lvl, req_originator_t req_orig, nrf_802154_notification_func_t notify_function) { - REQUEST_FUNCTION_3_ARGS(nrf_802154_core_receive, term_lvl, req_orig, notify_function) + REQUEST_FUNCTION_WITH_FAIL_INSTR(nrf_802154_core_receive, + notify_function(false); , + term_lvl, + req_orig, + notify_function) } bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl, @@ -100,40 +90,41 @@ bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl, bool cca, nrf_802154_notification_func_t notify_function) { - REQUEST_FUNCTION_5_ARGS(nrf_802154_core_transmit, - term_lvl, - req_orig, - p_data, - cca, - notify_function) + REQUEST_FUNCTION_WITH_FAIL_INSTR(nrf_802154_core_transmit, + notify_function(false); , + term_lvl, + req_orig, + p_data, + cca, + notify_function) } bool nrf_802154_request_energy_detection(nrf_802154_term_t term_lvl, uint32_t time_us) { - REQUEST_FUNCTION_2_ARGS(nrf_802154_core_energy_detection, term_lvl, time_us) + REQUEST_FUNCTION(nrf_802154_core_energy_detection, term_lvl, time_us) } bool nrf_802154_request_cca(nrf_802154_term_t term_lvl) { - REQUEST_FUNCTION_1_ARG(nrf_802154_core_cca, term_lvl) + REQUEST_FUNCTION(nrf_802154_core_cca, term_lvl) } bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl) { - REQUEST_FUNCTION_1_ARG(nrf_802154_core_continuous_carrier, term_lvl) + REQUEST_FUNCTION(nrf_802154_core_continuous_carrier, term_lvl) } bool nrf_802154_request_buffer_free(uint8_t * p_data) { - REQUEST_FUNCTION_1_ARG(nrf_802154_core_notify_buffer_free, p_data) + REQUEST_FUNCTION(nrf_802154_core_notify_buffer_free, p_data) } bool nrf_802154_request_channel_update(void) { - REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_channel_update) + REQUEST_FUNCTION(nrf_802154_core_channel_update) } bool nrf_802154_request_cca_cfg_update(void) { - REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_cca_cfg_update) + REQUEST_FUNCTION(nrf_802154_core_cca_cfg_update) } diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c index 55029fd1e..0f5e352a0 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_request_swi.c @@ -50,14 +50,40 @@ #include -#define REQUEST_FUNCTION(func_core, params_core, func_swi, params_swi) \ +#define REQUEST_FUNCTION_WITH_FAIL_INSTR(func_core, func_swi, fail_instr, ...) \ bool result = false; \ \ if (active_vector_priority_is_high()) \ { \ if (nrf_802154_critical_section_enter()) \ { \ - result = func_core params_core; \ + result = func_core(__VA_ARGS__); \ + nrf_802154_critical_section_exit(); \ + } \ + else \ + { \ + fail_instr \ + result = false; \ + } \ + } \ + else \ + { \ + func_swi(__VA_ARGS__, &result); \ + } \ + \ + return result; + +#define REQUEST_FUNCTION(func_core, func_swi, ...) \ + REQUEST_FUNCTION_WITH_FAIL_INSTR(func_core, func_swi, , __VA_ARGS__) + +#define REQUEST_FUNCTION_NO_ARGS(func_core, func_swi) \ + bool result = false; \ + \ + if (active_vector_priority_is_high()) \ + { \ + if (nrf_802154_critical_section_enter()) \ + { \ + result = func_core(); \ nrf_802154_critical_section_exit(); \ } \ else \ @@ -67,35 +93,11 @@ } \ else \ { \ - func_swi params_swi; \ + func_swi(&result); \ } \ \ return result; -#define REQUEST_FUNCTION_NO_ARGS(func_core, func_swi) \ - REQUEST_FUNCTION(func_core, (), func_swi, (&result)) - -#define REQUEST_FUNCTION_1_ARG(func_core, func_swi, arg) \ - REQUEST_FUNCTION(func_core, (arg), func_swi, (arg, &result)) - -#define REQUEST_FUNCTION_2_ARGS(func_core, func_swi, arg1, arg2) \ - REQUEST_FUNCTION(func_core, (arg1, arg2), func_swi, (arg1, arg2, &result)) - -#define REQUEST_FUNCTION_3_ARGS(func_core, func_swi, arg1, arg2, arg3) \ - REQUEST_FUNCTION(func_core, (arg1, arg2, arg3), func_swi, (arg1, arg2, arg3, &result)) - -#define REQUEST_FUNCTION_4_ARGS(func_core, func_swi, arg1, arg2, arg3, arg4) \ - REQUEST_FUNCTION(func_core, \ - (arg1, arg2, arg3, arg4), \ - func_swi, \ - (arg1, arg2, arg3, arg4, &result)) - -#define REQUEST_FUNCTION_5_ARGS(func_core, func_swi, arg1, arg2, arg3, arg4, arg5) \ - REQUEST_FUNCTION(func_core, \ - (arg1, arg2, arg3, arg4, arg5), \ - func_swi, \ - (arg1, arg2, arg3, arg4, arg5, &result)) - /** Check if active vector priority is high enough to call requests directly. * * @retval true Active vector priority is greater or equal to SWI priority. @@ -114,20 +116,19 @@ void nrf_802154_request_init(void) bool nrf_802154_request_sleep(nrf_802154_term_t term_lvl) { - REQUEST_FUNCTION_1_ARG(nrf_802154_core_sleep, - nrf_802154_swi_sleep, - term_lvl) + REQUEST_FUNCTION(nrf_802154_core_sleep, nrf_802154_swi_sleep, term_lvl) } bool nrf_802154_request_receive(nrf_802154_term_t term_lvl, req_originator_t req_orig, nrf_802154_notification_func_t notify_function) { - REQUEST_FUNCTION_3_ARGS(nrf_802154_core_receive, - nrf_802154_swi_receive, - term_lvl, - req_orig, - notify_function) + REQUEST_FUNCTION_WITH_FAIL_INSTR(nrf_802154_core_receive, + nrf_802154_swi_receive, + notify_function(false); , + term_lvl, + req_orig, + notify_function) } bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl, @@ -136,54 +137,47 @@ bool nrf_802154_request_transmit(nrf_802154_term_t term_lvl, bool cca, nrf_802154_notification_func_t notify_function) { - REQUEST_FUNCTION_5_ARGS(nrf_802154_core_transmit, - nrf_802154_swi_transmit, - term_lvl, - req_orig, - p_data, - cca, - notify_function) + REQUEST_FUNCTION_WITH_FAIL_INSTR(nrf_802154_core_transmit, + nrf_802154_swi_transmit, + notify_function(false); , + term_lvl, + req_orig, + p_data, + cca, + notify_function) } bool nrf_802154_request_energy_detection(nrf_802154_term_t term_lvl, uint32_t time_us) { - REQUEST_FUNCTION_2_ARGS(nrf_802154_core_energy_detection, - nrf_802154_swi_energy_detection, - term_lvl, - time_us) + REQUEST_FUNCTION(nrf_802154_core_energy_detection, + nrf_802154_swi_energy_detection, + term_lvl, + time_us) } bool nrf_802154_request_cca(nrf_802154_term_t term_lvl) { - REQUEST_FUNCTION_1_ARG(nrf_802154_core_cca, - nrf_802154_swi_cca, - term_lvl) + REQUEST_FUNCTION(nrf_802154_core_cca, nrf_802154_swi_cca, term_lvl) } bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl) { - REQUEST_FUNCTION_1_ARG(nrf_802154_core_continuous_carrier, - nrf_802154_swi_continuous_carrier, - term_lvl) + REQUEST_FUNCTION(nrf_802154_core_continuous_carrier, nrf_802154_swi_continuous_carrier, term_lvl) } bool nrf_802154_request_buffer_free(uint8_t * p_data) { - REQUEST_FUNCTION_1_ARG(nrf_802154_core_notify_buffer_free, - nrf_802154_swi_buffer_free, - p_data) + REQUEST_FUNCTION(nrf_802154_core_notify_buffer_free, nrf_802154_swi_buffer_free, p_data) } bool nrf_802154_request_channel_update(void) { - REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_channel_update, - nrf_802154_swi_channel_update) + REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_channel_update, nrf_802154_swi_channel_update) } bool nrf_802154_request_cca_cfg_update(void) { - REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_cca_cfg_update, - nrf_802154_swi_cca_cfg_update) + REQUEST_FUNCTION_NO_ARGS(nrf_802154_core_cca_cfg_update, nrf_802154_swi_cca_cfg_update) } diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.c index af6c0a63a..473b49dfc 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_revision.c @@ -111,7 +111,7 @@ bool nrf_802154_revision_has_phyend_event(void) #elif NRF52840_AABA return true; #else - bool result; + bool result = false; switch (m_nrf52840_revision) { diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c index 75198d5d0..dc78f266a 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.c @@ -368,6 +368,7 @@ static nrf_802154_req_data_t * req_enter(void) __ISB(); assert(!req_queue_is_full()); + (void)req_queue_is_full(); return &m_req_queue[m_req_w_ptr]; } @@ -511,6 +512,7 @@ void nrf_802154_swi_notify_cca(bool channel_free) void nrf_802154_swi_notify_cca_failed(nrf_802154_cca_error_t error) { assert(!ntf_queue_is_full()); + (void)ntf_queue_is_full(); nrf_802154_ntf_data_t * p_slot = &m_ntf_queue[m_ntf_w_ptr]; @@ -529,6 +531,11 @@ void nrf_802154_swi_timeslot_exit(void) nrf_egu_task_trigger(SWI_EGU, TIMESLOT_EXIT_TASK); } +void nrf_802154_swi_timeslot_exit_terminate(void) +{ + nrf_egu_event_clear(SWI_EGU, TIMESLOT_EXIT_EVENT); +} + void nrf_802154_swi_sleep(nrf_802154_term_t term_lvl, bool * p_result) { nrf_802154_req_data_t * p_slot = req_enter(); @@ -754,6 +761,12 @@ void SWI_IRQHandler(void) p_slot->data.receive.req_orig, p_slot->data.receive.notif_func) : false; + + if (!in_crit_sect) + { + p_slot->data.receive.notif_func(false); + } + break; case REQ_TYPE_TRANSMIT: @@ -764,6 +777,12 @@ void SWI_IRQHandler(void) p_slot->data.transmit.cca, p_slot->data.transmit.notif_func) : false; + + if (!in_crit_sect) + { + p_slot->data.transmit.notif_func(false); + } + break; case REQ_TYPE_ENERGY_DETECTION: diff --git a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h index 861dcb193..809e34d56 100644 --- a/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h +++ b/third_party/NordicSemiconductor/drivers/radio/nrf_802154_swi.h @@ -127,6 +127,13 @@ void nrf_802154_swi_notify_cca_failed(nrf_802154_cca_error_t error); */ void nrf_802154_swi_timeslot_exit(void); +/** + * @brief Terminate discarding of the timeslot. + * + * @note This function terminates discrading of timeslot only if it has not been performed. + */ +void nrf_802154_swi_timeslot_exit_terminate(void); + /** * @brief Request entering sleep state from SWI priority. * diff --git a/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c b/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c index b0ac7c2fd..6e9937429 100644 --- a/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c +++ b/third_party/NordicSemiconductor/drivers/radio/raal/single_phy/single_phy.c @@ -44,7 +44,9 @@ #include "platform/clock/nrf_802154_clock.h" -static bool m_continuous; +static bool m_continuous; +static volatile bool m_critical_section; +static volatile bool m_started_pending; void nrf_raal_init(void) { @@ -93,15 +95,28 @@ uint32_t nrf_raal_timeslot_us_left_get(void) void nrf_raal_critical_section_enter(void) { - // Intentionally empty. + m_critical_section = true; } void nrf_raal_critical_section_exit(void) { - // Intentionally empty. + m_critical_section = false; + + if (m_started_pending) + { + nrf_raal_timeslot_started(); + m_started_pending = false; + } } void nrf_802154_clock_hfclk_ready(void) { - nrf_raal_timeslot_started(); + if (m_critical_section) + { + m_started_pending = true; + } + else + { + nrf_raal_timeslot_started(); + } } diff --git a/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c b/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c index 2780ff817..0a6467f87 100644 --- a/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c +++ b/third_party/NordicSemiconductor/drivers/radio/raal/softdevice/nrf_raal_softdevice.c @@ -689,6 +689,7 @@ void nrf_raal_init(void) uint32_t err_code = sd_radio_session_open(signal_handler); assert(err_code == NRF_SUCCESS); + (void)err_code; m_initialized = true; } @@ -699,6 +700,7 @@ void nrf_raal_uninit(void) uint32_t err_code = sd_radio_session_close(); assert(err_code == NRF_SUCCESS); + (void)err_code; m_continuous = false; m_timeslot_state = TIMESLOT_STATE_IDLE;