From c081c7be7ca08819bc98f7899a89353ab88bd6bc Mon Sep 17 00:00:00 2001 From: Andrzej Kuros Date: Tue, 21 Dec 2021 18:11:29 +0100 Subject: [PATCH] drivers: nrf_802154: Update the IEEE 802.15.4 component This commit updates the nRF 802.15.4 radio driver to feature the latest changes. sdk-nrf-802154 commit: 453044a0e97ec2c8fa2d6d0135a093cbc5362eb2 Signed-off-by: Andrzej Kuros --- drivers/nrf_802154/driver/CMakeLists.txt | 19 +- .../nrf_802154/driver/include/nrf_802154.h | 204 +++-- .../driver/include/nrf_802154_config.h | 46 +- .../driver/include/nrf_802154_const.h | 13 +- .../driver/include/nrf_802154_types.h | 16 +- .../include/platform/nrf_802154_random.h | 2 +- .../ack_generator/nrf_802154_ack_data.h | 2 +- .../ack_generator/nrf_802154_ack_generator.c | 8 +- .../ack_generator/nrf_802154_ack_generator.h | 17 +- .../nrf_802154_enh_ack_generator.c | 369 ++++++--- .../nrf_802154_enh_ack_generator.h | 15 +- .../nrf_802154_imm_ack_generator.c | 11 + .../nrf_802154_imm_ack_generator.h | 20 +- .../src/mac_features/nrf_802154_ack_timeout.h | 2 +- .../src/mac_features/nrf_802154_csma_ca.c | 10 +- .../src/mac_features/nrf_802154_delayed_trx.c | 85 +- .../src/mac_features/nrf_802154_delayed_trx.h | 1 + .../src/mac_features/nrf_802154_filter.c | 8 +- .../mac_features/nrf_802154_frame_parser.c | 36 +- .../src/mac_features/nrf_802154_ie_writer.c | 1 - .../src/mac_features/nrf_802154_ie_writer.h | 2 +- .../driver/src/mac_features/nrf_802154_ifs.c | 45 +- .../nrf_802154_precise_ack_timeout.c | 7 +- .../mac_features/nrf_802154_security_writer.c | 19 +- drivers/nrf_802154/driver/src/nrf_802154.c | 53 +- .../driver/src/nrf_802154_aes_ccm.c | 52 +- .../driver/src/nrf_802154_aes_ccm.h | 12 + .../nrf_802154/driver/src/nrf_802154_core.c | 248 +++--- .../nrf_802154/driver/src/nrf_802154_core.h | 25 +- .../driver/src/nrf_802154_core_hooks.c | 27 + .../driver/src/nrf_802154_core_hooks.h | 9 + .../driver/src/nrf_802154_critical_section.c | 118 ++- .../driver/src/nrf_802154_critical_section.h | 17 +- .../driver/src/nrf_802154_debug_log.h | 8 +- .../driver/src/nrf_802154_debug_log_codes.h | 11 +- .../driver/src/nrf_802154_encrypt.c | 25 +- .../driver/src/nrf_802154_encrypt.h | 22 + .../driver/src/nrf_802154_notification.h | 24 +- .../src/nrf_802154_notification_direct.c | 54 +- .../driver/src/nrf_802154_notification_swi.c | 414 ++++++++-- .../driver/src/nrf_802154_peripherals_alloc.c | 77 ++ .../driver/src/nrf_802154_peripherals_nrf52.h | 2 +- .../driver/src/nrf_802154_peripherals_nrf53.h | 93 ++- .../nrf_802154/driver/src/nrf_802154_pib.c | 1 - .../driver/src/nrf_802154_request.h | 75 ++ .../driver/src/nrf_802154_request_direct.c | 40 + .../driver/src/nrf_802154_request_swi.c | 176 +++- .../nrf_802154/driver/src/nrf_802154_rssi.h | 2 +- .../nrf_802154/driver/src/nrf_802154_swi.c | 1 - .../nrf_802154/driver/src/nrf_802154_trx.c | 181 +++-- .../nrf_802154/driver/src/nrf_802154_trx.h | 47 +- .../driver/src/nrf_802154_trx_dppi.c | 64 +- .../driver/src/nrf_802154_trx_ppi.c | 39 +- .../driver/src/nrf_802154_trx_ppi_api.h | 38 +- .../driver/src/nrf_802154_tx_work_buffer.h | 5 +- .../serialization/include/host/nrf_802154.h | 360 ++++++++- .../include/host/nrf_802154_config.h | 56 +- .../include/host/nrf_802154_const.h | 189 ++++- .../include/host/nrf_802154_types.h | 103 ++- .../src/include/nrf_802154_spinel.h | 6 +- .../src/include/nrf_802154_spinel_datatypes.h | 552 ++++++++++++- .../src/include/nrf_802154_spinel_dec_app.h | 50 +- .../src/nrf_802154_buffer_allocator.c | 1 - .../serialization/src/nrf_802154_spinel_app.c | 762 +++++++++++++++++- .../src/nrf_802154_spinel_dec_app.c | 140 +++- .../src/nrf_802154_spinel_dec_net.c | 721 ++++++++++++++++- .../serialization/src/nrf_802154_spinel_net.c | 22 +- .../sl/include/nrf_802154_sl_ant_div.h | 2 +- .../sl/include/nrf_802154_sl_crit_sect_if.h | 103 +++ .../sl/include/nrf_802154_sl_periphs.h | 43 + .../sl/include/nrf_802154_sl_types.h | 76 ++ .../include/rsch/nrf_802154_rsch_crit_sect.h | 23 +- .../sl/include/timer/nrf_802154_timer_coord.h | 7 +- .../sl/sl_opensource/CMakeLists.txt | 1 + .../{ => protocol}/mpsl_fem_protocol_api.h | 52 +- .../src/nrf_802154_sl_crit_sect_if.c | 44 + .../sl/sl_opensource/src/nrf_802154_sl_fem.c | 7 +- .../sl/sl_opensource/src/nrf_802154_sl_rsch.c | 5 + 78 files changed, 5331 insertions(+), 912 deletions(-) create mode 100644 drivers/nrf_802154/driver/src/nrf_802154_peripherals_alloc.c create mode 100644 drivers/nrf_802154/sl/include/nrf_802154_sl_crit_sect_if.h create mode 100644 drivers/nrf_802154/sl/include/nrf_802154_sl_types.h rename drivers/nrf_802154/sl/sl_opensource/include/{ => protocol}/mpsl_fem_protocol_api.h (85%) create mode 100644 drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_crit_sect_if.c diff --git a/drivers/nrf_802154/driver/CMakeLists.txt b/drivers/nrf_802154/driver/CMakeLists.txt index 06e0d9e..c2fcde4 100644 --- a/drivers/nrf_802154/driver/CMakeLists.txt +++ b/drivers/nrf_802154/driver/CMakeLists.txt @@ -52,6 +52,7 @@ target_sources(nrf-802154-driver src/nrf_802154_debug_assert.c src/nrf_802154_encrypt.c src/nrf_802154_pib.c + src/nrf_802154_peripherals_alloc.c src/nrf_802154_queue.c src/nrf_802154_rssi.c src/nrf_802154_rx_buffer.c @@ -91,7 +92,7 @@ else () ) endif () -if (SL_OPENSOURCE OR NRF53_SERIES) +if (SL_OPENSOURCE) target_compile_definitions(nrf-802154-driver-interface INTERFACE # Disable Frame Timestamps @@ -100,8 +101,20 @@ if (SL_OPENSOURCE OR NRF53_SERIES) NRF_802154_DELAYED_TRX_ENABLED=0 # Disable IFS NRF_802154_IFS_ENABLED=0 - # Disable IE writer - NRF_802154_IE_WRITER_ENABLED=0 + ) +elseif (NRF53_SERIES) + target_compile_definitions(nrf-802154-driver-interface + INTERFACE + # Disable IFS + NRF_802154_IFS_ENABLED=0 + ) +endif() + +if (NRF_802154_PROJECT_CONFIG) + target_compile_definitions(nrf-802154-driver-interface + INTERFACE + # Propagate project config from build system defines + NRF_802154_PROJECT_CONFIG="${NRF_802154_PROJECT_CONFIG}" ) endif() diff --git a/drivers/nrf_802154/driver/include/nrf_802154.h b/drivers/nrf_802154/driver/include/nrf_802154.h index 54e9df6..9366007 100644 --- a/drivers/nrf_802154/driver/include/nrf_802154.h +++ b/drivers/nrf_802154/driver/include/nrf_802154.h @@ -102,11 +102,12 @@ void nrf_802154_deinit(void); */ extern void nrf_802154_custom_part_of_radio_init(void); -#if !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING +#if !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING || defined(DOXYGEN) + /** * @brief Handles the interrupt request from the RADIO peripheral. * - * @note If NRF_802154_INTERNAL_RADIO_IRQ_HANDLING is enabled, the driver internally handles the + * @note If @ref NRF_802154_INTERNAL_RADIO_IRQ_HANDLING is enabled, the driver internally handles the * RADIO IRQ, and this function must not be called. * * This function is intended for use in an operating system environment, where the OS handles IRQ @@ -114,13 +115,15 @@ extern void nrf_802154_custom_part_of_radio_init(void); * radio IRQ to the driver (that is, SoftDevice). */ void nrf_802154_radio_irq_handler(void); + #endif // !NRF_802154_INTERNAL_RADIO_IRQ_HANDLING -#if !NRF_802154_INTERNAL_SWI_IRQ_HANDLING +#if !NRF_802154_INTERNAL_SWI_IRQ_HANDLING || defined(DOXYGEN) + /** * @brief Handles the interrupt request from the RADIO peripheral. * - * @note If NRF_802154_INTERNAL_SWI_IRQ_HANDLING is enabled, the driver internally handles the + * @note If @ref NRF_802154_INTERNAL_SWI_IRQ_HANDLING is enabled, the driver internally handles the * SWI IRQ, and this function must not be called. * * This function is intended for use in an operating system environment, where the OS handles IRQ @@ -128,6 +131,7 @@ void nrf_802154_radio_irq_handler(void); * radio IRQ to the driver (that is, SoftDevice). */ void nrf_802154_swi_irq_handler(void); + #endif // !NRF_802154_INTERNAL_SWI_IRQ_HANDLING /** @@ -204,8 +208,8 @@ nrf_802154_sl_ant_div_mode_t nrf_802154_antenna_diversity_tx_mode_get(void); * @brief Manually selects the antenna to be used for rx. * * For antenna to be switched, antenna diversity rx mode needs - * to be @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL. Otherwise, antenna will - * be only switched after @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL is set. + * to be @c NRF_802154_SL_ANT_DIV_MODE_MANUAL. Otherwise, antenna will + * be only switched after @c NRF_802154_SL_ANT_DIV_MODE_MANUAL is set. * * @param[in] antenna Antenna to be used. * @@ -218,9 +222,8 @@ bool nrf_802154_antenna_diversity_rx_antenna_set(nrf_802154_sl_ant_div_antenna_t * @brief Gets antenna currently used for rx. * * @note The antenna read by this function is currently used rx antenna only if - * antenna diversity rx mode is set to @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL. Otherwise, + * antenna diversity rx mode is set to @c NRF_802154_SL_ANT_DIV_MODE_MANUAL. Otherwise, * currently used antenna may be different. - * @sa nrf_802154_sl_ant_div_mode_set * * @return Currently used antenna. */ @@ -230,8 +233,8 @@ nrf_802154_sl_ant_div_antenna_t nrf_802154_antenna_diversity_rx_antenna_get(void * @brief Manually selects the antenna to be used for tx. * * For antenna to be switched, antenna diversity tx mode needs - * to be @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL. Otherwise, antenna will - * be only switched after @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL is set. + * to be @c NRF_802154_SL_ANT_DIV_MODE_MANUAL. Otherwise, antenna will + * be only switched after @c NRF_802154_SL_ANT_DIV_MODE_MANUAL is set. * * @param[in] antenna Antenna to be used. * @@ -244,9 +247,8 @@ bool nrf_802154_antenna_diversity_tx_antenna_set(nrf_802154_sl_ant_div_antenna_t * @brief Gets antenna currently used for tx. * * @note The antenna read by this function is currently used tx antenna only if - * antenna diversity tx mode is set to @ref NRF_802154_SL_ANT_DIV_MODE_MANUAL. Otherwise, + * antenna diversity tx mode is set to @c NRF_802154_SL_ANT_DIV_MODE_MANUAL. Otherwise, * currently used antenna may be different. - * @sa nrf_802154_sl_ant_div_mode_set * * @return Currently used antenna. */ @@ -255,7 +257,7 @@ nrf_802154_sl_ant_div_antenna_t nrf_802154_antenna_diversity_tx_antenna_get(void /** * @brief Gets which antenna was selected as best for the last reception. * - * @note In three cases @ref NRF_802154_SL_ANT_DIV_ANTENNA_NONE may be returned: + * @note In three cases @c NRF_802154_SL_ANT_DIV_ANTENNA_NONE may be returned: * - No frame was received yet. * - Last frame was received with antenna diversity auto mode disabled. * - RSSI measurements didn't have enough time to finish during last frame reception @@ -327,14 +329,13 @@ void nrf_802154_antenna_diversity_timer_irq_handler(void); * @brief Gets the current time. * * The time returned by this function is to be used to calculate timing parameters for - * @ref nrf_802154_transmit_at and @ref nrf_802154_receive_at functions. + * @ref nrf_802154_transmit_raw_at and @ref nrf_802154_receive_at functions. * * @returns Current time in microseconds. */ uint32_t nrf_802154_time_get(void); /** - * @} * @defgroup nrf_802154_addresses Setting addresses and PAN ID of the device * @{ */ @@ -462,7 +463,7 @@ bool nrf_802154_receive(void); * This function works as a delayed version of @ref nrf_802154_receive. It is asynchronous. * It queues the delayed reception using the Radio Scheduler module. * If the delayed reception cannot be performed (@ref nrf_802154_receive_at would return false) - * or the requested reception timeslot is denied, @ref nrf_drv_radio802154_receive_failed is called + * or the requested reception timeslot is denied, @ref nrf_802154_receive_failed is called * with the @ref NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED argument. * * If the requested reception time is in the past, the function returns false and does not @@ -509,23 +510,26 @@ bool nrf_802154_receive_at(uint32_t t0, */ bool nrf_802154_receive_at_cancel(uint32_t id); -#if NRF_802154_USE_RAW_API +#if NRF_802154_USE_RAW_API || defined(DOXYGEN) + /** * @brief Changes the radio state to @ref RADIO_STATE_TX. * * @note If the CPU is halted or interrupted while this function is executed, - * @ref nrf_802154_transmitted or @ref nrf_802154_transmit_failed can be called before this + * @ref nrf_802154_transmitted_raw or @ref nrf_802154_transmit_failed can 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. * + * @note This function is available if @ref NRF_802154_USE_RAW_API is enabled. + * * In the 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 * @ref nrf_802154_sleep after the ACK timeout. - * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted + * The transmission result is reported to the higher layer by calls to @ref nrf_802154_transmitted_raw * or @ref nrf_802154_transmit_failed. * * @verbatim @@ -543,8 +547,11 @@ bool nrf_802154_receive_at_cancel(uint32_t id); * The CRC is computed automatically by the radio hardware. Therefore, * the FCS field can contain any bytes. * @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data - * to transmit and additional parameters for the procedure. - * If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used. + * to transmit. If @c NULL following metadata are used: + * Field | Value + * ----------------|----------------------------------------------------- + * @c frame_props | @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT + * @c cca | @c true * * @retval true The transmission procedure was scheduled. * @retval false The driver could not schedule the transmission procedure. @@ -552,7 +559,9 @@ bool nrf_802154_receive_at_cancel(uint32_t id); bool nrf_802154_transmit_raw(uint8_t * p_data, const nrf_802154_transmit_metadata_t * p_metadata); -#else // NRF_802154_USE_RAW_API +#endif // NRF_802154_USE_RAW_API + +#if !NRF_802154_USE_RAW_API || defined(DOXYGEN) /** * @brief Changes the radio state to transmit. @@ -565,6 +574,8 @@ bool nrf_802154_transmit_raw(uint8_t * p_data, * make a frame copy. To prevent unnecessary memory consumption and to perform zero-copy * transmission, use @ref nrf_802154_transmit_raw instead. * + * @note This function is available if @ref NRF_802154_USE_RAW_API is disabled. + * * In the 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 @@ -588,8 +599,11 @@ bool nrf_802154_transmit_raw(uint8_t * p_data, * @param[in] length Length of the given frame. This value must exclude PHR and FCS fields * from the given frame (exact size of buffer pointed to by @p p_data). * @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data - * to transmit and additional parameters for the procedure. - * If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used. + * to transmit. If @c NULL following metadata are used: + * Field | Value + * ----------------|----------------------------------------------------- + * @c frame_props | @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT + * @c cca | @c true * * @retval true The transmission procedure was scheduled. * @retval false The driver could not schedule the transmission procedure. @@ -598,7 +612,7 @@ bool nrf_802154_transmit(const uint8_t * p_data, uint8_t length, const nrf_802154_transmit_metadata_t * p_metadata); -#endif // NRF_802154_USE_RAW_API +#endif // !NRF_802154_USE_RAW_API /** * @brief Requests transmission at the specified time. @@ -606,18 +620,19 @@ bool nrf_802154_transmit(const uint8_t * p_data, * @note This function is implemented in a zero-copy fashion. It passes the given buffer pointer to * the RADIO peripheral. * + * * This function works as a delayed version of @ref nrf_802154_transmit_raw. It is asynchronous. * It queues the delayed transmission using the Radio Scheduler module and performs it * at the specified time. * - * If the delayed transmission is successfully performed, @ref nrf_802154_transmitted is called. - * If the delayed transmission cannot be performed (@ref nrf_802154_transmit_raw would return false) + * If the delayed transmission is successfully performed, @ref nrf_802154_transmitted_raw is called. + * If the delayed transmission cannot be performed ( @ref nrf_802154_transmit_raw would return @c false) * or the requested transmission timeslot is denied, @ref nrf_802154_transmit_failed with the * @ref NRF_802154_TX_ERROR_TIMESLOT_DENIED argument is called. * * This function is designed to transmit the first symbol of SHR at the given time. * - * If the requested transmission time is in the past, the function returns false and does not + * If the requested transmission time is in the past, the function returns @c false and does not * schedule transmission. * * A successfully scheduled transmission can be cancelled by a call @@ -631,8 +646,12 @@ bool nrf_802154_transmit(const uint8_t * p_data, * in microseconds (us). * @param[in] dt Delta of delay time from @p t0, in microseconds (us). * @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data - * to transmit and additional parameters for the procedure. - * If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used. + * to transmit. If @c NULL following metadata are used: + * Field | Value + * ----------------|----------------------------------------------------- + * @c frame_props | @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT + * @c cca | @c true + * @c channel | As returned by @ref nrf_802154_channel_get * * @retval true The transmission procedure was scheduled. * @retval false The driver could not schedule the transmission procedure. @@ -691,6 +710,8 @@ bool nrf_802154_energy_detection(uint32_t time_us); */ bool nrf_802154_cca(void); +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + /** * @brief Changes the radio state to continuous carrier. * @@ -723,6 +744,8 @@ bool nrf_802154_modulated_carrier(const uint8_t * p_data); * @{ */ +#endif + /** * @brief Notifies about the start of the ACK frame transmission. * @@ -732,7 +755,7 @@ bool nrf_802154_modulated_carrier(const uint8_t * p_data); */ extern void nrf_802154_tx_ack_started(const uint8_t * p_data); -#if NRF_802154_USE_RAW_API +#if NRF_802154_USE_RAW_API || defined(DOXYGEN) /** * @brief Notifies that a frame was received. @@ -741,6 +764,9 @@ extern void nrf_802154_tx_ack_started(const uint8_t * p_data); * 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. + * @note This callout is called by the nRF 802.15.4 Radio Driver if @ref NRF_802154_USE_RAW_API + * is enabled. Default implementation of this function provided by + * the nRF 802.15.4 Radio Driver calls @ref nrf_802154_received_timestamp_raw . * * @verbatim * p_data @@ -771,6 +797,8 @@ extern void nrf_802154_received_raw(uint8_t * p_data, int8_t power, uint8_t lqi) * the timestamp may be invalid. This erroneous situation is indicated by * the @ref NRF_802154_NO_TIMESTAMP value of the @p time parameter. * + * @note This callout is called by the default implementation of @ref nrf_802154_received_raw. + * * @param[in] p_data Pointer to a buffer that contains PHR and PSDU of the received frame. * The first byte in the buffer is the length of the frame (PHR). The following * bytes contain the frame itself (PSDU). The length byte (PHR) includes FCS. @@ -786,8 +814,9 @@ extern void nrf_802154_received_timestamp_raw(uint8_t * p_data, uint8_t lqi, uint32_t time); -#else // NRF_802154_USE_RAW_API +#endif // NRF_802154_USE_RAW_API +#if !NRF_802154_USE_RAW_API || defined(DOXYGEN) /** * @brief Notifies that a frame was received. * @@ -795,6 +824,9 @@ extern void nrf_802154_received_timestamp_raw(uint8_t * p_data, * be used to receive a frame) until @ref nrf_802154_buffer_free is called. * @note The buffer pointed to by @p p_data can be modified by the function handler (and other * modules) until @ref nrf_802154_buffer_free is called. + * @note This callout is called by the nRF 802.15.4 Radio Driver if @ref NRF_802154_USE_RAW_API + * is disabled. Default implementation of this function provided by + * the nRF 802.15.4 Radio Driver calls @ref nrf_802154_received_timestamp . * * @verbatim * p_data @@ -822,6 +854,7 @@ extern void nrf_802154_received(uint8_t * p_data, uint8_t length, int8_t power, * @note The received frame usually contains a timestamp. However, due to a race condition, * the timestamp may be invalid. This erroneous situation is indicated by * the @ref NRF_802154_NO_TIMESTAMP value of the @p time parameter. + * @note This callout is called by the default implementation of @ref nrf_802154_received . * * @param[in] p_data Pointer to a buffer that contains only the payload of the received frame * (PSDU without FCS). @@ -865,23 +898,24 @@ extern void nrf_802154_receive_failed(nrf_802154_rx_error_t error, uint32_t id); */ extern void nrf_802154_tx_started(const uint8_t * p_frame); -#if NRF_802154_USE_RAW_API - +#if NRF_802154_USE_RAW_API || defined(DOXYGEN) /** * @brief Notifies 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 * ended. - * @note The buffer pointed to by @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack + * @note The buffer pointed to by @c nrf_802154_transmit_done_metadata_t::data.transmitted.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 @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack + * @note The buffer pointed to by @c nrf_802154_transmit_done_metadata_t::data.transmitted.p_ack * may be modified by the function handler (and other modules) until * @ref nrf_802154_buffer_free_raw is called. - * @note @ref nrf_802154_transmit_done_metadata_t.data.transmitted.time granularity depends on the + * @note @c nrf_802154_transmit_done_metadata_t::data.transmitted.time granularity depends on the * granularity of the timer driver in the * platform/timer directory. + * @note This callout is called by the nRF 802.15.4 Radio Driver if @ref NRF_802154_USE_RAW_API + * is enabled. * * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame. * @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame. @@ -889,26 +923,29 @@ extern void nrf_802154_tx_started(const uint8_t * p_frame); extern void nrf_802154_transmitted_raw(uint8_t * p_frame, const nrf_802154_transmit_done_metadata_t * p_metadata); -#else // NRF_802154_USE_RAW_API +#endif // NRF_802154_USE_RAW_API +#if !NRF_802154_USE_RAW_API || defined(DOXYGEN) /** * @brief Notifies 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 * ended. - * @note The buffer pointed to by @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack + * @note The buffer pointed to by @c nrf_802154_transmit_done_metadata_t::data.transmitted.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 @ref nrf_802154_transmit_done_metadata_t.data.transmitted.p_ack + * @ref nrf_802154_buffer_free is called. + * @note The buffer pointed to by @c nrf_802154_transmit_done_metadata_t::data.transmitted.p_ack * may be modified by the function handler (and other modules) until - * @ref nrf_802154_buffer_free_raw is called. + * @ref nrf_802154_buffer_free is called. * @note The next higher layer must handle either @ref nrf_802154_transmitted or * @ref nrf_802154_transmitted_raw. It should not handle both functions. - * @note @ref nrf_802154_transmit_done_metadata_t.data.transmitted.time granularity depends on the + * @note @c nrf_802154_transmit_done_metadata_t::data.transmitted.time 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 This callout is called by the nRF 802.15.4 Radio Driver if @ref NRF_802154_USE_RAW_API + * is disabled. * * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame. * @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame. @@ -923,7 +960,7 @@ extern void nrf_802154_transmitted(uint8_t * p * * This function is called if the transmission procedure fails. * - * @note Frame data values in @ref nrf_802154_transmit_done_metadata_t.data are invalid for + * @note Frame data values in @ref nrf_802154_transmit_done_metadata_t::data are invalid for * @ref nrf_802154_transmit_failed callout. * * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that was not @@ -973,7 +1010,7 @@ extern void nrf_802154_cca_failed(nrf_802154_cca_error_t error); * @{ */ -#if NRF_802154_USE_RAW_API +#if NRF_802154_USE_RAW_API || defined(DOXYGEN) /** * @brief Notifies the driver that the buffer containing the received frame is not used anymore. @@ -981,6 +1018,7 @@ extern void nrf_802154_cca_failed(nrf_802154_cca_error_t error); * @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 the IRQ context, use @ref nrf_802154_buffer_free_immediately_raw. + * @note This function is available if @ref NRF_802154_USE_RAW_API is enabled. * * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed * by the higher layer. @@ -994,6 +1032,7 @@ void nrf_802154_buffer_free_raw(uint8_t * p_data); * @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. + * @note This function is available if @ref NRF_802154_USE_RAW_API is enabled. * * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed * by the higher layer. @@ -1003,7 +1042,9 @@ void nrf_802154_buffer_free_raw(uint8_t * p_data); */ bool nrf_802154_buffer_free_immediately_raw(uint8_t * p_data); -#else // NRF_802154_USE_RAW_API +#endif // NRF_802154_USE_RAW_API + +#if !NRF_802154_USE_RAW_API || defined(DOXYGEN) /** * @brief Notifies the driver that the buffer containing the received frame is not used anymore. @@ -1011,6 +1052,7 @@ bool nrf_802154_buffer_free_immediately_raw(uint8_t * p_data); * @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. + * @note This function is available if @ref NRF_802154_USE_RAW_API is disabled. * * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed * by the higher layer. @@ -1024,6 +1066,7 @@ void nrf_802154_buffer_free(uint8_t * p_data); * @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. + * @note This function is available if @ref NRF_802154_USE_RAW_API is disabled. * * @param[in] p_data Pointer to the buffer containing the received data that is no longer needed * by the higher layer. @@ -1033,7 +1076,7 @@ void nrf_802154_buffer_free(uint8_t * p_data); */ bool nrf_802154_buffer_free_immediately(uint8_t * p_data); -#endif // NRF_802154_USE_RAW_API +#endif // !NRF_802154_USE_RAW_API /** * @} @@ -1145,10 +1188,6 @@ bool nrf_802154_pan_coord_get(void); * * @note This method should be called after driver initialization, but before transceiver is enabled. * - * When calling @ref nrf_802154_ack_data_pending_bit_should_be_set, one of several algorithms - * for source address matching will be chosen. To ensure a specific algorithm is selected, - * call this function before @ref rf_802154_ack_data_pending_bit_should_be_set. - * * @param[in] match_method Source address matching method to be used. */ void nrf_802154_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_method); @@ -1185,6 +1224,7 @@ void nrf_802154_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_m * To better illustrate, if RSSI is to be inserted into ACKs for specific address, * following ie data needs to be prepared: * + * @verbatim * +------------+----------------------+---------------------------------+-----------------------------+ * | Bytes: 0-1 | 2-4 | 5 | 6 | * +------------+----------------------+---------------------------------+-----------------------------+ @@ -1192,11 +1232,12 @@ void nrf_802154_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_m * +------------+----------------------+---------------------------------+-----------------------------+ * | | * | <------------------IE Vendor-specific data------------------> | + * @endverbatim * * When sending ACK with this data, before transmission, RSSI of the last received frame * will be written into byte 6. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @param[in] p_addr Array of bytes containing the address of the node (little-endian). * @param[in] extended If the given address is an extended MAC address or a short MAC address. @@ -1225,7 +1266,7 @@ bool nrf_802154_ack_data_set(const uint8_t * p_addr, * - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 * For more information, see @ref nrf_802154_src_addr_match_t. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @param[in] p_addr Array of bytes containing the address of the node (little-endian). * @param[in] extended If the given address is an extended MAC address or a short MAC address. @@ -1269,7 +1310,7 @@ void nrf_802154_auto_pending_bit_set(bool enabled); * - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 * For more information, see @ref nrf_802154_src_addr_match_t. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @note This function makes a copy of the given address. * @@ -1291,7 +1332,7 @@ bool nrf_802154_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended); * - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 * For more information, see @ref nrf_802154_src_addr_match_t. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @param[in] p_addr Array of bytes containing the address of the node (little-endian). * @param[in] extended If the given address is an extended MAC address or a short MAC address. @@ -1311,7 +1352,7 @@ bool nrf_802154_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended * - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 * For more information, see @ref nrf_802154_src_addr_match_t. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @param[in] extended If the function is to remove all extended MAC addresses or all short * addresses. @@ -1344,8 +1385,8 @@ void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg); * @defgroup nrf_802154_csma CSMA-CA procedure * @{ */ -#if NRF_802154_CSMA_CA_ENABLED -#if NRF_802154_USE_RAW_API +#if NRF_802154_CSMA_CA_ENABLED || defined(DOXYGEN) +#if NRF_802154_USE_RAW_API || defined(DOXYGEN) /** * @brief Performs the CSMA-CA procedure and transmits a frame in case of success. @@ -1360,10 +1401,15 @@ void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg); * 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 is expected * to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame. + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled and + * @ref NRF_802154_USE_RAW_API is enabled. * * @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw. * @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data - * to transmit. If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used. + * to transmit. If @c NULL following metadata are used: + * Field | Value + * ----------------|----------------------------------------------------- + * @c frame_props | @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT * * @retval true The chain of CSMA-CA and transmission procedure was scheduled. * @retval false The driver could not schedule the procedure chain. @@ -1386,12 +1432,16 @@ bool nrf_802154_transmit_csma_ca_raw(uint8_t * 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 is expected * to call @ref nrf_802154_receive or @ref nrf_802154_sleep to stop waiting for the ACK frame. + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled and + * @ref NRF_802154_USE_RAW_API is disabled. * * @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. * @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data - * to transmit. If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT - * is used. + * to transmit. If @c NULL following metadata are used: + * Field | Value + * ----------------|----------------------------------------------------- + * @c frame_props | @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT * * @retval true The chain of CSMA-CA and transmission procedure was scheduled. * @retval false The driver could not schedule the procedure chain. @@ -1405,6 +1455,8 @@ bool nrf_802154_transmit_csma_ca(const uint8_t * /** * @brief Sets the minimum value of the backoff exponent (BE) in the CSMA-CA algorithm. * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * * @param[in] min_be Minimum value of the backoff exponent. * * @retval true When value provided by @p min_be has been set successfully. @@ -1415,6 +1467,8 @@ bool nrf_802154_csma_ca_min_be_set(uint8_t min_be); /** * @brief Gets the minimum value of the backoff exponent (BE) in the CSMA-CA algorithm. * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * * @return Current minimum value of the backoff exponent. */ uint8_t nrf_802154_csma_ca_min_be_get(void); @@ -1422,6 +1476,8 @@ uint8_t nrf_802154_csma_ca_min_be_get(void); /** * @brief Sets the maximum value of the backoff exponent (BE) in the CSMA-CA algorithm. * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * * @param[in] max_be Maximum value of the backoff exponent. * * @retval true When value provided by @p max_be has been set successfully. @@ -1432,6 +1488,8 @@ bool nrf_802154_csma_ca_max_be_set(uint8_t max_be); /** * @brief Gets the maximum value of the backoff exponent (BE) in the CSMA-CA algorithm. * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * * @return Current maximum value of the backoff exponent. */ uint8_t nrf_802154_csma_ca_max_be_get(void); @@ -1440,6 +1498,8 @@ uint8_t nrf_802154_csma_ca_max_be_get(void); * @brief Sets the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring * a channel access failure. * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * * @param[in] max_backoffs Maximum number of backoffs. */ void nrf_802154_csma_ca_max_backoffs_set(uint8_t max_backoffs); @@ -1448,6 +1508,8 @@ void nrf_802154_csma_ca_max_backoffs_set(uint8_t max_backoffs); * @brief Gets the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring * a channel access failure. * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * * @return Current maximum number of backoffs. */ uint8_t nrf_802154_csma_ca_max_backoffs_get(void); @@ -1459,13 +1521,15 @@ uint8_t nrf_802154_csma_ca_max_backoffs_get(void); * @defgroup nrf_802154_timeout ACK timeout procedure * @{ */ -#if NRF_802154_ACK_TIMEOUT_ENABLED +#if NRF_802154_ACK_TIMEOUT_ENABLED || defined(DOXYGEN) /** * @brief Sets timeout for the ACK timeout feature. * * A timeout is notified by @ref nrf_802154_transmit_failed. * + * @note This function is available if @ref NRF_802154_ACK_TIMEOUT_ENABLED is enabled. + * * @param[in] time Timeout in microseconds (us). * A default value is defined in nrf_802154_config.h. */ @@ -1612,11 +1676,13 @@ void nrf_802154_stat_totals_get(nrf_802154_stat_totals_t * p_stat_totals); * @defgroup nrf_802154_ifs Inter-frame spacing feature * @{ */ -#if NRF_802154_IFS_ENABLED +#if NRF_802154_IFS_ENABLED || defined(DOXYGEN) /** * @brief Gets IFS operation mode. * + * @note This function is available if @ref NRF_802154_IFS_ENABLED is enabled. + * * @return Current IFS operation mode. Refer to @ref nrf_802154_ifs_mode_t for details. */ nrf_802154_ifs_mode_t nrf_802154_ifs_mode_get(void); @@ -1624,6 +1690,8 @@ nrf_802154_ifs_mode_t nrf_802154_ifs_mode_get(void); /** * @brief Sets IFS operation mode. * + * @note This function is available if @ref NRF_802154_IFS_ENABLED is enabled. + * * @param[in] mode IFS operation mode. Refer to @ref nrf_802154_ifs_mode_t for details. * * @retval true The update of IFS operation mode was successful. @@ -1634,6 +1702,8 @@ bool nrf_802154_ifs_mode_set(nrf_802154_ifs_mode_t mode); /** * @brief Gets Short IFS period in microseconds. * + * @note This function is available if @ref NRF_802154_IFS_ENABLED is enabled. + * * @return Current Short IFS period in microseconds. */ uint16_t nrf_802154_ifs_min_sifs_period_get(void); @@ -1641,6 +1711,8 @@ uint16_t nrf_802154_ifs_min_sifs_period_get(void); /** * @brief Sets Short IFS period in microseconds. * + * @note This function is available if @ref NRF_802154_IFS_ENABLED is enabled. + * * @param[in] period Short IFS period in microseconds. */ void nrf_802154_ifs_min_sifs_period_set(uint16_t period); @@ -1648,6 +1720,8 @@ void nrf_802154_ifs_min_sifs_period_set(uint16_t period); /** * @brief Gets Long IFS period in microseconds. * + * @note This function is available if @ref NRF_802154_IFS_ENABLED is enabled. + * * @return Current Long IFS period in microseconds. */ uint16_t nrf_802154_ifs_min_lifs_period_get(void); @@ -1655,6 +1729,8 @@ uint16_t nrf_802154_ifs_min_lifs_period_get(void); /** * @brief Sets Long IFS period in microseconds. * + * @note This function is available if @ref NRF_802154_IFS_ENABLED is enabled. + * * @param[in] period Long IFS period in microseconds. */ void nrf_802154_ifs_min_lifs_period_set(uint16_t period); @@ -1674,8 +1750,6 @@ void nrf_802154_ifs_min_lifs_period_set(uint16_t period); */ nrf_802154_capabilities_t nrf_802154_capabilities_get(void); -/** @} */ - /** * @} * @defgroup nrf_802154_security Radio driver MAC security feature. diff --git a/drivers/nrf_802154/driver/include/nrf_802154_config.h b/drivers/nrf_802154/driver/include/nrf_802154_config.h index 3682376..257c488 100644 --- a/drivers/nrf_802154/driver/include/nrf_802154_config.h +++ b/drivers/nrf_802154/driver/include/nrf_802154_config.h @@ -106,7 +106,6 @@ extern "C" { * In this case, the internal handling must be disabled. * */ - #ifndef NRF_802154_INTERNAL_RADIO_IRQ_HANDLING #define NRF_802154_INTERNAL_RADIO_IRQ_HANDLING 0 #endif @@ -120,7 +119,6 @@ extern "C" { * In this case, the internal handling must be disabled. * */ - #ifndef NRF_802154_INTERNAL_SWI_IRQ_HANDLING #define NRF_802154_INTERNAL_SWI_IRQ_HANDLING 1 #endif @@ -162,7 +160,7 @@ extern "C" { * When this flag is set, the RAW API is available for the MAC layer. It is recommended to use * the RAW API because it provides more optimized functions. * - * @note If the RAW API is not available for the MAC layer, only less optimized functions performing + * @note If the RAW API is not enabled for the MAC layer, only less optimized functions performing * copy are available. * */ @@ -231,8 +229,10 @@ extern "C" { * * If timestamps are to be added to the frames received. * Enabling this feature enables the functions @ref nrf_802154_received_timestamp_raw, - * @ref nrf_802154_received_timestamp, @ref nrf_802154_transmitted_timestamp_raw, and - * @ref nrf_802154_transmitted_timestamp, which add timestamps to the frames received. + * @ref nrf_802154_received_timestamp which add timestamps to the frames received. + * Enables also proper value of frame timestamp + * ( @c nrf_802154_transmit_done_metadata_t::data.transmitted.time ) passed as metadata to + * @ref nrf_802154_transmitted and @ref nrf_802154_transmitted_raw, * This option also enables timestamping in stats. * */ @@ -287,7 +287,7 @@ extern "C" { * (see IEEE 802.15.4-2015: 6.2.5.1). * * @note The minimum value of the backoff exponent may be changed from default by calling the - * @ref nrf_802154_pib_csmaca_min_be_set function. + * @ref nrf_802154_csma_ca_min_be_set function. * */ #ifdef NRF_802154_CSMA_CA_MIN_BE @@ -304,7 +304,7 @@ extern "C" { * (see IEEE 802.15.4-2015: 6.2.5.1). * * @note The maximum value of the backoff exponent may be changed from default by calling the - * @ref nrf_802154_pib_csmaca_max_be_set function. + * @ref nrf_802154_csma_ca_max_be_set function. * */ #ifdef NRF_802154_CSMA_CA_MAX_BE @@ -321,7 +321,7 @@ extern "C" { * a channel access failure. * * @note The maximum number of backoffs may be changed from default by calling the - * @ref nrf_802154_pib_csmaca_max_backoffs_set function. + * @ref nrf_802154_csma_ca_max_backoffs_set function. * */ #ifdef NRF_802154_CSMA_CA_MAX_CSMA_BACKOFFS @@ -376,7 +376,7 @@ extern "C" { #endif /** - * @def NRF_802154_ACK_TIMEOUT_DEFAULT_TIMEOUT + * @def NRF_802154_PRECISE_ACK_TIMEOUT_DEFAULT_TIMEOUT * * The default timeout in microseconds (us) for the precise ACK timeout feature. * @@ -435,7 +435,7 @@ extern "C" { /** * @} - * @defgroup nrf_802154_coex WiFi coexistence feature configuration + * @defgroup nrf_802154_config_coex WiFi coexistence feature configuration * @{ */ @@ -450,7 +450,7 @@ extern "C" { /** * @} - * @defgroup nrf_802154_stats Statistics configuration + * @defgroup nrf_802154_config_stats Statistics configuration * @{ */ @@ -482,7 +482,7 @@ extern "C" { /** * @} - * @defgroup nrf_802154_security Security configuration + * @defgroup nrf_802154_config_security Security configuration * @{ */ @@ -533,12 +533,26 @@ extern "C" { #define NRF_802154_IE_WRITER_ENABLED 1 #endif +/** + * @def NRF_802154_CARRIER_FUNCTIONS_ENABLED + * + * Enables functions used for test purposes: nrf_802154_continuous_carrier and + * nrf_802154_modulated_carrier + */ +#ifndef NRF_802154_CARRIER_FUNCTIONS_ENABLED +#define NRF_802154_CARRIER_FUNCTIONS_ENABLED 1 +#endif + +/** + *@} + **/ + +/** + *@} + **/ + #ifdef __cplusplus } #endif #endif // NRF_802154_CONFIG_H__ - -/** - *@} - **/ diff --git a/drivers/nrf_802154/driver/include/nrf_802154_const.h b/drivers/nrf_802154/driver/include/nrf_802154_const.h index 4050198..41505e9 100644 --- a/drivers/nrf_802154/driver/include/nrf_802154_const.h +++ b/drivers/nrf_802154/driver/include/nrf_802154_const.h @@ -40,8 +40,8 @@ #ifndef NRF_802154_CONST_H_ #define NRF_802154_CONST_H_ -#include -#include "nrf_802154_config.h" +#define RAW_LENGTH_OFFSET 0 ///< Byte containing the frame length in a raw frame. +#define RAW_PAYLOAD_OFFSET 1 ///< Offset of the frame payload in a raw frame #define ACK_HEADER_WITH_PENDING 0x12 ///< The first byte of an ACK frame containing a pending bit. #define ACK_HEADER_WITHOUT_PENDING 0x02 ///< The first byte of an ACK frame without a pending bit. @@ -173,6 +173,7 @@ #define TURNAROUND_TIME 192UL ///< RX-to-TX or TX-to-RX turnaround time (aTurnaroundTime), in microseconds (us). #define CCA_TIME 128UL ///< Time required to perform CCA detection (aCcaTime), in microseconds (us). +#define ACK_IFS TURNAROUND_TIME ///< Ack Inter Frame Spacing [us] - delay between last symbol of received frame and first symbol of transmitted Ack #define UNIT_BACKOFF_PERIOD (TURNAROUND_TIME + CCA_TIME) ///< Number of symbols in the basic time period used by CSMA-CA algorithm (aUnitBackoffPeriod), in (us). #define PHY_US_PER_SYMBOL 16 ///< Duration of a single symbol in microseconds (us). @@ -228,18 +229,10 @@ typedef enum REQ_ORIG_HIGHER_LAYER, REQ_ORIG_CORE, REQ_ORIG_RSCH, -#if NRF_802154_CSMA_CA_ENABLED REQ_ORIG_CSMA_CA, -#endif // NRF_802154_CSMA_CA_ENABLED -#if NRF_802154_ACK_TIMEOUT_ENABLED REQ_ORIG_ACK_TIMEOUT, -#endif // NRF_802154_ACK_TIMEOUT_ENABLED -#if NRF_802154_DELAYED_TRX_ENABLED REQ_ORIG_DELAYED_TRX, -#endif // NRF_802154_DELAYED_TRX_ENABLED -#if NRF_802154_IFS_ENABLED REQ_ORIG_IFS, -#endif // NRF_802154_IFS_ENABLED } req_originator_t; #endif // NRF_802154_CONST_H_ diff --git a/drivers/nrf_802154/driver/include/nrf_802154_types.h b/drivers/nrf_802154/driver/include/nrf_802154_types.h index d98b89f..cff5bb9 100644 --- a/drivers/nrf_802154/driver/include/nrf_802154_types.h +++ b/drivers/nrf_802154/driver/include/nrf_802154_types.h @@ -170,7 +170,7 @@ typedef uint8_t nrf_802154_ack_data_t; * @brief Methods of source address matching. * * You can use one of the following methods that can be set during the initialization phase - * by calling @ref nrf_802154_src_matching_method: + * by calling @ref nrf_802154_src_addr_matching_method_set : * - For Thread: @ref NRF_802154_SRC_ADDR_MATCH_THREAD -- The pending bit is set only for the addresses found in the list. * - For Zigbee: @ref NRF_802154_SRC_ADDR_MATCH_ZIGBEE -- The pending bit is cleared only for the short addresses found in the list.\n * This method does not set pending bit in non-command and non-data-request frames. @@ -366,12 +366,6 @@ typedef struct bool use_global_frame_counter; // !< Whether to use the global frame counter instead of the one defined in this structure. } nrf_802154_key_t; -/** - * @brief Function pointer used for notifying about transmission failure. - */ -typedef void (* nrf_802154_transmit_failed_notification_t)(uint8_t * p_frame, - nrf_802154_tx_error_t error); - /** * @brief Structure with frame properties associated with the transmission operation. * @@ -466,6 +460,14 @@ typedef struct // until its preconditions are met. } nrf_802154_transmit_params_t; +/** + * @brief Function pointer used for notifying about transmission failure. + */ +typedef void (* nrf_802154_transmit_failed_notification_t)( + uint8_t * p_frame, + nrf_802154_tx_error_t error, + const nrf_802154_transmit_done_metadata_t * p_meta); + /** *@} **/ diff --git a/drivers/nrf_802154/driver/include/platform/nrf_802154_random.h b/drivers/nrf_802154/driver/include/platform/nrf_802154_random.h index 39d5fd7..552dec7 100644 --- a/drivers/nrf_802154/driver/include/platform/nrf_802154_random.h +++ b/drivers/nrf_802154/driver/include/platform/nrf_802154_random.h @@ -50,7 +50,7 @@ extern "C" { /** * @defgroup nrf_802154_random Random Abstraction Layer for the 802.15.4 driver * @{ - * @ingroup nrf_802154_random + * @ingroup nrf_802154 * @brief The pseudo-random number generator Abstraction Layer interface for the 802.15.4 driver. * * The Random Abstraction Layer is an abstraction layer of a pseudo-random number generator that is diff --git a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_data.h b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_data.h index f748388..b68ef5e 100644 --- a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_data.h +++ b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_data.h @@ -115,7 +115,7 @@ void nrf_802154_ack_data_reset(bool extended, nrf_802154_ack_data_t data_type); * * When calling @ref nrf_802154_ack_data_pending_bit_should_be_set, one of several algorithms * for source address matching will be chosen. To ensure a specific algorithm is selected, - * call this function before @ref rf_802154_ack_data_pending_bit_should_be_set. + * call this function before @ref nrf_802154_ack_data_pending_bit_should_be_set. * * @param[in] match_method Source matching method to be used. */ diff --git a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_generator.c b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_generator.c index 8724ab3..003a274 100644 --- a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_generator.c +++ b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_generator.c @@ -41,7 +41,6 @@ #include "nrf_802154_ack_generator.h" #include -#include #include "nrf_802154_const.h" #include "nrf_802154_enh_ack_generator.h" @@ -78,6 +77,13 @@ void nrf_802154_ack_generator_init(void) nrf_802154_enh_ack_generator_init(); } +void nrf_802154_ack_generator_reset(void) +{ + // Both generators are reset to enable sending both Imm-Ack and Enh-Ack. + nrf_802154_imm_ack_generator_reset(); + nrf_802154_enh_ack_generator_reset(); +} + uint8_t * nrf_802154_ack_generator_create(const nrf_802154_frame_parser_data_t * p_frame_data) { // This function should not be called if ACK is not requested. diff --git a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_generator.h b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_generator.h index cfb5b70..c9b9ae1 100644 --- a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_generator.h +++ b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_ack_generator.h @@ -47,13 +47,26 @@ /** Initializes the ACK generator module. */ void nrf_802154_ack_generator_init(void); -/** Creates an ACK in response to the provided frame and inserts it into a radio buffer. +/** @brief Resets the ACK generator module. + * + * @note This function should be called for every received frame to be acknowledged before + * @ref nrf_802154_ack_generator_create is called for that frame. + */ +void nrf_802154_ack_generator_reset(void); + +/** @brief Creates an ACK in response to the provided frame and inserts it into a radio buffer. + * + * @note Only those contents of the frame being acknowledged marked by @p p_frame_data as valid + * are used for ACK generation. If any data necessary to generate an ACK is missing or marked as + * invalid by @p p_frame_data, this function returns NULL. Once more data becomes available and valid, + * this function can be called again and the generation will be continued. That allows for + * generating ACK iteratively as data to be acknowledged is being received. * * @param [in] p_frame_data Pointer to the parser data of the frame for which an Ack * will be generated. * * @returns Either pointer to a constant buffer that contains PHR and PSDU - * of the created ACK frame, or NULL in case of an invalid frame. + * of the created ACK frame, or NULL when the response cannot be created. */ uint8_t * nrf_802154_ack_generator_create( const nrf_802154_frame_parser_data_t * p_frame_data); diff --git a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_enh_ack_generator.c b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_enh_ack_generator.c index 469b8bc..187e1a3 100644 --- a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_enh_ack_generator.c +++ b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_enh_ack_generator.c @@ -54,12 +54,29 @@ #define ENH_ACK_MAX_SIZE MAX_PACKET_SIZE -static uint8_t m_ack_data[ENH_ACK_MAX_SIZE + PHR_SIZE]; - -static void ack_buffer_clear(nrf_802154_frame_parser_data_t * p_ack_data) +typedef enum { - memset(&m_ack_data[PHR_OFFSET], 0U, PHR_SIZE + FCF_SIZE); - (void)nrf_802154_frame_parser_data_init(m_ack_data, 0U, PARSE_LEVEL_NONE, p_ack_data); + ACK_STATE_RESET, + ACK_STATE_INVALID, + ACK_STATE_PROCESSING, + ACK_STATE_COMPLETE, +} ack_state_t; + +static ack_state_t m_ack_state; + +static uint8_t m_ack[ENH_ACK_MAX_SIZE + PHR_SIZE]; +static nrf_802154_frame_parser_data_t m_ack_data; +static const uint8_t * mp_ie_data; +static uint8_t m_ie_data_len; + +static void ack_state_set(ack_state_t state_to_set) +{ + m_ack_state = state_to_set; +} + +static inline ack_state_t ack_state_get(void) +{ + return m_ack_state; } static uint8_t sequence_number_set(const nrf_802154_frame_parser_data_t * p_frame_data) @@ -68,7 +85,7 @@ static uint8_t sequence_number_set(const nrf_802154_frame_parser_data_t * p_fram if (p_frame_dsn != NULL) { - m_ack_data[DSN_OFFSET] = *p_frame_dsn; + m_ack[DSN_OFFSET] = *p_frame_dsn; return DSN_SIZE; } @@ -82,14 +99,14 @@ static uint8_t sequence_number_set(const nrf_802154_frame_parser_data_t * p_fram static void fcf_frame_type_set(void) { - m_ack_data[FRAME_TYPE_OFFSET] |= FRAME_TYPE_ACK; + m_ack[FRAME_TYPE_OFFSET] |= FRAME_TYPE_ACK; } static void fcf_security_enabled_set(const nrf_802154_frame_parser_data_t * p_frame_data) { if (nrf_802154_frame_parser_security_enabled_bit_is_set(p_frame_data)) { - m_ack_data[SECURITY_ENABLED_OFFSET] |= SECURITY_ENABLED_BIT; + m_ack[SECURITY_ENABLED_OFFSET] |= SECURITY_ENABLED_BIT; } } @@ -97,7 +114,7 @@ static void fcf_frame_pending_set(const nrf_802154_frame_parser_data_t * p_frame { if (nrf_802154_ack_data_pending_bit_should_be_set(p_frame_data)) { - m_ack_data[FRAME_PENDING_OFFSET] |= FRAME_PENDING_BIT; + m_ack[FRAME_PENDING_OFFSET] |= FRAME_PENDING_BIT; } } @@ -105,7 +122,7 @@ static void fcf_panid_compression_set(const nrf_802154_frame_parser_data_t * p_f { if (nrf_802154_frame_parser_panid_compression_is_set(p_frame_data)) { - m_ack_data[PAN_ID_COMPR_OFFSET] |= PAN_ID_COMPR_MASK; + m_ack[PAN_ID_COMPR_OFFSET] |= PAN_ID_COMPR_MASK; } } @@ -113,7 +130,7 @@ static void fcf_sequence_number_suppression_set(const nrf_802154_frame_parser_da { if (nrf_802154_frame_parser_dsn_suppress_bit_is_set(p_frame_data)) { - m_ack_data[DSN_SUPPRESS_OFFSET] |= DSN_SUPPRESS_BIT; + m_ack[DSN_SUPPRESS_OFFSET] |= DSN_SUPPRESS_BIT; } } @@ -121,7 +138,7 @@ static void fcf_ie_present_set(bool ie_present) { if (ie_present) { - m_ack_data[IE_PRESENT_OFFSET] |= IE_PRESENT_BIT; + m_ack[IE_PRESENT_OFFSET] |= IE_PRESENT_BIT; } } @@ -129,40 +146,51 @@ static void fcf_dst_addressing_mode_set(const nrf_802154_frame_parser_data_t * p { if (nrf_802154_frame_parser_src_addr_is_extended(p_frame_data)) { - m_ack_data[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_EXTENDED; + m_ack[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_EXTENDED; } else if (nrf_802154_frame_parser_src_addr_is_short(p_frame_data)) { - m_ack_data[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_SHORT; + m_ack[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_SHORT; } else { - m_ack_data[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_NONE; + m_ack[DEST_ADDR_TYPE_OFFSET] |= DEST_ADDR_TYPE_NONE; } } static void fcf_src_addressing_mode_set(void) { - m_ack_data[SRC_ADDR_TYPE_OFFSET] |= SRC_ADDR_TYPE_NONE; + m_ack[SRC_ADDR_TYPE_OFFSET] |= SRC_ADDR_TYPE_NONE; } static void fcf_frame_version_set(void) { - m_ack_data[FRAME_VERSION_OFFSET] |= FRAME_VERSION_2; + m_ack[FRAME_VERSION_OFFSET] |= FRAME_VERSION_2; } static uint8_t frame_control_set(const nrf_802154_frame_parser_data_t * p_frame_data, bool ie_present) { - fcf_frame_type_set(); - fcf_security_enabled_set(p_frame_data); - fcf_frame_pending_set(p_frame_data); - fcf_panid_compression_set(p_frame_data); - fcf_sequence_number_suppression_set(p_frame_data); - fcf_ie_present_set(ie_present); - fcf_dst_addressing_mode_set(p_frame_data); - fcf_frame_version_set(); - fcf_src_addressing_mode_set(); + nrf_802154_frame_parser_level_t level = nrf_802154_frame_parser_parse_level_get(p_frame_data); + + if (level >= PARSE_LEVEL_FCF_OFFSETS) + { + fcf_frame_type_set(); + fcf_security_enabled_set(p_frame_data); + fcf_panid_compression_set(p_frame_data); + fcf_sequence_number_suppression_set(p_frame_data); + fcf_ie_present_set(ie_present); + fcf_dst_addressing_mode_set(p_frame_data); + fcf_frame_version_set(); + fcf_src_addressing_mode_set(); + } + + if (level >= PARSE_LEVEL_FULL) + { + // As some frame pending bit setting algorithms depend on MAC payload, + // the entire frame must be known to set this field. + fcf_frame_pending_set(p_frame_data); + } return FCF_SIZE; } @@ -440,6 +468,179 @@ static bool encryption_prepare(const nrf_802154_frame_parser_data_t * p_ack_data #endif // NRF_802154_ENCRYPTION_ENABLED } +/*************************************************************************************************** + * @section Enhanced ACK generation + **************************************************************************************************/ + +static void fcf_process(const nrf_802154_frame_parser_data_t * p_frame_data, + uint8_t * p_bytes_written) +{ + // Set Frame Control field bits. + // Some of them might require correction when higher parse level is available + *p_bytes_written = frame_control_set(p_frame_data, false); + m_ack[PHR_OFFSET] += *p_bytes_written; + + bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data, + m_ack[PHR_OFFSET] + PHR_SIZE, + PARSE_LEVEL_FCF_OFFSETS); + + assert(result); + (void)result; +} + +static void dst_addr_process(const nrf_802154_frame_parser_data_t * p_frame_data, + uint8_t * p_bytes_written) +{ + // Set valid sequence number in ACK frame. + *p_bytes_written = sequence_number_set(p_frame_data); + m_ack[PHR_OFFSET] += *p_bytes_written; + + // Set destination address and PAN ID. + *p_bytes_written = destination_set(p_frame_data, &m_ack_data); + m_ack[PHR_OFFSET] += *p_bytes_written; + + bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data, + m_ack[PHR_OFFSET] + PHR_SIZE, + PARSE_LEVEL_DST_ADDRESSING_END); + + assert(result); + (void)result; +} + +static void addr_end_process(const nrf_802154_frame_parser_data_t * p_frame_data) +{ + // Set source address and PAN ID. + source_set(); + + // Having the frame's source address, presence of IEs can be determined. + // coverity[unchecked_value] + mp_ie_data = nrf_802154_ack_data_ie_get( + nrf_802154_frame_parser_src_addr_get(p_frame_data), + nrf_802154_frame_parser_src_addr_is_extended(p_frame_data), + &m_ie_data_len); + + // Update the IE present bit in Frame Control field knowing if IEs should be present. + fcf_ie_present_set(mp_ie_data != NULL); + + bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data, + m_ack[PHR_OFFSET] + PHR_SIZE, + PARSE_LEVEL_ADDRESSING_END); + + assert(result); + (void)result; +} + +static bool aux_sec_hdr_process(const nrf_802154_frame_parser_data_t * p_frame_data, + uint8_t * p_bytes_written) +{ + if (security_header_set(p_frame_data, &m_ack_data, p_bytes_written) == false) + { + return false; + } + + m_ack[PHR_OFFSET] += *p_bytes_written; + + bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data, + m_ack[PHR_OFFSET] + PHR_SIZE, + PARSE_LEVEL_AUX_SEC_HDR_END); + + assert(result); + (void)result; + + return true; +} + +static void ie_process(const nrf_802154_frame_parser_data_t * p_frame_data, + uint8_t * p_bytes_written) +{ + // Set IE header. + ie_header_set(mp_ie_data, m_ie_data_len, &m_ack_data); + m_ack[PHR_OFFSET] += m_ie_data_len; + + // Terminate the IE header if needed. + *p_bytes_written = ie_header_terminate(mp_ie_data, m_ie_data_len, &m_ack_data); + m_ack[PHR_OFFSET] += *p_bytes_written + FCS_SIZE; + + bool result = nrf_802154_frame_parser_valid_data_extend(&m_ack_data, + m_ack[PHR_OFFSET] + PHR_SIZE, + PARSE_LEVEL_FULL); + + assert(result); + (void)result; +} + +static bool encryption_process(void) +{ + return encryption_prepare(&m_ack_data); +} + +static uint8_t * ack_process( + const nrf_802154_frame_parser_data_t * p_frame_data, + bool * p_processing_done) +{ + uint8_t bytes_written = 0U; + + nrf_802154_frame_parser_level_t frame_parse_level = nrf_802154_frame_parser_parse_level_get( + p_frame_data); + nrf_802154_frame_parser_level_t ack_parse_level = nrf_802154_frame_parser_parse_level_get( + &m_ack_data); + + *p_processing_done = false; + + if ((frame_parse_level >= PARSE_LEVEL_FCF_OFFSETS) && + (ack_parse_level < PARSE_LEVEL_FCF_OFFSETS)) + { + fcf_process(p_frame_data, &bytes_written); + } + + if ((frame_parse_level >= PARSE_LEVEL_DST_ADDRESSING_END) && + (ack_parse_level < PARSE_LEVEL_DST_ADDRESSING_END)) + { + dst_addr_process(p_frame_data, &bytes_written); + } + + if ((frame_parse_level >= PARSE_LEVEL_ADDRESSING_END) && + (ack_parse_level < PARSE_LEVEL_ADDRESSING_END)) + { + addr_end_process(p_frame_data); + } + + if ((frame_parse_level >= PARSE_LEVEL_AUX_SEC_HDR_END) && + (ack_parse_level < PARSE_LEVEL_AUX_SEC_HDR_END)) + { + if (!aux_sec_hdr_process(p_frame_data, &bytes_written)) + { + // Failure to set auxiliary security header, the ACK cannot be created. Exit immediately + *p_processing_done = true; + return NULL; + } + + ie_process(p_frame_data, &bytes_written); + } + + if (frame_parse_level == PARSE_LEVEL_FULL) + { + // With the entire frame validated update the Frame Pending bit in Frame Control field + fcf_frame_pending_set(p_frame_data); + + if (encryption_process()) + { + // Success. Processing completed + *p_processing_done = true; + return m_ack; + } + else + { + // Failure to prepare encryption even though it's required, the ACK cannot be created. + // Exit immediately + *p_processing_done = true; + return NULL; + } + } + + return NULL; +} + /*************************************************************************************************** * @section Public API implementation **************************************************************************************************/ @@ -449,89 +650,45 @@ void nrf_802154_enh_ack_generator_init(void) // Intentionally empty. } +void nrf_802154_enh_ack_generator_reset(void) +{ + memset(m_ack, 0U, sizeof(m_ack)); + (void)nrf_802154_frame_parser_data_init(m_ack, 0U, PARSE_LEVEL_NONE, &m_ack_data); + mp_ie_data = 0U; + m_ie_data_len = 0U; + m_ack_state = ACK_STATE_RESET; +} + uint8_t * nrf_802154_enh_ack_generator_create( const nrf_802154_frame_parser_data_t * p_frame_data) { - nrf_802154_frame_parser_data_t ack_data; - - bool result; - uint8_t bytes_written = 0U; - uint8_t ie_data_len = 0U; - - // coverity[unchecked_value] - const uint8_t * p_ie_data = nrf_802154_ack_data_ie_get( - nrf_802154_frame_parser_src_addr_get(p_frame_data), - nrf_802154_frame_parser_src_addr_is_extended(p_frame_data), - &ie_data_len); - - // Clear previously created ACK. - ack_buffer_clear(&ack_data); - - // Set Frame Control field bits. - bytes_written = frame_control_set(p_frame_data, p_ie_data != NULL); - m_ack_data[PHR_OFFSET] += bytes_written; - - result = nrf_802154_frame_parser_valid_data_extend(&ack_data, - m_ack_data[PHR_OFFSET] + PHR_SIZE, - PARSE_LEVEL_FCF_OFFSETS); - assert(result); - (void)result; - - // Set valid sequence number in ACK frame. - bytes_written = sequence_number_set(p_frame_data); - m_ack_data[PHR_OFFSET] += bytes_written; - - // Set destination address and PAN ID. - bytes_written = destination_set(p_frame_data, &ack_data); - m_ack_data[PHR_OFFSET] += bytes_written; - - // Set source address and PAN ID. - source_set(); - - if (security_header_set(p_frame_data, &ack_data, &bytes_written) == false) + switch (ack_state_get()) { - // Failure to set auxiliary security header: The ACK cannot be created. - ack_buffer_clear(&ack_data); - return NULL; + case ACK_STATE_RESET: + ack_state_set(ACK_STATE_PROCESSING); + // Fallthrough + + case ACK_STATE_PROCESSING: + { + bool processing_done; + uint8_t * p_ack = ack_process(p_frame_data, &processing_done); + + if (processing_done) + { + ack_state_set(p_ack ? ACK_STATE_COMPLETE : ACK_STATE_INVALID); + } + + return processing_done ? p_ack : NULL; + } + + case ACK_STATE_INVALID: + return NULL; + + case ACK_STATE_COMPLETE: + return m_ack; + + default: + assert(false); + return NULL; } - - m_ack_data[PHR_OFFSET] += bytes_written; - - result = nrf_802154_frame_parser_valid_data_extend(&ack_data, - m_ack_data[PHR_OFFSET] + PHR_SIZE, - PARSE_LEVEL_AUX_SEC_HDR_END); - assert(result); - (void)result; - - // Set IE header. - ie_header_set(p_ie_data, ie_data_len, &ack_data); - m_ack_data[PHR_OFFSET] += ie_data_len; - - // Terminate the IE header if needed. - bytes_written = ie_header_terminate(p_ie_data, ie_data_len, &ack_data); - m_ack_data[PHR_OFFSET] += bytes_written + FCS_SIZE; - - result = nrf_802154_frame_parser_valid_data_extend(&ack_data, - m_ack_data[PHR_OFFSET] + PHR_SIZE, - PARSE_LEVEL_FULL); - assert(result); - (void)result; - - // Prepare encryption. - if (!encryption_prepare(&ack_data)) - { - // Failure to prepare encryption even though it's required. The ACK cannot be created. - ack_buffer_clear(&ack_data); - return NULL; - } - - return m_ack_data; } - -#ifdef TEST -void nrf_802154_enh_ack_generator_module_reset(void) -{ - memset(m_ack_data, 0U, sizeof(m_ack_data)); -} - -#endif // TEST diff --git a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_enh_ack_generator.h b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_enh_ack_generator.h index 5931885..c6b9ce1 100644 --- a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_enh_ack_generator.h +++ b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_enh_ack_generator.h @@ -48,9 +48,20 @@ /** Initializes the Enhanced ACK generator module. */ void nrf_802154_enh_ack_generator_init(void); -/** Creates an Enhanced ACK in response to the provided frame. +/** @brief Resets the Enhanced ACK generator module. * - * This function creates an Enhanced ACK frame and inserts it into a radio buffer. + * @note This function should be called for every received frame to be acknowledged before + * @ref nrf_802154_enh_ack_generator_create is called for that frame. + */ +void nrf_802154_enh_ack_generator_reset(void); + +/** @brief Creates an Enhanced ACK in response to the provided frame. + * + * @note Only those contents of the frame being acknowledged marked by @p p_frame_data as valid + * are used for ACK generation. If any data necessary to generate an ACK is missing or marked as + * invalid by @p p_frame_data, this function returns NULL. Once more data becomes available and valid, + * this function can be called again and the generation will be continued. That allows for + * generating ACK iteratively as data to be acknowledged is being received. * * @param [in] p_frame_data Pointer to the parser data of the frame for which an Ack * will be generated. diff --git a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_imm_ack_generator.c b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_imm_ack_generator.c index 9365c22..1cb2154 100644 --- a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_imm_ack_generator.c +++ b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_imm_ack_generator.c @@ -57,9 +57,20 @@ void nrf_802154_imm_ack_generator_init(void) memcpy(m_ack_data, ack_data, sizeof(ack_data)); } +void nrf_802154_imm_ack_generator_reset(void) +{ + // Intentionally empty +} + uint8_t * nrf_802154_imm_ack_generator_create( const nrf_802154_frame_parser_data_t * p_frame_data) { + if (nrf_802154_frame_parser_parse_level_get(p_frame_data) < PARSE_LEVEL_FULL) + { + // The entire frame being acknowledged is necessary to correctly generate Ack + return NULL; + } + const uint8_t * frame_dsn = nrf_802154_frame_parser_dsn_get(p_frame_data); if (frame_dsn == NULL) diff --git a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_imm_ack_generator.h b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_imm_ack_generator.h index 3963710..d22447c 100644 --- a/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_imm_ack_generator.h +++ b/drivers/nrf_802154/driver/src/mac_features/ack_generator/nrf_802154_imm_ack_generator.h @@ -49,15 +49,27 @@ /** Initializes the Immediate ACK generator module. */ void nrf_802154_imm_ack_generator_init(void); -/** Creates an Immediate ACK in response to the provided frame. +/** @brief Resets the Immediate ACK generator module. * - * This function creates an Immediate ACK frame and inserts it into a radio buffer. + * @note This function should be called for every received frame to be acknowledged before + * @ref nrf_802154_imm_ack_generator_create is called for that frame. + */ +void nrf_802154_imm_ack_generator_reset(void); + +/** @brief Creates an Immediate ACK in response to the provided frame. + * + * @note Only those contents of the frame being acknowledged marked by @p p_frame_data as valid + * are used for ACK generation. If any data necessary to generate an ACK is missing or marked as + * invalid by @p p_frame_data, this function returns NULL. Once more data becomes available and valid, + * this function can be called again and the generation will be continued. That allows for + * generating ACK iteratively as data to be acknowledged is being received. * * @param [in] p_frame_data Pointer to the parser data of the frame for which an Ack * will be generated. * - * @returns Pointer to a constant buffer that contains PHR and PSDU of the created - * Immediate ACK frame. + * @returns Either pointer to a constant buffer that contains PHR and PSDU + * of the created Immediate ACK frame, or NULL when the response cannot be + * created. */ uint8_t * nrf_802154_imm_ack_generator_create( const nrf_802154_frame_parser_data_t * p_frame_data); diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ack_timeout.h b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ack_timeout.h index 1539ef2..13e2ae3 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ack_timeout.h +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ack_timeout.h @@ -42,7 +42,7 @@ #include "nrf_802154_types.h" /** - * @defgroup nrf_802154_csma_ca 802.15.4 driver ACK timeout support + * @defgroup nrf_802154_ack_timeout 802.15.4 driver ACK timeout support * @{ * @ingroup nrf_802154 * @brief ACK timeout feature. diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_csma_ca.c b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_csma_ca.c index d7ddf1a..fd74693 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_csma_ca.c +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_csma_ca.c @@ -45,17 +45,14 @@ #include #include #include -#include #include "nrf_802154_config.h" #include "nrf_802154_const.h" #include "nrf_802154_debug.h" #include "nrf_802154_notification.h" #include "nrf_802154_pib.h" -#include "nrf_802154_procedures_duration.h" #include "nrf_802154_request.h" #include "nrf_802154_stats.h" -#include "mac_features/nrf_802154_frame_parser.h" #include "platform/nrf_802154_random.h" #include "rsch/nrf_802154_rsch.h" #include "timer/nrf_802154_timer_sched.h" @@ -145,7 +142,12 @@ static void notify_busy_channel(bool result) // the comparison uses `greater or equal` instead of `greater than`. if (!result && (m_nb >= nrf_802154_pib_csmaca_max_backoffs_get())) { - nrf_802154_notify_transmit_failed(mp_data, NRF_802154_TX_ERROR_BUSY_CHANNEL); + // core rejected attempt, use my current frame_props + nrf_802154_transmit_done_metadata_t metadata = {}; + + metadata.frame_props = m_data_props; + + nrf_802154_notify_transmit_failed(mp_data, NRF_802154_TX_ERROR_BUSY_CHANNEL, &metadata); } nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.c b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.c index 173a7f8..e23f904 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.c +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.c @@ -73,10 +73,10 @@ */ typedef enum { - DELAYED_TRX_OP_STATE_STOPPED, ///< Delayed operation stopped. - DELAYED_TRX_OP_STATE_PENDING, ///< Delayed operation scheduled and waiting for timeslot. - DELAYED_TRX_OP_STATE_ONGOING, ///< Delayed operation ongoing (during timeslot). - DELAYED_TRX_OP_STATE_NB ///< Number of delayed operation states. + DELAYED_TRX_OP_STATE_STOPPED = (1 << 0), ///< Delayed operation stopped. + DELAYED_TRX_OP_STATE_PENDING = (1 << 1), ///< Delayed operation scheduled and waiting for timeslot. + DELAYED_TRX_OP_STATE_ONGOING = (1 << 2), ///< Delayed operation ongoing (during timeslot). + DELAYED_TRX_OP_STATE_ALLOWED_MSK = ((1 << 3) - 1) ///< Mask of allowed delayed operation states. } delayed_trx_op_state_t; /** @@ -313,18 +313,18 @@ static dly_op_data_t * dly_rx_data_atomically_pop(void) /** * Set state of a delayed operation. * - * @param[in] p_dly_op_data Data of the delayed operation. - * @param[in] expected_state Expected delayed operation state prior state transition. - * @param[in] new_state Delayed operation state to enter. + * @param[in] p_dly_op_data Data of the delayed operation. + * @param[in] expected_state_mask Mask of expected delayed operation states prior state transition. + * @param[in] new_state Delayed operation state to enter. * * @retval true Successfully set the new state. * @retval false Failed to set the new state. */ static bool dly_op_state_set(dly_op_data_t * p_dly_op_data, - delayed_trx_op_state_t expected_state, + uint32_t expected_state_mask, delayed_trx_op_state_t new_state) { - assert(new_state < DELAYED_TRX_OP_STATE_NB); + assert(new_state & DELAYED_TRX_OP_STATE_ALLOWED_MSK); switch (p_dly_op_data->op) { @@ -337,7 +337,7 @@ static bool dly_op_state_set(dly_op_data_t * p_dly_op_data, { current_state = (delayed_trx_op_state_t)__LDREXB((uint8_t *)&p_dly_op_data->state); - if (current_state != expected_state) + if (0 == (current_state & expected_state_mask)) { __CLREX(); return false; @@ -434,8 +434,15 @@ static void notify_rx_timeout(void * p_context) DELAYED_TRX_OP_STATE_ONGOING, DELAYED_TRX_OP_STATE_STOPPED)) { - nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_DELAYED_TIMEOUT, - p_dly_op_data->id); + bool notified = nrf_802154_notify_receive_failed( + NRF_802154_RX_ERROR_DELAYED_TIMEOUT, + p_dly_op_data->id, + false); + + // It should always be possible to notify DRX result + assert(notified); + (void)notified; + dly_ts_slot_release(p_dly_op_data); } @@ -467,8 +474,13 @@ static void dly_tx_result_notify(bool result) if (!result) { + // core rejected attempt, use my current frame_props + nrf_802154_transmit_done_metadata_t metadata = {}; + + metadata.frame_props = p_dly_op_data->tx.params.frame_props; nrf_802154_notify_transmit_failed(p_dly_op_data->tx.p_data, - NRF_802154_TX_ERROR_TIMESLOT_DENIED); + NRF_802154_TX_ERROR_TIMESLOT_DENIED, + &metadata); } dly_ts_slot_release(p_dly_op_data); @@ -509,8 +521,14 @@ static void dly_rx_result_notify(bool result) assert(state_set); (void)state_set; - nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_DELAYED_ABORTED, - p_parallel_ongoing_dly_op_data->id); + bool notified = nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_DELAYED_ABORTED, + p_parallel_ongoing_dly_op_data->id, + false); + + // It should always be possible to notify DRX result + assert(notified); + (void)notified; + dly_ts_slot_release(p_parallel_ongoing_dly_op_data); } @@ -542,8 +560,15 @@ static void dly_rx_result_notify(bool result) assert(state_set); (void)state_set; - nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED, - p_dly_op_data->id); + bool notified = nrf_802154_notify_receive_failed( + NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED, + p_dly_op_data->id, + false); + + // It should always be possible to notify DRX result + assert(notified); + (void)notified; + dly_ts_slot_release(p_dly_op_data); } @@ -693,12 +718,14 @@ void nrf_802154_delayed_trx_init(void) for (uint32_t i = 0; i < sizeof(m_dly_rx_data) / sizeof(m_dly_rx_data[0]); i++) { - m_dly_rx_data[i].id = NRF_802154_RESERVED_INVALID_ID; + m_dly_rx_data[i].state = DELAYED_TRX_OP_STATE_STOPPED; + m_dly_rx_data[i].id = NRF_802154_RESERVED_INVALID_ID; } for (uint32_t i = 0; i < sizeof(m_dly_tx_data) / sizeof(m_dly_tx_data[0]); i++) { - m_dly_tx_data[i].id = NRF_802154_RESERVED_INVALID_ID; + m_dly_tx_data[i].state = DELAYED_TRX_OP_STATE_STOPPED; + m_dly_tx_data[i].id = NRF_802154_RESERVED_INVALID_ID; } } @@ -822,10 +849,13 @@ bool nrf_802154_delayed_trx_receive_cancel(uint32_t id) nrf_802154_timer_sched_remove(&p_dly_op_data->rx.timeout_timer, &was_running); - p_dly_op_data->state = DELAYED_TRX_OP_STATE_STOPPED; - p_dly_op_data->id = NRF_802154_RESERVED_INVALID_ID; + bool stopped = dly_op_state_set(p_dly_op_data, + DELAYED_TRX_OP_STATE_PENDING | DELAYED_TRX_OP_STATE_ONGOING, + DELAYED_TRX_OP_STATE_STOPPED); - result = result || was_running; + p_dly_op_data->id = NRF_802154_RESERVED_INVALID_ID; + + result = (result || was_running) && stopped; return result; } @@ -843,8 +873,15 @@ bool nrf_802154_delayed_trx_abort(nrf_802154_term_t term_lvl, req_originator_t r DELAYED_TRX_OP_STATE_ONGOING, DELAYED_TRX_OP_STATE_STOPPED)) { - nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_DELAYED_ABORTED, - p_dly_op_data->id); + bool notified = nrf_802154_notify_receive_failed( + NRF_802154_RX_ERROR_DELAYED_ABORTED, + p_dly_op_data->id, + false); + + // It should always be possible to notify DRX result + assert(notified); + (void)notified; + dly_ts_slot_release(p_dly_op_data); } diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.h b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.h index ec120ff..244b856 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.h +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_delayed_trx.h @@ -39,6 +39,7 @@ #include #include "nrf_802154_const.h" +#include "nrf_802154_config.h" #include "nrf_802154_types.h" #if NRF_802154_DELAYED_TRX_ENABLED diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_filter.c b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_filter.c index a3f40b9..31cdedf 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_filter.c +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_filter.c @@ -412,12 +412,10 @@ static nrf_802154_rx_error_t dst_addr_check(const nrf_802154_frame_parser_data_t } } - if (p_dst_addr == NULL) - { - return NRF_802154_RX_ERROR_INVALID_DEST_ADDR; - } + uint8_t dst_addr_size = + p_dst_addr ? nrf_802154_frame_parser_dst_addr_size_get(p_frame_data) : 0U; - switch (nrf_802154_frame_parser_dst_addr_size_get(p_frame_data)) + switch (dst_addr_size) { case SHORT_ADDRESS_SIZE: return dst_short_addr_check(p_dst_addr) ? NRF_802154_RX_ERROR_NONE : diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_frame_parser.c b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_frame_parser.c index 2cc9812..d1b1131 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_frame_parser.c +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_frame_parser.c @@ -354,9 +354,8 @@ static bool full_parse(nrf_802154_frame_parser_data_t * p_parser_data) uint8_t offset = p_parser_data->helper.aux_sec_hdr_end_offset; uint8_t psdu_length = nrf_802154_frame_parser_frame_length_get(p_parser_data); const uint8_t * p_ie_header; - const uint8_t * p_mfr; + const uint8_t * p_end_addr; const uint8_t * p_iterator; - const uint8_t * p_ie_end_addr; if (((psdu_length + PHR_SIZE) != p_parser_data->valid_data_len) || (psdu_length > MAX_PACKET_SIZE)) @@ -369,25 +368,36 @@ static bool full_parse(nrf_802154_frame_parser_data_t * p_parser_data) p_parser_data->mhr.header_ie_offset = offset; p_ie_header = &p_parser_data->p_frame[offset]; - p_mfr = nrf_802154_frame_parser_mfr_get(p_parser_data); + p_end_addr = nrf_802154_frame_parser_mfr_get(p_parser_data) - mic_size_get(p_parser_data); p_iterator = nrf_802154_frame_parser_header_ie_iterator_begin(p_ie_header); - while (nrf_802154_frame_parser_ie_iterator_end(p_iterator, p_mfr) == false) + while (!nrf_802154_frame_parser_ie_iterator_end(p_iterator, p_end_addr)) { - p_ie_end_addr = nrf_802154_frame_parser_ie_content_address_get(p_iterator) + - nrf_802154_frame_parser_ie_length_get(p_iterator); + p_iterator = nrf_802154_frame_parser_ie_iterator_next(p_iterator); - // Boundary check - if (p_ie_end_addr > p_mfr) + if (p_iterator > p_end_addr) { + // Boundary check failed return false; } - - p_iterator = nrf_802154_frame_parser_ie_iterator_next(p_iterator); + else if (p_iterator == p_end_addr) + { + // End of frame; IE header has no termination. + offset = p_iterator - p_parser_data->p_frame; + break; + } + else if (nrf_802154_frame_parser_ie_iterator_end(p_iterator, p_end_addr)) + { + // End of IE header; termination reached. + offset = nrf_802154_frame_parser_ie_content_address_get(p_iterator) - + p_parser_data->p_frame; + break; + } + else + { + // Intentionally empty + } } - - offset = nrf_802154_frame_parser_ie_content_address_get(p_iterator) - - p_parser_data->p_frame; } if (offset != nrf_802154_frame_parser_mfr_offset_get(p_parser_data)) diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ie_writer.c b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ie_writer.c index eb89008..392275e 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ie_writer.c +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ie_writer.c @@ -45,7 +45,6 @@ #include "nrf_802154_core.h" #include "nrf_802154_nrfx_addons.h" #include "nrf_802154_tx_work_buffer.h" -#include "nrf_802154_utils.h" #include "nrf_802154_utils_byteorder.h" #include diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ie_writer.h b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ie_writer.h index 4393435..af8bc59 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ie_writer.h +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ie_writer.h @@ -41,7 +41,7 @@ #include "nrf_802154_types.h" /** - * @defgroup nrf_802154_ie_writer 802.15.4 driver Information Element writer + * @defgroup nrf_802154_ie_writer Radio driver Information Element data injection feature. * @{ * @ingroup nrf_802154 * @brief Information element writer module. diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ifs.c b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ifs.c index 1c7f710..66d8ba8 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ifs.c +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_ifs.c @@ -72,7 +72,12 @@ static void ifs_tx_result_notify(bool result) { if (!result) { - nrf_802154_notify_transmit_failed(m_context.p_data, NRF_802154_TX_ERROR_TIMESLOT_DENIED); + nrf_802154_transmit_done_metadata_t metadata = {}; + + metadata.frame_props = m_context.params.frame_props; + nrf_802154_notify_transmit_failed(m_context.p_data, + NRF_802154_TX_ERROR_TIMESLOT_DENIED, + &metadata); } } @@ -99,11 +104,16 @@ static bool is_ifs_needed_by_address(const uint8_t * p_frame) PARSE_LEVEL_ADDRESSING_END, &frame_data); - assert(result); - (void)result; - - addr = nrf_802154_frame_parser_dst_addr_get(&frame_data); - is_extended = nrf_802154_frame_parser_dst_addr_is_extended(&frame_data); + if (result) + { + addr = nrf_802154_frame_parser_dst_addr_get(&frame_data); + is_extended = nrf_802154_frame_parser_dst_addr_is_extended(&frame_data); + } + else + { + addr = NULL; + is_extended = false; + } if (!addr) { @@ -226,11 +236,16 @@ void nrf_802154_ifs_transmitted_hook(const uint8_t * p_frame) PARSE_LEVEL_ADDRESSING_END, &frame_data); - assert(result); - (void)result; - - addr = nrf_802154_frame_parser_dst_addr_get(&frame_data); - m_is_last_address_extended = nrf_802154_frame_parser_dst_addr_is_extended(&frame_data); + if (result) + { + addr = nrf_802154_frame_parser_dst_addr_get(&frame_data); + m_is_last_address_extended = nrf_802154_frame_parser_dst_addr_is_extended(&frame_data); + } + else + { + addr = NULL; + m_is_last_address_extended = false; + } if (!addr) { @@ -268,8 +283,14 @@ bool nrf_802154_ifs_abort(nrf_802154_term_t term_lvl, req_originator_t req_orig) if (was_running) { ifs_operation_t * p_op = (ifs_operation_t *)m_timer.p_context; + // The IFS was still waiting, so the transmission didn't occur + // at all. Notify with frame_props passed in nrf_802154_ifs_pretransmission hook + nrf_802154_transmit_done_metadata_t metadata = {}; - nrf_802154_notify_transmit_failed(p_op->p_data, NRF_802154_TX_ERROR_ABORTED); + metadata.frame_props = m_context.params.frame_props; + nrf_802154_notify_transmit_failed(p_op->p_data, + NRF_802154_TX_ERROR_ABORTED, + &metadata); } } else diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_precise_ack_timeout.c b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_precise_ack_timeout.c index fc7fc06..2bb654d 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_precise_ack_timeout.c +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_precise_ack_timeout.c @@ -50,6 +50,7 @@ #include "nrf_802154_notification.h" #include "nrf_802154_procedures_duration.h" #include "nrf_802154_request.h" +#include "nrf_802154_tx_work_buffer.h" #include "timer/nrf_802154_timer_sched.h" #if NRF_802154_ACK_TIMEOUT_ENABLED @@ -68,7 +69,11 @@ static void notify_tx_error(bool result) { if (result) { - nrf_802154_notify_transmit_failed(mp_frame, NRF_802154_TX_ERROR_NO_ACK); + // If waiting for ack timeout occurred, the transmission must had already finished. + nrf_802154_transmit_done_metadata_t metadata = {0}; + + nrf_802154_tx_work_buffer_original_frame_update(mp_frame, &metadata.frame_props); + nrf_802154_notify_transmit_failed(mp_frame, NRF_802154_TX_ERROR_NO_ACK, &metadata); } } diff --git a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_security_writer.c b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_security_writer.c index 6739c48..0334623 100644 --- a/drivers/nrf_802154/driver/src/mac_features/nrf_802154_security_writer.c +++ b/drivers/nrf_802154/driver/src/mac_features/nrf_802154_security_writer.c @@ -44,7 +44,6 @@ #include "mac_features/nrf_802154_security_pib.h" #include "nrf_802154_config.h" #include "nrf_802154_const.h" -#include "nrf_802154_notification.h" #include "nrf_802154_tx_work_buffer.h" #include "nrf_802154_utils_byteorder.h" @@ -197,14 +196,24 @@ bool nrf_802154_security_writer_tx_setup( break; case NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND: - notify_function(p_frame, NRF_802154_TX_ERROR_KEY_ID_INVALID); + { + nrf_802154_transmit_done_metadata_t metadata = {}; + + metadata.frame_props = p_params->frame_props; + notify_function(p_frame, NRF_802154_TX_ERROR_KEY_ID_INVALID, &metadata); result = false; - break; + } + break; case NRF_802154_SECURITY_ERROR_FRAME_COUNTER_OVERFLOW: - notify_function(p_frame, NRF_802154_TX_ERROR_FRAME_COUNTER_ERROR); + { + nrf_802154_transmit_done_metadata_t metadata = {}; + + metadata.frame_props = p_params->frame_props; + notify_function(p_frame, NRF_802154_TX_ERROR_FRAME_COUNTER_ERROR, &metadata); result = false; - break; + } + break; default: /* frame_counter_inject function shall not return other error codes than those diff --git a/drivers/nrf_802154/driver/src/nrf_802154.c b/drivers/nrf_802154/driver/src/nrf_802154.c index 75b7ab3..515cefb 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154.c +++ b/drivers/nrf_802154/driver/src/nrf_802154.c @@ -57,7 +57,6 @@ #include "nrf_802154_nrfx_addons.h" #include "nrf_802154_pib.h" #include "nrf_802154_request.h" -#include "nrf_802154_rssi.h" #include "nrf_802154_rx_buffer.h" #include "nrf_802154_stats.h" #include "hal/nrf_radio.h" @@ -79,12 +78,10 @@ #include "mac_features/ack_generator/nrf_802154_ack_data.h" #include "nrf_802154_sl_ant_div.h" +#include "nrf_802154_sl_crit_sect_if.h" #include "nrf_802154_sl_capabilities.h" -#define RAW_LENGTH_OFFSET 0 -#define RAW_PAYLOAD_OFFSET 1 - -#if !NRF_802154_USE_RAW_API +#if !NRF_802154_USE_RAW_API || NRF_802154_CARRIER_FUNCTIONS_ENABLED /** Static transmit buffer used by @sa nrf_802154_transmit() family of functions. * * If none of functions using this buffer is called and link time optimization is enabled, this @@ -92,6 +89,9 @@ */ static uint8_t m_tx_buffer[RAW_PAYLOAD_OFFSET + MAX_PACKET_SIZE]; +#endif // !NRF_802154_USE_RAW_API || NRF_802154_CARRIER_FUNCTIONS_ENABLED + +#if !NRF_802154_USE_RAW_API /** * @brief Fill transmit buffer with given data. * @@ -110,6 +110,24 @@ static void tx_buffer_fill(const uint8_t * p_data, uint8_t length) #endif // !NRF_802154_USE_RAW_API +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED +/** + * @brief Fill the transmit buffer with given data in order to use it with the + * modulated carrier functionality. + * + * @param[in] p_data Pointer to array containing modulating data. + */ +static void tx_buffer_fill_for_modulated_carrier(const uint8_t * p_data) +{ + uint8_t length = p_data[RAW_LENGTH_OFFSET]; + + assert(length <= MAX_PACKET_SIZE); + + memcpy(m_tx_buffer, p_data, RAW_PAYLOAD_OFFSET + length); +} + +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + static inline bool are_frame_properties_valid(const nrf_802154_transmitted_frame_props_t * p_props) { return p_props->dynamic_data_is_set || !(p_props->is_secured); @@ -203,7 +221,7 @@ uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t p void nrf_802154_init(void) { - nrf_802154_sl_crit_sect_interface_t crit_sect_int = + static const nrf_802154_sl_crit_sect_interface_t crit_sect_int = { .enter = nrf_802154_critical_section_enter, .exit = nrf_802154_critical_section_exit @@ -213,6 +231,7 @@ void nrf_802154_init(void) nrf_802154_core_init(); nrf_802154_clock_init(); nrf_802154_critical_section_init(); + nrf_802154_sl_crit_sect_init(&crit_sect_int); nrf_802154_debug_init(); nrf_802154_notification_init(); nrf_802154_lp_timer_init(); @@ -221,7 +240,7 @@ void nrf_802154_init(void) nrf_802154_rsch_prio_drop_init(); nrf_802154_random_init(); nrf_802154_request_init(); - nrf_802154_rsch_crit_sect_init(&crit_sect_int); + nrf_802154_rsch_crit_sect_init(); nrf_802154_rsch_init(); nrf_802154_rx_buffer_init(); nrf_802154_temperature_init(); @@ -379,11 +398,15 @@ nrf_802154_state_t nrf_802154_state_get(void) case RADIO_STATE_CCA: return NRF_802154_STATE_CCA; +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + case RADIO_STATE_CONTINUOUS_CARRIER: return NRF_802154_STATE_CONTINUOUS_CARRIER; case RADIO_STATE_MODULATED_CARRIER: return NRF_802154_STATE_MODULATED_CARRIER; +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + } return NRF_802154_STATE_INVALID; @@ -542,7 +565,7 @@ bool nrf_802154_transmit_raw_at(uint8_t * p_data result = are_frame_properties_valid(&p_metadata->frame_props); if (result) { - result = nrf_802154_delayed_trx_transmit(p_data, t0, dt, p_metadata); + result = nrf_802154_request_transmit_raw_at(p_data, t0, dt, p_metadata); } nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); @@ -555,7 +578,7 @@ bool nrf_802154_transmit_at_cancel(void) nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); - result = nrf_802154_delayed_trx_transmit_cancel(); + result = nrf_802154_request_transmit_at_cancel(); nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); return result; @@ -571,7 +594,7 @@ bool nrf_802154_receive_at(uint32_t t0, nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); - result = nrf_802154_delayed_trx_receive(t0, dt, timeout, channel, id); + result = nrf_802154_request_receive_at(t0, dt, timeout, channel, id); nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); return result; @@ -583,7 +606,7 @@ bool nrf_802154_receive_at_cancel(uint32_t id) nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); - result = nrf_802154_delayed_trx_receive_cancel(id); + result = nrf_802154_request_receive_at_cancel(id); nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); return result; @@ -615,6 +638,8 @@ bool nrf_802154_cca(void) return result; } +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + bool nrf_802154_continuous_carrier(void) { bool result; @@ -633,12 +658,16 @@ bool nrf_802154_modulated_carrier(const uint8_t * p_data) nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); - result = nrf_802154_request_modulated_carrier(NRF_802154_TERM_NONE, p_data); + tx_buffer_fill_for_modulated_carrier(p_data); + + result = nrf_802154_request_modulated_carrier(NRF_802154_TERM_NONE, m_tx_buffer); nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); return result; } +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + #if NRF_802154_USE_RAW_API void nrf_802154_buffer_free_raw(uint8_t * p_data) diff --git a/drivers/nrf_802154/driver/src/nrf_802154_aes_ccm.c b/drivers/nrf_802154/driver/src/nrf_802154_aes_ccm.c index 3d8276b..61985e0 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_aes_ccm.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_aes_ccm.c @@ -39,6 +39,7 @@ #include "hal/nrf_ecb.h" #include "nrf_802154_const.h" +#include "nrf_802154_config.h" #include "nrf_802154_tx_work_buffer.h" #include "platform/nrf_802154_irq.h" @@ -138,6 +139,7 @@ static void ecb_init(void) nrf_802154_irq_clear_pending(ECB_IRQn); nrf_802154_irq_enable(ECB_IRQn); nrf_ecb_int_enable(NRF_ECB, NRF_ECB_INT_ENDECB_MASK); + nrf_ecb_int_enable(NRF_ECB, NRF_ECB_INT_ERRORECB_MASK); } /******************************************************************************/ @@ -384,7 +386,8 @@ static void ecb_irq_handler(void) uint8_t len = 0; uint8_t offset; - if (nrf_ecb_event_check(NRF_ECB, NRF_ECB_EVENT_ENDECB)) + if (nrf_ecb_int_enable_check(NRF_ECB, NRF_ECB_INT_ENDECB_MASK) && + nrf_ecb_event_check(NRF_ECB, NRF_ECB_EVENT_ENDECB)) { nrf_ecb_event_clear(NRF_ECB, NRF_ECB_EVENT_ENDECB); @@ -451,6 +454,23 @@ static void ecb_irq_handler(void) break; } } + + if (nrf_ecb_int_enable_check(NRF_ECB, NRF_ECB_INT_ERRORECB_MASK) && + nrf_ecb_event_check(NRF_ECB, NRF_ECB_EVENT_ERRORECB)) + { + /* + * It is possible that the ERRORECB event is caused by the + * AAR and CCM peripherals, which share the same hardware resources. + * At this point it is assumed, that ECB, AAR and CCM peripherals + * are not used by anything, except the 802.15.4 driver and + * other MPSL clients and thus it is impossible that ECB was aborted + * for any other reason, than the TX failed event caused by a terminated + * 802.15.4 transmit operation or end of timeslot. + * + * Therefore no action is taken in this handler. + */ + nrf_ecb_event_clear(NRF_ECB, NRF_ECB_EVENT_ERRORECB); + } } /** @@ -465,6 +485,11 @@ static void start_ecb_auth_transformation(void) nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STARTECB); } +void nrf_802154_aes_ccm_transform_reset(void) +{ + m_aes_ccm_data.raw_frame = NULL; +} + bool nrf_802154_aes_ccm_transform_prepare(const nrf_802154_aes_ccm_data_t * p_aes_ccm_data) { // Verify that all necessary data is available @@ -519,6 +544,10 @@ void nrf_802154_aes_ccm_transform_start(uint8_t * p_frame) uint8_t auth_flags = auth_flags_format(&m_aes_ccm_data); uint8_t * p_x = m_x; uint8_t * p_b = m_b; + ptrdiff_t offset = mp_ciphertext - mp_work_buffer; + + // Copy updated part of the frame + memcpy(mp_work_buffer, p_frame, offset); // initial settings memset(p_x, 0, NRF_802154_AES_CCM_BLOCK_SIZE); @@ -530,3 +559,24 @@ void nrf_802154_aes_ccm_transform_start(uint8_t * p_frame) nrf_ecb_set_key(m_aes_ccm_data.key); start_ecb_auth_transformation(); } + +void nrf_802154_aes_ccm_transform_abort(uint8_t * p_frame) +{ + // Verify that the encryption of the correct frame is being aborted. + if (p_frame != m_aes_ccm_data.raw_frame) + { + return; + } + + /* + * Temporarily disable ENDECB interrupt, trigger STOPECB task + * to stop encryption in case it is still running and clear + * the ENDECB event in case the encryption has completed. + */ + nrf_ecb_int_disable(NRF_ECB, NRF_ECB_INT_ENDECB_MASK); + nrf_ecb_task_trigger(NRF_ECB, NRF_ECB_TASK_STOPECB); + nrf_ecb_event_clear(NRF_ECB, NRF_ECB_EVENT_ENDECB); + nrf_ecb_int_enable(NRF_ECB, NRF_ECB_INT_ENDECB_MASK); + + m_aes_ccm_data.raw_frame = NULL; +} diff --git a/drivers/nrf_802154/driver/src/nrf_802154_aes_ccm.h b/drivers/nrf_802154/driver/src/nrf_802154_aes_ccm.h index f9e4283..9b54338 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_aes_ccm.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_aes_ccm.h @@ -62,6 +62,11 @@ typedef struct uint8_t * raw_frame; ///< Pointer to the buffer that contains the PHR and PSDU of the transmitted frame. } nrf_802154_aes_ccm_data_t; +/** + * @brief Resets AES-CCM* transformation. + */ +void nrf_802154_aes_ccm_transform_reset(void); + /** * @brief Prepares AES-CCM* transformation. * @@ -84,4 +89,11 @@ bool nrf_802154_aes_ccm_transform_prepare(const nrf_802154_aes_ccm_data_t * p_ae */ void nrf_802154_aes_ccm_transform_start(uint8_t * p_frame); +/** + * @brief Aborts AES-CCM* transformation. + * + * @param[in] p_frame Pointer to the buffer that contains a frame being transmitted. + */ +void nrf_802154_aes_ccm_transform_abort(uint8_t * p_frame); + #endif // NRF_802154_AES_CCM_H_ diff --git a/drivers/nrf_802154/driver/src/nrf_802154_core.c b/drivers/nrf_802154/driver/src/nrf_802154_core.c index e30b6f9..e325e93 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_core.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_core.c @@ -54,7 +54,6 @@ #include "nrf_802154_debug.h" #include "nrf_802154_notification.h" #include "nrf_802154_nrfx_addons.h" -#include "nrf_802154_peripherals.h" #include "nrf_802154_pib.h" #include "nrf_802154_procedures_duration.h" #include "nrf_802154_rssi.h" @@ -67,11 +66,8 @@ #include "nrf_802154_utils.h" #include "drivers/nrfx_errors.h" #include "hal/nrf_radio.h" -#include "mpsl_fem_protocol_api.h" -#include "mac_features/nrf_802154_delayed_trx.h" #include "mac_features/nrf_802154_filter.h" #include "mac_features/nrf_802154_frame_parser.h" -#include "mac_features/ack_generator/nrf_802154_ack_data.h" #include "mac_features/ack_generator/nrf_802154_ack_generator.h" #include "rsch/nrf_802154_rsch.h" #include "rsch/nrf_802154_rsch_crit_sect.h" @@ -79,6 +75,7 @@ #include "timer/nrf_802154_timer_sched.h" #include "platform/nrf_802154_hp_timer.h" #include "platform/nrf_802154_irq.h" +#include "protocol/mpsl_fem_protocol_api.h" #include "nrf_802154_core_hooks.h" #include "nrf_802154_sl_ant_div.h" @@ -91,12 +88,10 @@ /// Overhead of hardware preparation for ED procedure (aTurnaroundTime) [number of iterations] #define ED_ITERS_OVERHEAD 2U -#define ACK_IFS TURNAROUND_TIME ///< Ack Inter Frame Spacing [us] - delay between last symbol of received frame and first symbol of transmitted Ack +#define MAX_CRIT_SECT_TIME 60 ///< Maximal time that the driver spends in single critical section. -#define MAX_CRIT_SECT_TIME 60 ///< Maximal time that the driver spends in single critical section. - -#define LQI_VALUE_FACTOR 4 ///< Factor needed to calculate LQI value based on data from RADIO peripheral -#define LQI_MAX 0xff ///< Maximal LQI value +#define LQI_VALUE_FACTOR 4 ///< Factor needed to calculate LQI value based on data from RADIO peripheral +#define LQI_MAX 0xff ///< Maximal LQI value /** Get LQI of given received packet. If CRC is calculated by hardware LQI is included instead of CRC * in the frame. Length is stored in byte with index 0; CRC is 2 last bytes. @@ -133,7 +128,6 @@ typedef struct { bool frame_filtered : 1; ///< If frame being received passed filtering operation. bool frame_parsed : 1; ///< If frame being received has been parsed - bool frame_parsed_result : 1; bool rx_timeslot_requested : 1; ///< If timeslot for the frame being received is already requested. bool tx_with_cca : 1; ///< If currently transmitted frame is transmitted with cca. bool tx_diminished_prio : 1; ///< If priority of the current transmission should be diminished. @@ -215,7 +209,6 @@ static void rx_flags_clear(void) m_flags.frame_filtered = false; m_flags.rx_timeslot_requested = false; m_flags.frame_parsed = false; - m_flags.frame_parsed_result = false; } /** Wait for the RSSI measurement. */ @@ -297,9 +290,7 @@ static uint32_t timer_coord_timestamp_get(void) static void received_frame_notify(uint8_t * p_data) { - nrf_802154_notify_received(p_data, // data - m_last_rssi, // rssi - m_last_lqi); // lqi + nrf_802154_notify_received(p_data, m_last_rssi, m_last_lqi); } /** Allow nesting critical sections and notify MAC layer that a frame was received. */ @@ -317,7 +308,9 @@ static void receive_failed_notify(nrf_802154_rx_error_t error) { nrf_802154_critical_section_nesting_allow(); - nrf_802154_notify_receive_failed(error, m_rx_window_id); + // Don't care about the result - if the notification cannot be performed + // no impact on the device's operation is expected + (void)nrf_802154_notify_receive_failed(error, m_rx_window_id, true); nrf_802154_critical_section_nesting_deny(); } @@ -381,20 +374,24 @@ static void transmitted_frame_notify(uint8_t * p_ack, int8_t power, uint8_t lqi) } /** Notify MAC layer that transmission procedure failed. */ -static void transmit_failed_notify(uint8_t * p_frame, nrf_802154_tx_error_t error) +static void transmit_failed_notify(uint8_t * p_frame, + nrf_802154_tx_error_t error, + const nrf_802154_transmit_done_metadata_t * p_meta) { if (nrf_802154_core_hooks_tx_failed(p_frame, error)) { - nrf_802154_notify_transmit_failed(p_frame, error); + nrf_802154_notify_transmit_failed(p_frame, error, p_meta); } } /** Allow nesting critical sections and notify MAC layer that transmission procedure failed. */ -static void transmit_failed_notify_and_nesting_allow(nrf_802154_tx_error_t error) +static void transmit_failed_notify_and_nesting_allow( + nrf_802154_tx_error_t error, + const nrf_802154_transmit_done_metadata_t * p_meta) { nrf_802154_critical_section_nesting_allow(); - transmit_failed_notify(mp_tx_data, error); + transmit_failed_notify(mp_tx_data, error, p_meta); nrf_802154_critical_section_nesting_deny(); } @@ -584,8 +581,10 @@ static rsch_prio_t min_required_rsch_prio(radio_state_t state) case RADIO_STATE_TX: case RADIO_STATE_TX_ACK: +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case RADIO_STATE_CONTINUOUS_CARRIER: case RADIO_STATE_MODULATED_CARRIER: +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED return RSCH_PRIO_TX; case RADIO_STATE_CCA_TX: @@ -685,8 +684,10 @@ static bool can_terminate_current_operation(radio_state_t state, { case RADIO_STATE_SLEEP: case RADIO_STATE_FALLING_ASLEEP: +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case RADIO_STATE_CONTINUOUS_CARRIER: case RADIO_STATE_MODULATED_CARRIER: +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED result = true; break; @@ -716,31 +717,48 @@ static void operation_terminated_notify(radio_state_t state, bool receiving_psdu { case RADIO_STATE_SLEEP: case RADIO_STATE_FALLING_ASLEEP: +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case RADIO_STATE_CONTINUOUS_CARRIER: case RADIO_STATE_MODULATED_CARRIER: +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED break; case RADIO_STATE_RX: if (receiving_psdu_now) { - nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_ABORTED, m_rx_window_id); + // Don't care about the result - if the notification cannot be performed + // no impact on the device's operation is expected + (void)nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_ABORTED, + m_rx_window_id, + true); } break; case RADIO_STATE_TX_ACK: mp_current_rx_buffer->free = false; + nrf_802154_core_hooks_tx_ack_failed(mp_ack, NRF_802154_TX_ERROR_ABORTED); received_frame_notify(mp_current_rx_buffer->data); break; case RADIO_STATE_CCA_TX: case RADIO_STATE_TX: - transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_ABORTED); - break; + { + nrf_802154_transmit_done_metadata_t metadata = {}; + + nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props); + transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_ABORTED, &metadata); + } + break; case RADIO_STATE_RX_ACK: - transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_ABORTED); - break; + { + nrf_802154_transmit_done_metadata_t metadata = {}; + + nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props); + transmit_failed_notify(mp_tx_data, NRF_802154_TX_ERROR_ABORTED, &metadata); + } + break; case RADIO_STATE_ED: nrf_802154_notify_energy_detection_failed(NRF_802154_ED_ERROR_ABORTED); @@ -901,7 +919,11 @@ static bool current_operation_terminate(nrf_802154_term_t term_lvl, /** Enter Sleep state. */ static void sleep_init(void) { - nrf_802154_timer_coord_stop(); + // This function is always executed from a critical section, so this check is safe. + if (timeslot_is_granted()) + { + nrf_802154_timer_coord_stop(); + } } /** Initialize Falling Asleep operation. */ @@ -1027,12 +1049,10 @@ static void rx_init(void) #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED) // Configure the timer coordinator to get a timestamp of the END event which // fires several cycles after CRCOK or CRCERROR events. - nrf_802154_timer_coord_timestamp_prepare( - nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_END)); + nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_end_event_handle_get()); #else // Configure the timer coordinator to get a timestamp of the CRCOK event. - nrf_802154_timer_coord_timestamp_prepare(nrf_radio_event_address_get(NRF_RADIO, - NRF_RADIO_EVENT_CRCOK)); + nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_crcok_event_handle_get()); #endif #endif @@ -1069,14 +1089,12 @@ static bool tx_init(const uint8_t * p_data, bool cca) // Configure the timer coordinator to get a time stamp of the READY event. // Note: This event triggers CCASTART, so the time stamp of READY event // is the time stamp when CCA started. - nrf_802154_timer_coord_timestamp_prepare(nrf_radio_event_address_get(NRF_RADIO, - NRF_RADIO_EVENT_READY)); + nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_ready_event_handle_get()); } else { // Configure the timer coordinator to get a time stamp of the PHYEND event. - nrf_802154_timer_coord_timestamp_prepare(nrf_radio_event_address_get(NRF_RADIO, - NRF_RADIO_EVENT_PHYEND)); + nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_phyend_event_handle_get()); } #endif @@ -1132,6 +1150,8 @@ static void cca_init(void) nrf_802154_trx_standalone_cca(); } +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + /** Initialize Continuous Carrier operation. */ static void continuous_carrier_init(void) { @@ -1164,6 +1184,8 @@ static void modulated_carrier_init(const uint8_t * p_data) nrf_802154_trx_modulated_carrier(p_data); } +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + /*************************************************************************************************** * @section Radio Scheduler notification handlers **************************************************************************************************/ @@ -1211,20 +1233,29 @@ static void on_timeslot_ended(void) case RADIO_STATE_TX_ACK: state_set(RADIO_STATE_RX); mp_current_rx_buffer->free = false; + nrf_802154_core_hooks_tx_ack_failed(mp_ack, NRF_802154_TX_ERROR_TIMESLOT_ENDED); received_frame_notify_and_nesting_allow(mp_current_rx_buffer->data); break; case RADIO_STATE_CCA_TX: case RADIO_STATE_TX: case RADIO_STATE_RX_ACK: + { state_set(RADIO_STATE_RX); - transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_TIMESLOT_ENDED); - break; + nrf_802154_transmit_done_metadata_t metadata = {}; + + nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props); + transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_TIMESLOT_ENDED, + &metadata); + } + break; case RADIO_STATE_ED: case RADIO_STATE_CCA: +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case RADIO_STATE_CONTINUOUS_CARRIER: case RADIO_STATE_MODULATED_CARRIER: +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED case RADIO_STATE_SLEEP: // Intentionally empty. break; @@ -1285,8 +1316,10 @@ static void on_preconditions_denied(radio_state_t state) case RADIO_STATE_ED: case RADIO_STATE_CCA: +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case RADIO_STATE_CONTINUOUS_CARRIER: case RADIO_STATE_MODULATED_CARRIER: +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED case RADIO_STATE_SLEEP: // Intentionally empty. break; @@ -1332,6 +1365,7 @@ static void on_preconditions_approved(radio_state_t state) cca_init(); break; +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case RADIO_STATE_CONTINUOUS_CARRIER: continuous_carrier_init(); break; @@ -1339,6 +1373,7 @@ static void on_preconditions_approved(radio_state_t state) case RADIO_STATE_MODULATED_CARRIER: modulated_carrier_init(mp_tx_data); break; +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED default: assert(false); @@ -1633,12 +1668,10 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc) /* Request boosted preconditions */ nrf_802154_rsch_crit_sect_prio_request(RSCH_PRIO_RX); - /* Request next bcc match event just after all frame bytes are received - * but before FCS. This happens 64us before frame is fully received. - * This time is used for preparation of possible ACK transmission - */ - m_flags.frame_parsed = false; - m_flags.frame_parsed_result = false; + /* Request next bcc match event to occur when basic data necessary for Ack + * generation is received. */ + m_flags.frame_parsed = false; + nrf_802154_ack_generator_reset(); bcc = PHR_SIZE + nrf_802154_frame_parser_addressing_end_offset_get(&m_current_rx_frame_data) + @@ -1671,52 +1704,40 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc) { if (nrf_802154_frame_parser_security_enabled_bit_is_set(&m_current_rx_frame_data)) { - if (nrf_802154_frame_parser_parse_level_get(&m_current_rx_frame_data) < - PARSE_LEVEL_ADDRESSING_END) - { - // All addressing fields and Security Control byte have been received. - uint8_t parsable_bytes = - PHR_SIZE + - nrf_802154_frame_parser_addressing_end_offset_get(&m_current_rx_frame_data) + - SECURITY_CONTROL_SIZE; - - (void)nrf_802154_frame_parser_valid_data_extend( + if (nrf_802154_frame_parser_valid_data_extend( &m_current_rx_frame_data, - parsable_bytes, - PARSE_LEVEL_SEC_CTRL_OFFSETS); - - // Having parsed Security Control field, length of Auxiliary Security Header is - // known. Set BCC there - bcc = PHR_SIZE + - nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(&m_current_rx_frame_data); - } - else if (nrf_802154_frame_parser_parse_level_get(&m_current_rx_frame_data) < - PARSE_LEVEL_AUX_SEC_HDR_END) + num_data_bytes, + PARSE_LEVEL_AUX_SEC_HDR_END)) { // All security fields have been received. - uint8_t parsable_bytes = - PHR_SIZE + - nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(&m_current_rx_frame_data); - - m_flags.frame_parsed = true; - m_flags.frame_parsed_result = nrf_802154_frame_parser_valid_data_extend( - &m_current_rx_frame_data, - parsable_bytes, - PARSE_LEVEL_AUX_SEC_HDR_END); + m_flags.frame_parsed = true; + } + else if (nrf_802154_frame_parser_valid_data_extend( + &m_current_rx_frame_data, + num_data_bytes, + PARSE_LEVEL_SEC_CTRL_OFFSETS)) + { + // All addressing fields and Security Control byte have been received. + // With the Security Control field, length of Auxiliary Security Header can be + // determined. Set BCC there + bcc = PHR_SIZE + + nrf_802154_frame_parser_aux_sec_hdr_end_offset_get(&m_current_rx_frame_data); } else { // This code should be unreachable. } } + else if (nrf_802154_frame_parser_valid_data_extend( + &m_current_rx_frame_data, + num_data_bytes, + PARSE_LEVEL_ADDRESSING_END)) + { + m_flags.frame_parsed = true; + } else { - m_flags.frame_parsed = true; - m_flags.frame_parsed_result = nrf_802154_frame_parser_valid_data_extend( - &m_current_rx_frame_data, - PHR_SIZE + - nrf_802154_frame_parser_addressing_end_offset_get(&m_current_rx_frame_data), - PARSE_LEVEL_ADDRESSING_END); + // This code should be unreachable. } } else @@ -1744,17 +1765,19 @@ uint8_t nrf_802154_trx_receive_frame_bcmatched(uint8_t bcc) // which could result in spurious RF emission. rx_init(); - nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_TIMESLOT_ENDED, m_rx_window_id); + // Don't care about the result - if the notification cannot be performed + // no impact on the device's operation is expected + (void)nrf_802154_notify_receive_failed(NRF_802154_RX_ERROR_TIMESLOT_ENDED, + m_rx_window_id, + true); } } if (m_flags.frame_filtered && - m_flags.frame_parsed_result && + m_flags.frame_parsed && nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) && nrf_802154_pib_auto_ack_get()) { - nrf_802154_tx_work_buffer_reset(&m_default_frame_props); - mp_ack = nrf_802154_ack_generator_create(&m_current_rx_frame_data); } @@ -1866,8 +1889,7 @@ void nrf_802154_trx_receive_frame_crcerror(void) // Configure the timer coordinator to get a timestamp of the END event which // fires several cycles after CRCOK or CRCERROR events. - nrf_802154_timer_coord_timestamp_prepare( - nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_END)); + nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_end_event_handle_get()); #endif #else @@ -1989,27 +2011,23 @@ void nrf_802154_trx_receive_frame_received(void) nrf_802154_sl_ant_div_rx_frame_received_notify(); - bool send_ack = m_flags.frame_filtered && - nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) && - nrf_802154_pib_auto_ack_get(); + bool send_ack = false; + bool parse_result = nrf_802154_frame_parser_valid_data_extend( + &m_current_rx_frame_data, + PHR_SIZE + nrf_802154_frame_parser_frame_length_get(&m_current_rx_frame_data), + PARSE_LEVEL_FULL); -#if NRF_802154_DISABLE_BCC_MATCHING - bool parse_result = nrf_802154_frame_parser_valid_data_extend(&m_current_rx_frame_data, - p_received_data[PHR_OFFSET] + PHR_SIZE, - PARSE_LEVEL_FULL); - - nrf_802154_tx_work_buffer_reset(&m_default_frame_props); - - if (send_ack && parse_result) + if (m_flags.frame_filtered && + parse_result && + nrf_802154_frame_parser_ar_bit_is_set(&m_current_rx_frame_data) && + nrf_802154_pib_auto_ack_get()) { - mp_ack = nrf_802154_ack_generator_create(&m_current_rx_frame_data); + nrf_802154_tx_work_buffer_reset(&m_default_frame_props); + mp_ack = nrf_802154_ack_generator_create(&m_current_rx_frame_data); + send_ack = (mp_ack != NULL); } -#else - bool parse_result = m_flags.frame_parsed_result; -#endif - - if (send_ack && parse_result && (NULL != mp_ack)) + if (send_ack) { state_set(RADIO_STATE_TX_ACK); @@ -2196,12 +2214,10 @@ void nrf_802154_trx_transmit_frame_transmitted(void) #if (NRF_802154_TOTAL_TIMES_MEASUREMENT_ENABLED) // Configure the timer coordinator to get a timestamp of the END event which // fires several cycles after CRCOK or CRCERROR events. - nrf_802154_timer_coord_timestamp_prepare( - nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_END)); + nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_end_event_handle_get()); #else // Configure the timer coordinator to get a timestamp of the CRCOK event. - nrf_802154_timer_coord_timestamp_prepare(nrf_radio_event_address_get(NRF_RADIO, - NRF_RADIO_EVENT_CRCOK)); + nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_crcok_event_handle_get()); #endif #endif @@ -2270,8 +2286,11 @@ static bool ack_match_check_version_2(const uint8_t * p_tx_frame, const uint8_t p_tx_frame[PHR_OFFSET] + PHR_SIZE, PARSE_LEVEL_ADDRESSING_END, &tx_data); - assert(parse_result); - (void)parse_result; + if (!parse_result) + { + return false; + } + parse_result = nrf_802154_frame_parser_data_init(p_ack_frame, p_ack_frame[PHR_OFFSET] + PHR_SIZE, PARSE_LEVEL_ADDRESSING_END, @@ -2337,7 +2356,10 @@ static void on_bad_ack(void) rx_init(); - transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_INVALID_ACK); + nrf_802154_transmit_done_metadata_t metadata = {}; + + nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props); + transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_INVALID_ACK, &metadata); nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } @@ -2415,8 +2437,7 @@ void nrf_802154_trx_transmit_frame_ccaidle(void) uint32_t ts = timer_coord_timestamp_get(); // Configure the timer coordinator to get a timestamp of the PHYEND event. - nrf_802154_timer_coord_timestamp_prepare(nrf_radio_event_address_get(NRF_RADIO, - NRF_RADIO_EVENT_PHYEND)); + nrf_802154_timer_coord_timestamp_prepare(nrf_802154_trx_radio_phyend_event_handle_get()); // Update stat timestamp of CCASTART event nrf_802154_stat_timestamp_write(last_cca_start_timestamp, ts); @@ -2446,7 +2467,10 @@ void nrf_802154_trx_transmit_frame_ccabusy(void) state_set(RADIO_STATE_RX); rx_init(); - transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_BUSY_CHANNEL); + nrf_802154_transmit_done_metadata_t metadata = {}; + + nrf_802154_tx_work_buffer_original_frame_update(mp_tx_data, &metadata.frame_props); + transmit_failed_notify_and_nesting_allow(NRF_802154_TX_ERROR_BUSY_CHANNEL, &metadata); nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } @@ -2743,6 +2767,8 @@ bool nrf_802154_core_cca(nrf_802154_term_t term_lvl) return result; } +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + bool nrf_802154_core_continuous_carrier(nrf_802154_term_t term_lvl) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); @@ -2793,6 +2819,8 @@ bool nrf_802154_core_modulated_carrier(nrf_802154_term_t term_lvl, return result; } +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + bool nrf_802154_core_notify_buffer_free(uint8_t * p_data) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); @@ -2843,6 +2871,7 @@ bool nrf_802154_core_channel_update(req_originator_t req_orig) } break; +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case RADIO_STATE_CONTINUOUS_CARRIER: if (timeslot_is_granted()) { @@ -2857,6 +2886,7 @@ bool nrf_802154_core_channel_update(req_originator_t req_orig) } break; +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED default: // Don't perform any additional action in any other state. break; diff --git a/drivers/nrf_802154/driver/src/nrf_802154_core.h b/drivers/nrf_802154/driver/src/nrf_802154_core.h index 1ebe72b..42d135f 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_core.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_core.h @@ -58,29 +58,32 @@ extern "C" { typedef enum { // Sleep - RADIO_STATE_SLEEP, ///< Low power mode (disabled) - the only state in which all radio preconditions are not requested. - RADIO_STATE_FALLING_ASLEEP, ///< Before entering the sleep state, all radio preconditions are requested. + RADIO_STATE_SLEEP, ///< Low power mode (disabled) - the only state in which all radio preconditions are not requested. + RADIO_STATE_FALLING_ASLEEP, ///< Before entering the sleep state, all radio preconditions are requested. // Receive - RADIO_STATE_RX, ///< The receiver is enabled and it is receiving frames. - RADIO_STATE_TX_ACK, ///< The frame is received and the ACK is being transmitted. + RADIO_STATE_RX, ///< The receiver is enabled and it is receiving frames. + RADIO_STATE_TX_ACK, ///< The frame is received and the ACK is being transmitted. // Transmit - RADIO_STATE_CCA_TX, ///< Performing CCA followed by the frame transmission. - RADIO_STATE_TX, ///< Transmitting data frame (or beacon). - RADIO_STATE_RX_ACK, ///< Receiving ACK after the transmitted frame. + RADIO_STATE_CCA_TX, ///< Performing CCA followed by the frame transmission. + RADIO_STATE_TX, ///< Transmitting data frame (or beacon). + RADIO_STATE_RX_ACK, ///< Receiving ACK after the transmitted frame. // Energy Detection - RADIO_STATE_ED, ///< Performing the energy detection procedure. + RADIO_STATE_ED, ///< Performing the energy detection procedure. // CCA - RADIO_STATE_CCA, ///< Performing the CCA procedure. + RADIO_STATE_CCA, ///< Performing the CCA procedure. +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED // Continuous carrier RADIO_STATE_CONTINUOUS_CARRIER, ///< Emitting the continuous carrier wave. // Modulated carrier RADIO_STATE_MODULATED_CARRIER ///< Emitting the modulated carrier signal. +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + } radio_state_t; /** @@ -177,6 +180,8 @@ bool nrf_802154_core_energy_detection(nrf_802154_term_t term_lvl, uint32_t time_ */ bool nrf_802154_core_cca(nrf_802154_term_t term_lvl); +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + /** * @brief Requests the transition to the @ref RADIO_STATE_CONTINUOUS_CARRIER state. * @@ -201,6 +206,8 @@ bool nrf_802154_core_continuous_carrier(nrf_802154_term_t term_lvl); bool nrf_802154_core_modulated_carrier(nrf_802154_term_t term_lvl, const uint8_t * p_data); +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + /*************************************************************************************************** * @section State machine notifications **************************************************************************************************/ diff --git a/drivers/nrf_802154/driver/src/nrf_802154_core_hooks.c b/drivers/nrf_802154/driver/src/nrf_802154_core_hooks.c index c553d60..b58d8ed 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_core_hooks.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_core_hooks.c @@ -64,6 +64,7 @@ typedef bool (* tx_setup_hook)(uint8_t * p_frame nrf_802154_transmit_failed_notification_t notify_function); typedef void (* transmitted_hook)(const uint8_t * p_frame); typedef bool (* tx_failed_hook)(uint8_t * p_frame, nrf_802154_tx_error_t error); +typedef void (* tx_ack_failed_hook)(uint8_t * p_ack, nrf_802154_tx_error_t error); typedef bool (* tx_started_hook)(uint8_t * p_frame); typedef void (* rx_started_hook)(const uint8_t * p_frame); typedef void (* rx_ack_started_hook)(void); @@ -138,6 +139,19 @@ static const tx_failed_hook m_tx_failed_hooks[] = nrf_802154_ack_timeout_tx_failed_hook, #endif +#if NRF_802154_ENCRYPTION_ENABLED + nrf_802154_encrypt_tx_failed_hook, +#endif + + NULL, +}; + +static const tx_ack_failed_hook m_tx_ack_failed_hooks[] = +{ +#if NRF_802154_ENCRYPTION_ENABLED + nrf_802154_encrypt_tx_ack_failed_hook, +#endif + NULL, }; @@ -306,6 +320,19 @@ bool nrf_802154_core_hooks_tx_failed(uint8_t * p_frame, nrf_802154_tx_error_t er return result; } +void nrf_802154_core_hooks_tx_ack_failed(uint8_t * p_ack, nrf_802154_tx_error_t error) +{ + for (uint32_t i = 0; i < sizeof(m_tx_ack_failed_hooks) / sizeof(m_tx_ack_failed_hooks[0]); i++) + { + if (m_tx_ack_failed_hooks[i] == NULL) + { + break; + } + + m_tx_ack_failed_hooks[i](p_ack, error); + } +} + bool nrf_802154_core_hooks_tx_started(uint8_t * p_frame) { bool result = true; diff --git a/drivers/nrf_802154/driver/src/nrf_802154_core_hooks.h b/drivers/nrf_802154/driver/src/nrf_802154_core_hooks.h index b524d83..bbd1f14 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_core_hooks.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_core_hooks.h @@ -117,6 +117,15 @@ void nrf_802154_core_hooks_transmitted(const uint8_t * p_frame); */ bool nrf_802154_core_hooks_tx_failed(uint8_t * p_frame, nrf_802154_tx_error_t error); +/** + * @brief Processes hooks for the ACK TX failed event. + * + * @param[in] p_ack Pointer to a buffer that contains PHR and PSDU of the ACK frame + * that was not transmitted. + * @param[in] error Cause of the failed transmission. + */ +void nrf_802154_core_hooks_tx_ack_failed(uint8_t * p_ack, nrf_802154_tx_error_t error); + /** * @brief Processes hooks for the TX started event. * diff --git a/drivers/nrf_802154/driver/src/nrf_802154_critical_section.c b/drivers/nrf_802154/driver/src/nrf_802154_critical_section.c index ecf64f9..d0af6f1 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_critical_section.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_critical_section.c @@ -48,7 +48,6 @@ #include "nrf_802154_config.h" #include "nrf_802154_debug.h" #include "nrf_802154_utils.h" -#include "hal/nrf_radio.h" #include "rsch/nrf_802154_rsch.h" #include "platform/nrf_802154_lp_timer.h" #include "platform/nrf_802154_irq.h" @@ -59,7 +58,6 @@ #define NESTED_CRITICAL_SECTION_ALLOWED_PRIORITY_NONE (-1) -static volatile uint8_t m_critical_section_monitor; ///< Monitors each critical section enter operation static volatile uint8_t m_nested_critical_section_counter; ///< Counter of nested critical sections static volatile int8_t m_nested_critical_section_allowed_priority; ///< Indicator if nested critical sections are currently allowed @@ -104,106 +102,87 @@ static int8_t active_priority_convert(uint32_t active_priority) return active_priority == UINT32_MAX ? INT8_MAX : (int8_t)active_priority; } -/** @brief Check if active vector priority is equal to priority that allows nested crit sections. - * - * @retval true Active vector priority allows nested critical sections. - * @retval false Active vector priority denies nested critical sections. - */ -static bool nested_critical_section_is_allowed_in_this_context(void) +/**@brief Returns priority of the currently executing context */ +static int8_t active_vector_priority_get(void) { - return m_nested_critical_section_allowed_priority == - active_priority_convert(nrf_802154_critical_section_active_vector_priority_get()); + return active_priority_convert(nrf_802154_critical_section_active_vector_priority_get()); } static bool critical_section_enter(bool forced) { - bool result = false; - uint8_t cnt; + bool result = false; + int8_t active_vector_priority; + nrf_802154_mcu_critical_state_t mcu_cs; + + /* We assume that preempting interrupts won't change the priority + * of the currently executing one. + */ + active_vector_priority = active_vector_priority_get(); + + nrf_802154_mcu_critical_enter(mcu_cs); if (forced || (m_nested_critical_section_counter == 0) || - nested_critical_section_is_allowed_in_this_context()) + (m_nested_critical_section_allowed_priority == active_vector_priority)) { - nrf_802154_mcu_critical_state_t mcu_cs; + uint8_t cnt = m_nested_critical_section_counter; - nrf_802154_mcu_critical_enter(mcu_cs); + ++cnt; + m_nested_critical_section_counter = cnt; - do + if (cnt == 1U) { - cnt = __LDREXB(&m_nested_critical_section_counter); - - assert(cnt < UINT8_MAX); + nrf_802154_lp_timer_critical_section_enter(); + radio_critical_section_enter(); } - while (__STREXB(cnt + 1, &m_nested_critical_section_counter)); - - nrf_802154_critical_section_rsch_enter(); - nrf_802154_lp_timer_critical_section_enter(); - radio_critical_section_enter(); - - nrf_802154_mcu_critical_exit(mcu_cs); - - m_critical_section_monitor++; result = true; } + nrf_802154_mcu_critical_exit(mcu_cs); + return result; } static void critical_section_exit(void) { - uint8_t cnt = m_nested_critical_section_counter; - uint8_t monitor; - uint8_t atomic_cnt; - static bool exiting_crit_sect; - bool result; - - assert(cnt > 0); + bool succeed = false; do { - monitor = m_critical_section_monitor; + uint8_t cnt; + nrf_802154_mcu_critical_state_t mcu_cs; - // If critical section is not nested exit critical section - if (cnt == 1) + nrf_802154_mcu_critical_enter(mcu_cs); + + cnt = m_nested_critical_section_counter; + + assert(cnt > 0); + + --cnt; + + if (cnt == 0U) { - assert(!exiting_crit_sect); - (void)exiting_crit_sect; - exiting_crit_sect = true; + if (nrf_802154_critical_section_rsch_event_is_pending()) + { + nrf_802154_mcu_critical_exit(mcu_cs); + + nrf_802154_critical_section_rsch_process_pending(); + continue; + } - nrf_802154_critical_section_rsch_exit(); radio_critical_section_exit(); nrf_802154_lp_timer_critical_section_exit(); - - exiting_crit_sect = false; } - do - { - atomic_cnt = __LDREXB(&m_nested_critical_section_counter); - assert(atomic_cnt == cnt); - } - while (__STREXB(atomic_cnt - 1, &m_nested_critical_section_counter)); + m_nested_critical_section_counter = cnt; - // If critical section is not nested verify if during exit procedure RSCH notified - // change of state or critical section was visited by higher priority IRQ meantime. - if (cnt == 1) - { - // Check if critical section must be exited again. - if (nrf_802154_critical_section_rsch_event_is_pending() || - (monitor != m_critical_section_monitor)) - { - result = critical_section_enter(false); - assert(result); - (void)result; - } - else - { - break; - } - } + nrf_802154_mcu_critical_exit(mcu_cs); + + succeed = true; } - while (cnt == 1); + while (!succeed); + } /*************************************************************************************************** @@ -257,8 +236,7 @@ void nrf_802154_critical_section_nesting_allow(void) NESTED_CRITICAL_SECTION_ALLOWED_PRIORITY_NONE); assert(m_nested_critical_section_counter >= 1); - m_nested_critical_section_allowed_priority = active_priority_convert( - nrf_802154_critical_section_active_vector_priority_get()); + m_nested_critical_section_allowed_priority = active_vector_priority_get(); } void nrf_802154_critical_section_nesting_deny(void) diff --git a/drivers/nrf_802154/driver/src/nrf_802154_critical_section.h b/drivers/nrf_802154/driver/src/nrf_802154_critical_section.h index d410914..7e04f65 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_critical_section.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_critical_section.h @@ -106,21 +106,18 @@ bool nrf_802154_critical_section_is_nested(void); */ uint32_t nrf_802154_critical_section_active_vector_priority_get(void); -/** - * @brief Function for entering a critical section in the RSCH module. - */ -extern void nrf_802154_critical_section_rsch_enter(void); - -/** - * @brief Function for exiting a critical section in the RSCH module. - */ -extern void nrf_802154_critical_section_rsch_exit(void); - /** * @brief Checks if there is a pending event in the RSCH critical section. */ extern bool nrf_802154_critical_section_rsch_event_is_pending(void); +/** + * @brief Process a pending RSCH event. + * + * This function must be called from inside of the critical section. + */ +extern void nrf_802154_critical_section_rsch_process_pending(void); + /** *@} **/ diff --git a/drivers/nrf_802154/driver/src/nrf_802154_debug_log.h b/drivers/nrf_802154/driver/src/nrf_802154_debug_log.h index 48e0130..38d24b1 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_debug_log.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_debug_log.h @@ -63,10 +63,10 @@ nrf_802154_sl_log_local_event(verbosity, local_event_id, param_u16) /**@brief Records log about event (with parameter) related to global resource. - * @param verbosity Verbosity level of the module in which log is recorded required to emit log. - * @param event_id Event identifier whose meaning is defined globally. Possible values 0...63 - * @param param_u16 Additional parameter to be logged with event. Meaning - * of the parameter is defined by value of global_event_id. + * @param verbosity Verbosity level of the module in which log is recorded required to emit log. + * @param global_event_id Event identifier whose meaning is defined globally. Possible values 0...63 + * @param param_u16 Additional parameter to be logged with event. Meaning + * of the parameter is defined by value of global_event_id. */ #define nrf_802154_log_global_event(verbosity, global_event_id, param_u16) \ nrf_802154_sl_log_global_event(verbosity, global_event_id, param_u16) diff --git a/drivers/nrf_802154/driver/src/nrf_802154_debug_log_codes.h b/drivers/nrf_802154/driver/src/nrf_802154_debug_log_codes.h index b41ef7b..a2b0f08 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_debug_log_codes.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_debug_log_codes.h @@ -57,11 +57,12 @@ typedef enum NRF_802154_DRV_MODULE_ID_APPLICATION = 1U, NRF_802154_DRV_MODULE_ID_CORE = 2U, NRF_802154_DRV_MODULE_ID_CRITICAL_SECTION = 3U, - NRF_802154_DRV_MODULE_ID_TRX = 4U, - NRF_802154_DRV_MODULE_ID_CSMACA = 5U, - NRF_802154_DRV_MODULE_ID_DELAYED_TRX = 6U, - NRF_802154_DRV_MODULE_ID_ACK_TIMEOUT = 7U, - NRF_802154_DRV_MODULE_ID_TRX_PPI = 8U, + NRF_802154_DRV_MODULE_ID_TRX = 4U, + NRF_802154_DRV_MODULE_ID_CSMACA = 5U, + NRF_802154_DRV_MODULE_ID_DELAYED_TRX = 6U, + NRF_802154_DRV_MODULE_ID_ACK_TIMEOUT = 7U, + NRF_802154_DRV_MODULE_ID_TRX_PPI = 8U, + NRF_802154_DRV_MODULE_ID_NOTIFICATION = 9U } nrf_802154_drv_modules_list_t; /** diff --git a/drivers/nrf_802154/driver/src/nrf_802154_encrypt.c b/drivers/nrf_802154/driver/src/nrf_802154_encrypt.c index 2619980..055478e 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_encrypt.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_encrypt.c @@ -301,6 +301,8 @@ bool nrf_802154_encrypt_ack_prepare(const nrf_802154_frame_parser_data_t * p_ack nrf_802154_aes_ccm_data_t aes_ccm_data; bool success = false; + nrf_802154_aes_ccm_transform_reset(); + if (!nrf_802154_frame_parser_security_enabled_bit_is_set(p_ack_data)) { success = true; @@ -323,6 +325,8 @@ bool nrf_802154_encrypt_tx_setup( nrf_802154_transmit_params_t * p_params, nrf_802154_transmit_failed_notification_t notify_function) { + nrf_802154_aes_ccm_transform_reset(); + if (p_params->frame_props.is_secured) { // The frame is already secured. Pass. @@ -356,7 +360,10 @@ bool nrf_802154_encrypt_tx_setup( if (!success) { - notify_function(p_frame, NRF_802154_TX_ERROR_KEY_ID_INVALID); + nrf_802154_transmit_done_metadata_t metadata = {}; + + metadata.frame_props = p_params->frame_props; + notify_function(p_frame, NRF_802154_TX_ERROR_KEY_ID_INVALID, &metadata); } return success; @@ -375,3 +382,19 @@ void nrf_802154_encrypt_tx_ack_started_hook(uint8_t * p_ack) { nrf_802154_aes_ccm_transform_start(p_ack); } + +bool nrf_802154_encrypt_tx_failed_hook(uint8_t * p_frame, nrf_802154_tx_error_t error) +{ + (void)error; + + nrf_802154_aes_ccm_transform_abort(p_frame); + + return true; +} + +void nrf_802154_encrypt_tx_ack_failed_hook(uint8_t * p_ack, nrf_802154_tx_error_t error) +{ + (void)error; + + nrf_802154_aes_ccm_transform_abort(p_ack); +} diff --git a/drivers/nrf_802154/driver/src/nrf_802154_encrypt.h b/drivers/nrf_802154/driver/src/nrf_802154_encrypt.h index 931c782..277b947 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_encrypt.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_encrypt.h @@ -90,4 +90,26 @@ bool nrf_802154_encrypt_tx_started_hook(uint8_t * p_frame); */ void nrf_802154_encrypt_tx_ack_started_hook(uint8_t * p_ack); +/** + * @brief TX failed hook for the encryption module. + * + * This function aborts the transformation procedure of the provided frame. + * + * @param[in] p_frame Pointer to the buffer that contains a frame being transmitted. + * @param[in] error Cause of the failed transmission. + * + * @retval true Always succeeds. + */ +bool nrf_802154_encrypt_tx_failed_hook(uint8_t * p_frame, nrf_802154_tx_error_t error); + +/** + * @brief ACK TX failed hook for the encryption module. + * + * This function aborts the transformation procedure of the provided ACK frame. + * + * @param[in] p_ack Pointer to the buffer that contains a frame being transmitted. + * @param[in] error Cause of the failed transmission. + */ +void nrf_802154_encrypt_tx_ack_failed_hook(uint8_t * p_ack, nrf_802154_tx_error_t error); + #endif /* NRF_802154_ENCRYPT_H_ */ diff --git a/drivers/nrf_802154/driver/src/nrf_802154_notification.h b/drivers/nrf_802154/driver/src/nrf_802154_notification.h index 4ceadc4..390a3b7 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_notification.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_notification.h @@ -79,14 +79,18 @@ void nrf_802154_notify_received(uint8_t * p_data, int8_t power, uint8_t lqi); /** * @brief Notifies the next higher layer that the reception of a frame failed. * - * @param[in] error Error code that indicates the reason of the failure. - * @param[in] id Identifier of reception window the error occurred in. - * If the error is related to a delayed reception window requested through - * @ref nrf_802154_receive_at, the value of @p id equals the identifier - * of the scheduled reception window. Otherwise, the value of @p id equals - * @ref NRF_802154_RESERVED_IMM_RX_WINDOW_ID. + * @param[in] error Error code that indicates the reason of the failure. + * @param[in] id Identifier of reception window the error occurred in. + * If the error is related to a delayed reception window requested through + * @ref nrf_802154_receive_at, the value of @p id equals the identifier + * of the scheduled reception window. Otherwise, the value of @p id equals + * @ref NRF_802154_RESERVED_IMM_RX_WINDOW_ID. + * @param[in] allow_drop Indicates if the notification can be dropped safely. + * + * @retval true The next higher layer is bound to be notified about the frame reception failure. + * @retval false Notification could not be executed. */ -void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id); +bool nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id, bool allow_drop); /** * @brief Notifies the next higher layer that a frame was transmitted. @@ -109,9 +113,11 @@ void nrf_802154_notify_transmitted(uint8_t * p_frame * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the frame that failed * the transmission operation. * @param[in] error An error code indicating the reason of the failure. + * @param[in] p_metadata Pointer to a metadata structure to be notified. */ -void nrf_802154_notify_transmit_failed(uint8_t * p_frame, - nrf_802154_tx_error_t error); +void nrf_802154_notify_transmit_failed(uint8_t * p_frame, + nrf_802154_tx_error_t error, + const nrf_802154_transmit_done_metadata_t * p_metadata); /** * @brief Notifies the next higher layer that the energy detection procedure ended. diff --git a/drivers/nrf_802154/driver/src/nrf_802154_notification_direct.c b/drivers/nrf_802154/driver/src/nrf_802154_notification_direct.c index d669045..9ab5c25 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_notification_direct.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_notification_direct.c @@ -38,6 +38,8 @@ * */ +#define NRF_802154_MODULE_ID NRF_802154_DRV_MODULE_ID_NOTIFICATION + #include "nrf_802154_notification.h" #include @@ -46,6 +48,7 @@ #include "nrf_802154.h" #include "nrf_802154_critical_section.h" +#include "nrf_802154_debug.h" #include "nrf_802154_tx_work_buffer.h" #define RAW_LENGTH_OFFSET 0 @@ -58,21 +61,35 @@ void nrf_802154_notification_init(void) void nrf_802154_notify_received(uint8_t * p_data, int8_t power, uint8_t lqi) { + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + #if NRF_802154_USE_RAW_API nrf_802154_received_raw(p_data, power, lqi); #else // NRF_802154_USE_RAW_API nrf_802154_received(p_data + RAW_PAYLOAD_OFFSET, p_data[RAW_LENGTH_OFFSET], power, lqi); #endif // NRF_802154_USE_RAW_API + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } -void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id) +bool nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id, bool allow_drop) { + (void)allow_drop; + + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + nrf_802154_receive_failed(error, id); + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); + + return true; } void nrf_802154_notify_transmitted(uint8_t * p_frame, nrf_802154_transmit_done_metadata_t * p_metadata) { + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + // Update the transmitted frame contents and update frame status flags nrf_802154_tx_work_buffer_original_frame_update(p_frame, &p_metadata->frame_props); @@ -88,41 +105,58 @@ void nrf_802154_notify_transmitted(uint8_t * p_frame nrf_802154_transmitted(p_frame + RAW_PAYLOAD_OFFSET, p_metadata); #endif // NRF_802154_USE_RAW_API + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } -void nrf_802154_notify_transmit_failed(uint8_t * p_frame, - nrf_802154_tx_error_t error) +void nrf_802154_notify_transmit_failed(uint8_t * p_frame, + nrf_802154_tx_error_t error, + const nrf_802154_transmit_done_metadata_t * p_metadata) { - nrf_802154_transmit_done_metadata_t metadata = {0}; - - // Update the failed frame contents and update frame status flags - nrf_802154_tx_work_buffer_original_frame_update(p_frame, - &metadata.frame_props); + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); // Notify #if NRF_802154_USE_RAW_API - nrf_802154_transmit_failed(p_frame, error, &metadata); + nrf_802154_transmit_failed(p_frame, error, p_metadata); #else // NRF_802154_USE_RAW_API - nrf_802154_transmit_failed(p_frame + RAW_PAYLOAD_OFFSET, error, &metadata); + nrf_802154_transmit_failed(p_frame + RAW_PAYLOAD_OFFSET, error, p_metadata); #endif // NRF_802154_USE_RAW_API + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } void nrf_802154_notify_energy_detected(uint8_t result) { + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + nrf_802154_energy_detected(result); + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } void nrf_802154_notify_energy_detection_failed(nrf_802154_ed_error_t error) { + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + nrf_802154_energy_detection_failed(error); + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } void nrf_802154_notify_cca(bool is_free) { + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + nrf_802154_cca_done(is_free); + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } void nrf_802154_notify_cca_failed(nrf_802154_cca_error_t error) { + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + nrf_802154_cca_failed(error); + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } diff --git a/drivers/nrf_802154/driver/src/nrf_802154_notification_swi.c b/drivers/nrf_802154/driver/src/nrf_802154_notification_swi.c index d4b78bc..fe1f6a2 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_notification_swi.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_notification_swi.c @@ -38,6 +38,8 @@ * */ +#define NRF_802154_MODULE_ID NRF_802154_DRV_MODULE_ID_NOTIFICATION + #include "nrf_802154_notification.h" #include @@ -47,28 +49,73 @@ #include "nrf_802154.h" #include "nrf_802154_config.h" +#include "nrf_802154_debug.h" #include "nrf_802154_peripherals.h" #include "nrf_802154_queue.h" #include "nrf_802154_swi.h" #include "nrf_802154_tx_work_buffer.h" #include "nrf_802154_utils.h" #include "hal/nrf_egu.h" +#include "rsch/nrf_802154_rsch.h" #define RAW_PAYLOAD_OFFSET 1 #define RAW_LENGTH_OFFSET 0 -/** Size of notification queue. +/** @brief Size of pool of slots for notifications that must not be lost. * - * One slot for each receive buffer, one for transmission, one for busy channel and one for energy - * detection. + * The pool needs to contain slots for: + * - immediate operation result notification + * ~ transmission + * ~ energy detection + * ~ standalone CCA + * - CSMA-CA result notification + * - DTX result notification + * - DRX timeout notifications + * - frame received notifications for each receive buffer. + */ +#define NTF_PRIMARY_POOL_SIZE \ + (NRF_802154_RX_BUFFERS + NRF_802154_RSCH_DLY_TS_OP_DRX_SLOTS + 3) + +/** + * The implementation uses 8-bit integers to address slots with the oldest bit + * indicating pool. That leaves 7 bits for addressing slots within a fixed pool. + * If the pool's size exceeds that width, throw an error. + */ +#if NTF_PRIMARY_POOL_SIZE > 0x7FU +#error NTF_PRIMARY_POOL_SIZE exceeds its bit width +#endif + +/** @brief Size of pool of slots for notifications that can be ignored. + * + * The pool needs to contain slots for failed receptions. Its size is chosen arbitrarily. + */ +#define NTF_SECONDARY_POOL_SIZE 4 + +/** @brief Bitmask that represents slot pool used. + */ +#define NTF_POOL_ID_MASK (1U << 7) + +/** @brief Bitmask that indicates a given slot comes from the primary pool. + */ +#define NTF_PRIMARY_POOL_ID_MASK (1U << 7) + +/** @brief Bitmask that indicates a given slot comes from the secondary pool. + */ +#define NTF_SECONDARY_POOL_ID_MASK 0U + +/** @brief Identifier of an invalid slot. + */ +#define NTF_INVALID_SLOT_ID UINT8_MAX + +/** @brief Size of notification queue. * * One slot is lost due to simplified queue implementation. */ -#define NTF_QUEUE_SIZE ((NRF_802154_RX_BUFFERS + 3) + 1) +#define NTF_QUEUE_SIZE (NTF_PRIMARY_POOL_SIZE + NTF_SECONDARY_POOL_SIZE + 1) -#define NTF_INT NRF_EGU_INT_TRIGGERED0 ///< Label of notification interrupt. -#define NTF_TASK NRF_EGU_TASK_TRIGGER0 ///< Label of notification task. -#define NTF_EVENT NRF_EGU_EVENT_TRIGGERED0 ///< Label of notification event. +#define NTF_INT NRF_EGU_INT_TRIGGERED0 ///< Label of notification interrupt. +#define NTF_TASK NRF_EGU_TASK_TRIGGER0 ///< Label of notification task. +#define NTF_EVENT NRF_EGU_EVENT_TRIGGERED0 ///< Label of notification event. /// Types of notifications in notification queue. typedef enum @@ -86,7 +133,8 @@ typedef enum /// Notification data in the notification queue. typedef struct { - nrf_802154_ntf_type_t type; ///< Notification type. + volatile uint8_t taken; ///< Indicates if the slot is available. + nrf_802154_ntf_type_t type; ///< Notification type. union { @@ -138,11 +186,70 @@ typedef struct } data; ///< Notification data depending on it's type. } nrf_802154_ntf_data_t; -static nrf_802154_queue_t m_notifications_queue; -static nrf_802154_ntf_data_t m_notifications_queue_memory[NTF_QUEUE_SIZE]; +/// Entry in the notification queue +typedef struct +{ + uint8_t id; ///< Identifier of the pool and an entry within. +} nrf_802154_queue_entry_t; + +static nrf_802154_ntf_data_t m_primary_ntf_pool[NTF_PRIMARY_POOL_SIZE]; +static nrf_802154_ntf_data_t m_secondary_ntf_pool[NTF_SECONDARY_POOL_SIZE]; + +static nrf_802154_queue_t m_notifications_queue; +static nrf_802154_queue_entry_t m_notifications_queue_memory[NTF_QUEUE_SIZE]; static volatile nrf_802154_mcu_critical_state_t m_mcu_cs; +/** @brief Allocate notification slot from the specified pool. + * + * @param[inout] p_pool Pointer to a pool of slots. + * @param[in] pool_len Length of the pool. + * + * @return Index of the allocated slot or NTF_INVALID_SLOT_ID in case of failure. + */ +static uint8_t ntf_slot_alloc(nrf_802154_ntf_data_t * p_pool, size_t pool_len) +{ + // Linear search for a free slot + for (size_t i = 0; i < pool_len; i++) + { + bool slot_found = true; + + do + { + uint8_t taken = __LDREXB(&p_pool[i].taken); + + if (taken) + { + // The slot is taken. Proceed to the next slot + __CLREX(); + slot_found = false; + break; + } + } + while (__STREXB(true, &p_pool[i].taken)); + + __DMB(); + + if (slot_found) + { + // Free slot was found and it was successfully marked as taken + return i; + } + } + + return NTF_INVALID_SLOT_ID; +} + +/** @brief Release a slot. + * + * @param[inout] p_slot Pointer to a slot to free. + */ +static void ntf_slot_free(nrf_802154_ntf_data_t * p_slot) +{ + __DMB(); + p_slot->taken = false; +} + /** * Enter notify block. * @@ -151,7 +258,7 @@ static volatile nrf_802154_mcu_critical_state_t m_mcu_cs; * * @return Pointer to an empty slot in the notification queue. */ -static nrf_802154_ntf_data_t * ntf_enter(void) +static nrf_802154_queue_entry_t * ntf_enter(void) { nrf_802154_mcu_critical_enter(m_mcu_cs); @@ -175,6 +282,18 @@ static void ntf_exit(void) nrf_802154_mcu_critical_exit(m_mcu_cs); } +/** @brief Push notification to the queue. + * + * @param[in] slot_id Identifier of the pool and a slot within. + */ +static void ntf_push(uint8_t slot_id) +{ + nrf_802154_queue_entry_t * p_entry = ntf_enter(); + + p_entry->id = slot_id; + ntf_exit(); +} + /** * @brief Notifies the next higher layer that a frame was received. * @@ -183,33 +302,78 @@ static void ntf_exit(void) * @param[in] p_data Pointer to a buffer that contains PHR and PSDU of the received frame. * @param[in] power RSSI measured during the frame reception. * @param[in] lqi LQI that indicates the measured link quality during the frame reception. + * + * @retval true Notification enqueued successfully. + * @retval false Notification could not be performed. */ -void swi_notify_received(uint8_t * p_data, int8_t power, uint8_t lqi) +bool swi_notify_received(uint8_t * p_data, int8_t power, uint8_t lqi) { - nrf_802154_ntf_data_t * p_slot = ntf_enter(); + uint8_t slot_id = ntf_slot_alloc(m_primary_ntf_pool, NTF_PRIMARY_POOL_SIZE); + + if (slot_id == NTF_INVALID_SLOT_ID) + { + // No slots are available. + return false; + } + + nrf_802154_ntf_data_t * p_slot = &m_primary_ntf_pool[slot_id]; p_slot->type = NTF_TYPE_RECEIVED; p_slot->data.received.p_data = p_data; p_slot->data.received.power = power; p_slot->data.received.lqi = lqi; - ntf_exit(); + ntf_push(slot_id | NTF_PRIMARY_POOL_ID_MASK); + + return true; } /** * @brief Notifies the next higher layer that the reception of a frame failed. * * @param[in] error Error code that indicates reason of the failure. + * + * @retval true Notification enqueued successfully. + * @retval false Notification could not be performed. */ -void swi_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id) +bool swi_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id, bool allow_drop) { - nrf_802154_ntf_data_t * p_slot = ntf_enter(); + nrf_802154_ntf_data_t * p_pool; + size_t pool_len; + uint32_t pool_id_bitmask; + + if (!allow_drop) + { + // Choose the primary pool for DRX-related errors + p_pool = m_primary_ntf_pool; + pool_len = NTF_PRIMARY_POOL_SIZE; + pool_id_bitmask = NTF_PRIMARY_POOL_ID_MASK; + } + else + { + // Choose the secondary pool for spurious reception errors + p_pool = m_secondary_ntf_pool; + pool_len = NTF_SECONDARY_POOL_SIZE; + pool_id_bitmask = NTF_SECONDARY_POOL_ID_MASK; + } + + uint8_t slot_id = ntf_slot_alloc(p_pool, pool_len); + + if (slot_id == NTF_INVALID_SLOT_ID) + { + // No slots are available. + return false; + } + + nrf_802154_ntf_data_t * p_slot = &p_pool[slot_id]; p_slot->type = NTF_TYPE_RECEIVE_FAILED; p_slot->data.receive_failed.error = error; p_slot->data.receive_failed.id = id; - ntf_exit(); + ntf_push(slot_id | pool_id_bitmask); + + return true; } /** @@ -219,17 +383,30 @@ void swi_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id) * * @param[in] p_frame Pointer to a buffer that contains PHR and PSDU of the transmitted frame. * @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame. + * + * @retval true Notification enqueued successfully. + * @retval false Notification could not be performed. */ -void swi_notify_transmitted(uint8_t * p_frame, +bool swi_notify_transmitted(uint8_t * p_frame, nrf_802154_transmit_done_metadata_t * p_metadata) { - nrf_802154_ntf_data_t * p_slot = ntf_enter(); + uint8_t slot_id = ntf_slot_alloc(m_primary_ntf_pool, NTF_PRIMARY_POOL_SIZE); + + if (slot_id == NTF_INVALID_SLOT_ID) + { + // No slots are available. + return false; + } + + nrf_802154_ntf_data_t * p_slot = &m_primary_ntf_pool[slot_id]; p_slot->type = NTF_TYPE_TRANSMITTED; p_slot->data.transmitted.p_frame = p_frame; p_slot->data.transmitted.metadata = *p_metadata; - ntf_exit(); + ntf_push(slot_id | NTF_PRIMARY_POOL_ID_MASK); + + return true; } /** @@ -240,19 +417,32 @@ void swi_notify_transmitted(uint8_t * p_frame, * the transmission. * @param[in] error Reason of the transmission failure. * @param[in] p_metadata Pointer to a metadata structure describing frame passed in @p p_frame. + * + * @retval true Notification enqueued successfully. + * @retval false Notification could not be performed. */ -void swi_notify_transmit_failed(uint8_t * p_frame, +bool swi_notify_transmit_failed(uint8_t * p_frame, nrf_802154_tx_error_t error, const nrf_802154_transmit_done_metadata_t * p_metadata) { - nrf_802154_ntf_data_t * p_slot = ntf_enter(); + uint8_t slot_id = ntf_slot_alloc(m_primary_ntf_pool, NTF_PRIMARY_POOL_SIZE); + + if (slot_id == NTF_INVALID_SLOT_ID) + { + // No slots are available. + return false; + } + + nrf_802154_ntf_data_t * p_slot = &m_primary_ntf_pool[slot_id]; p_slot->type = NTF_TYPE_TRANSMIT_FAILED; p_slot->data.transmit_failed.p_frame = p_frame; p_slot->data.transmit_failed.error = error; p_slot->data.transmit_failed.metadata = *p_metadata; - ntf_exit(); + ntf_push(slot_id | NTF_PRIMARY_POOL_ID_MASK); + + return true; } /** @@ -260,15 +450,28 @@ void swi_notify_transmit_failed(uint8_t * p_fr * the SWI priority level. * * @param[in] result Detected energy level. + * + * @retval true Notification enqueued successfully. + * @retval false Notification could not be performed. */ -void swi_notify_energy_detected(uint8_t result) +bool swi_notify_energy_detected(uint8_t result) { - nrf_802154_ntf_data_t * p_slot = ntf_enter(); + uint8_t slot_id = ntf_slot_alloc(m_primary_ntf_pool, NTF_PRIMARY_POOL_SIZE); + + if (slot_id == NTF_INVALID_SLOT_ID) + { + // No slots are available. + return false; + } + + nrf_802154_ntf_data_t * p_slot = &m_primary_ntf_pool[slot_id]; p_slot->type = NTF_TYPE_ENERGY_DETECTED; p_slot->data.energy_detected.result = result; - ntf_exit(); + ntf_push(slot_id | NTF_PRIMARY_POOL_ID_MASK); + + return true; } /** @@ -276,15 +479,28 @@ void swi_notify_energy_detected(uint8_t result) * the SWI priority level. * * @param[in] error Reason of the energy detection failure. + * + * @retval true Notification enqueued successfully. + * @retval false Notification could not be performed. */ -void swi_notify_energy_detection_failed(nrf_802154_ed_error_t error) +bool swi_notify_energy_detection_failed(nrf_802154_ed_error_t error) { - nrf_802154_ntf_data_t * p_slot = ntf_enter(); + uint8_t slot_id = ntf_slot_alloc(m_primary_ntf_pool, NTF_PRIMARY_POOL_SIZE); + + if (slot_id == NTF_INVALID_SLOT_ID) + { + // No slots are available. + return false; + } + + nrf_802154_ntf_data_t * p_slot = &m_primary_ntf_pool[slot_id]; p_slot->type = NTF_TYPE_ENERGY_DETECTION_FAILED; p_slot->data.energy_detection_failed.error = error; - ntf_exit(); + ntf_push(slot_id | NTF_PRIMARY_POOL_ID_MASK); + + return true; } /** @@ -293,15 +509,28 @@ void swi_notify_energy_detection_failed(nrf_802154_ed_error_t error) * The notification is triggered from the SWI priority level. * * @param[in] channel_free If a free channel was detected. + * + * @retval true Notification enqueued successfully. + * @retval false Notification could not be performed. */ -void swi_notify_cca(bool channel_free) +bool swi_notify_cca(bool channel_free) { - nrf_802154_ntf_data_t * p_slot = ntf_enter(); + uint8_t slot_id = ntf_slot_alloc(m_primary_ntf_pool, NTF_PRIMARY_POOL_SIZE); + + if (slot_id == NTF_INVALID_SLOT_ID) + { + // No slots are available. + return false; + } + + nrf_802154_ntf_data_t * p_slot = &m_primary_ntf_pool[slot_id]; p_slot->type = NTF_TYPE_CCA; p_slot->data.cca.result = channel_free; - ntf_exit(); + ntf_push(slot_id | NTF_PRIMARY_POOL_ID_MASK); + + return true; } /** @@ -310,15 +539,28 @@ void swi_notify_cca(bool channel_free) * The notification is triggered from the SWI priority level. * * @param[in] error Reason of the CCA failure. + * + * @retval true Notification enqueued successfully. + * @retval false Notification could not be performed. */ -void swi_notify_cca_failed(nrf_802154_cca_error_t error) +bool swi_notify_cca_failed(nrf_802154_cca_error_t error) { - nrf_802154_ntf_data_t * p_slot = ntf_enter(); + uint8_t slot_id = ntf_slot_alloc(m_primary_ntf_pool, NTF_PRIMARY_POOL_SIZE); + + if (slot_id == NTF_INVALID_SLOT_ID) + { + // No slots are available. + return false; + } + + nrf_802154_ntf_data_t * p_slot = &m_primary_ntf_pool[slot_id]; p_slot->type = NTF_TYPE_CCA_FAILED; p_slot->data.cca_failed.error = error; - ntf_exit(); + ntf_push(slot_id | NTF_PRIMARY_POOL_ID_MASK); + + return true; } void nrf_802154_notification_init(void) @@ -335,65 +577,128 @@ void nrf_802154_notification_init(void) void nrf_802154_notify_received(uint8_t * p_data, int8_t power, uint8_t lqi) { - swi_notify_received(p_data, power, lqi); + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + + bool notified = swi_notify_received(p_data, power, lqi); + + // It should always be possible to notify a successful reception + assert(notified); + (void)notified; + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } -void nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id) +bool nrf_802154_notify_receive_failed(nrf_802154_rx_error_t error, uint32_t id, bool allow_drop) { - swi_notify_receive_failed(error, id); + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + + bool notified = swi_notify_receive_failed(error, id, allow_drop); + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); + + return notified; } void nrf_802154_notify_transmitted(uint8_t * p_frame, nrf_802154_transmit_done_metadata_t * p_metadata) { + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + // Update the transmitted frame contents and update frame status flags nrf_802154_tx_work_buffer_original_frame_update(p_frame, &p_metadata->frame_props); - // Notify - swi_notify_transmitted(p_frame, p_metadata); + bool notified = swi_notify_transmitted(p_frame, p_metadata); + + // It should always be possible to notify transmission result + assert(notified); + (void)notified; + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } -void nrf_802154_notify_transmit_failed(uint8_t * p_frame, - nrf_802154_tx_error_t error) +void nrf_802154_notify_transmit_failed(uint8_t * p_frame, + nrf_802154_tx_error_t error, + const nrf_802154_transmit_done_metadata_t * p_metadata) { - nrf_802154_transmit_done_metadata_t metadata = {0}; + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); - // Update the failed frame contents and update frame status flags - nrf_802154_tx_work_buffer_original_frame_update(p_frame, - &metadata.frame_props); + bool notified = swi_notify_transmit_failed(p_frame, error, p_metadata); - // Notify - swi_notify_transmit_failed(p_frame, error, &metadata); + // It should always be possible to notify transmission result + assert(notified); + (void)notified; + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } void nrf_802154_notify_energy_detected(uint8_t result) { - swi_notify_energy_detected(result); + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + + bool notified = swi_notify_energy_detected(result); + + // It should always be possible to notify energy detection result + assert(notified); + (void)notified; + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } void nrf_802154_notify_energy_detection_failed(nrf_802154_ed_error_t error) { - swi_notify_energy_detection_failed(error); + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + + bool notified = swi_notify_energy_detection_failed(error); + + // It should always be possible to notify energy detection result + assert(notified); + (void)notified; + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } void nrf_802154_notify_cca(bool is_free) { - swi_notify_cca(is_free); + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + + bool notified = swi_notify_cca(is_free); + + // It should always be possible to notify CCA result + assert(notified); + (void)notified; + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } void nrf_802154_notify_cca_failed(nrf_802154_cca_error_t error) { - swi_notify_cca_failed(error); + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + + bool notified = swi_notify_cca_failed(error); + + // It should always be possible to notify CCA result + assert(notified); + (void)notified; + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } /**@brief Handles NTF_EVENT on NRF_802154_EGU_INSTANCE */ static void irq_handler_ntf_event(void) { + nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); + while (!nrf_802154_queue_is_empty(&m_notifications_queue)) { + nrf_802154_queue_entry_t * p_entry = + (nrf_802154_queue_entry_t *)nrf_802154_queue_pop_begin(&m_notifications_queue); + + uint8_t slot_id = p_entry->id & (~NTF_POOL_ID_MASK); + nrf_802154_ntf_data_t * p_slot = - (nrf_802154_ntf_data_t *)nrf_802154_queue_pop_begin(&m_notifications_queue); + (p_entry->id & NTF_POOL_ID_MASK) ? &m_primary_ntf_pool[slot_id] : + &m_secondary_ntf_pool[slot_id]; switch (p_slot->type) { @@ -468,7 +773,10 @@ static void irq_handler_ntf_event(void) } nrf_802154_queue_pop_commit(&m_notifications_queue); + ntf_slot_free(p_slot); } + + nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_LOW); } void nrf_802154_notification_swi_irq_handler(void) diff --git a/drivers/nrf_802154/driver/src/nrf_802154_peripherals_alloc.c b/drivers/nrf_802154/driver/src/nrf_802154_peripherals_alloc.c new file mode 100644 index 0000000..ddbebf4 --- /dev/null +++ b/drivers/nrf_802154/driver/src/nrf_802154_peripherals_alloc.c @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file + * This file supplies bitmasks specifying which of the peripherals are used + * by the 802.15.4 driver. + * + * Bitmasks currently provided applies to: + * - PPI or DPPI channels (g_nrf_802154_used_nrf_ppi_channels) + * - PPI or DPPI channel groups (g_nrf_802154_used_nrf_ppi_groups) + */ + +#include "nrf_802154_peripherals.h" + +#include + +#if NRF_802154_VERIFY_PERIPHS_ALLOC_AGAINST_MPSL +/* Obtaining the MPSL_RESERVED_.. macros */ +#include "mpsl.h" +#endif + +#if defined(NRF52_SERIES) +#define NRF_802154_PPI_CH_USED_MSK NRF_802154_PPI_CHANNELS_USED_MASK +#define NRF_802154_PPI_GR_USED_MSK NRF_802154_PPI_GROUPS_USED_MASK +#elif defined(NRF53_SERIES) +#define NRF_802154_PPI_CH_USED_MSK NRF_802154_DPPI_CHANNELS_USED_MASK +#define NRF_802154_PPI_GR_USED_MSK NRF_802154_DPPI_GROUPS_USED_MASK +#else +#error Unsupported chip family +#endif + +const uint32_t g_nrf_802154_used_nrf_ppi_channels = NRF_802154_PPI_CH_USED_MSK; +const uint32_t g_nrf_802154_used_nrf_ppi_groups = NRF_802154_PPI_GR_USED_MSK; + +#if NRF_802154_VERIFY_PERIPHS_ALLOC_AGAINST_MPSL + +#if ((NRF_802154_PPI_CH_USED_MSK & MPSL_RESERVED_PPI_CHANNELS) != 0UL) +#error PPI channels for 802.15.4 driver overlap with MPSL channels +#endif + +#if ((NRF_802154_PPI_GR_USED_MSK & MPSL_RESERVED_PPI_GROUPS) != 0UL) +#error PPI groups for 802.15.4 driver overlap with MPSL groups +#endif + +#endif // NRF_802154_VERIFY_PERIPHS_ALLOC_AGAINST_MPSL diff --git a/drivers/nrf_802154/driver/src/nrf_802154_peripherals_nrf52.h b/drivers/nrf_802154/driver/src/nrf_802154_peripherals_nrf52.h index 95583e4..7889da9 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_peripherals_nrf52.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_peripherals_nrf52.h @@ -344,7 +344,7 @@ extern "C" { #endif /** - * @def NRF_80254_PPI_CHANNELS_USED_MASK + * @def NRF_802154_PPI_CHANNELS_USED_MASK * * Bit mask of PPI channels used by the 802.15.4 driver. */ diff --git a/drivers/nrf_802154/driver/src/nrf_802154_peripherals_nrf53.h b/drivers/nrf_802154/driver/src/nrf_802154_peripherals_nrf53.h index 77a7c0a..7eeb41a 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_peripherals_nrf53.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_peripherals_nrf53.h @@ -44,6 +44,7 @@ #include #include "nrf_802154_config.h" #include "nrf_802154_debug.h" +#include "nrf_802154_sl_periphs.h" #ifdef __cplusplus extern "C" { @@ -113,15 +114,63 @@ extern "C" { #endif /** - * @def NRF_802154_DPPI_RADIO_DISABLED_TO_EGU + * @def NRF_802154_DPPI_RADIO_DISABLED * - * The DPPI channel that connects RADIO_DISABLED event to EGU task. + * The DPPI channel that publishes RADIO_DISABLED event. * * @note This option is used by the core module regardless of the driver configuration. * */ -#ifndef NRF_802154_DPPI_RADIO_DISABLED_TO_EGU -#define NRF_802154_DPPI_RADIO_DISABLED_TO_EGU 6U +#ifndef NRF_802154_DPPI_RADIO_DISABLED +#define NRF_802154_DPPI_RADIO_DISABLED 7U +#endif + +/** + * @def NRF_802154_DPPI_RADIO_READY + * + * The DPPI channel that publishes RADIO_READY event. + * + * @note This option is used by the core module regardless of the driver configuration. + * + */ +#ifndef NRF_802154_DPPI_RADIO_READY +#define NRF_802154_DPPI_RADIO_READY 4U +#endif + +/** + * @def NRF_802154_DPPI_RADIO_ADDRESS + * + * The DPPI channel that publishes RADIO_ADDRESS event. + * + * @note This option is used by the core module regardless of the driver configuration. + * + */ +#ifndef NRF_802154_DPPI_RADIO_ADDRESS +#define NRF_802154_DPPI_RADIO_ADDRESS 5U +#endif + +/** + * @def NRF_802154_DPPI_RADIO_END + * + * The DPPI channel that publishes RADIO_END event. + * + * @note This option is used by the core module regardless of the driver configuration. + * + */ +#ifndef NRF_802154_DPPI_RADIO_END +#define NRF_802154_DPPI_RADIO_END 6U +#endif + +/** + * @def NRF_802154_DPPI_RADIO_PHYEND + * + * The DPPI channel that publishes RADIO_PHYEND event. + * + * @note This option is used by the core module regardless of the driver configuration. + * + */ +#ifndef NRF_802154_DPPI_RADIO_PHYEND +#define NRF_802154_DPPI_RADIO_PHYEND 12U #endif /** @@ -134,7 +183,7 @@ extern "C" { * */ #ifndef NRF_802154_DPPI_EGU_TO_RADIO_RAMP_UP -#define NRF_802154_DPPI_EGU_TO_RADIO_RAMP_UP 7U +#define NRF_802154_DPPI_EGU_TO_RADIO_RAMP_UP 10U #endif /** @@ -147,7 +196,7 @@ extern "C" { * */ #ifndef NRF_802154_DPPI_TIMER_COMPARE_TO_RADIO_TXEN -#define NRF_802154_DPPI_TIMER_COMPARE_TO_RADIO_TXEN 7U +#define NRF_802154_DPPI_TIMER_COMPARE_TO_RADIO_TXEN 10U #endif /** @@ -161,6 +210,28 @@ extern "C" { #define NRF_802154_DPPI_RADIO_SYNC_TO_EGU_SYNC 8U #endif +/** + * @def NRF_802154_DPPI_RADIO_CCAIDLE + * + * The DPPI channel that RADIO.CCAIDLE event publishes to + */ +#ifndef NRF_802154_DPPI_RADIO_CCAIDLE +#define NRF_802154_DPPI_RADIO_CCAIDLE 9U +#endif + +/** + * @def NRF_802154_DPPI_TIMESTAMPS_USED_MASK + * + * Helper bit mask of DPPI channels used by the 802.15.4 driver for timestamping. + */ +#ifdef NRF_802154_FRAME_TIMESTAMP_ENABLED +#define NRF_802154_DPPI_TIMESTAMPS_USED_MASK \ + ((1UL << NRF_802154_PPI_RTC_COMPARE_TO_TIMER_CAPTURE) | \ + (1UL << NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE)) +#else // NRF_802154_FRAME_TIMESTAMP_ENABLED +#define NRF_802154_DPPI_TIMESTAMPS_USED_MASK 0U +#endif // NRF_802154_FRAME_TIMESTAMP_ENABLED + /** * @def NRF_802154_DPPI_CHANNELS_USED_MASK * @@ -168,10 +239,16 @@ extern "C" { */ #ifndef NRF_802154_DPPI_CHANNELS_USED_MASK #define NRF_802154_DPPI_CHANNELS_USED_MASK ( \ - (1UL << NRF_802154_DPPI_RADIO_DISABLED_TO_EGU) | \ + (1UL << NRF_802154_DPPI_RADIO_DISABLED) | \ + (1UL << NRF_802154_DPPI_RADIO_READY) | \ + (1UL << NRF_802154_DPPI_RADIO_ADDRESS) | \ + (1UL << NRF_802154_DPPI_RADIO_END) | \ + (1UL << NRF_802154_DPPI_RADIO_PHYEND) | \ (1UL << NRF_802154_DPPI_EGU_TO_RADIO_RAMP_UP) | \ (1UL << NRF_802154_DPPI_TIMER_COMPARE_TO_RADIO_TXEN) | \ - (1UL << NRF_802154_DPPI_RADIO_SYNC_TO_EGU_SYNC)) + (1UL << NRF_802154_DPPI_RADIO_SYNC_TO_EGU_SYNC) | \ + (1UL << NRF_802154_DPPI_RADIO_CCAIDLE) | \ + NRF_802154_DPPI_TIMESTAMPS_USED_MASK) #endif // NRF_802154_DPPI_CHANNELS_USED_MASK /** diff --git a/drivers/nrf_802154/driver/src/nrf_802154_pib.c b/drivers/nrf_802154/driver/src/nrf_802154_pib.c index f8d063d..85b98e8 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_pib.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_pib.c @@ -47,7 +47,6 @@ #include "nrf_802154_config.h" #include "nrf_802154_const.h" -#include "nrf_802154_nrfx_addons.h" #include "nrf_802154_utils.h" #include "fal/nrf_802154_fal.h" diff --git a/drivers/nrf_802154/driver/src/nrf_802154_request.h b/drivers/nrf_802154/driver/src/nrf_802154_request.h index ecf24ff..d012974 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_request.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_request.h @@ -125,6 +125,8 @@ bool nrf_802154_request_energy_detection(nrf_802154_term_t term_lvl, uint32_t ti */ bool nrf_802154_request_cca(nrf_802154_term_t term_lvl); +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + /** * @brief Requests entering the @ref RADIO_STATE_CONTINUOUS_CARRIER state. * @@ -139,6 +141,7 @@ bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl); * @brief Requests entering the @ref RADIO_STATE_MODULATED_CARRIER state. * * @param[in] term_lvl Termination level of this request. Selects procedures to abort. + * @param[in] p_data Pointer to a buffer to modulate the carrier with. * * @retval true The driver will enter the modulated carrier state. * @retval false The driver cannot enter the modulated carrier state due to an ongoing operation. @@ -146,6 +149,8 @@ bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl); bool nrf_802154_request_modulated_carrier(nrf_802154_term_t term_lvl, const uint8_t * p_data); +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + /** * @brief Requests the driver to free the given buffer. * @@ -180,6 +185,76 @@ bool nrf_802154_request_rssi_measure(void); */ bool nrf_802154_request_rssi_measurement_get(int8_t * p_rssi); +#if NRF_802154_DELAYED_TRX_ENABLED +/** + * @brief Requests a call to @ref nrf_802154_delayed_trx_transmit. + * + * @param[in] p_data Pointer to the array with data to transmit. The first byte must contain + * the frame length (including FCS). The following bytes contain data. + * The CRC is computed automatically by the radio hardware. Therefore, + * the FCS field can contain any bytes. + * @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler, + * in microseconds (us). + * @param[in] dt Delta of delay time from @p t0, in microseconds (us). + * @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data + * to transmit. If @c NULL following metadata are used: + * Field | Value + * ----------------|----------------------------------------------------- + * @c frame_props | @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT + * @c cca | @c true + * @c channel | As returned by @ref nrf_802154_channel_get + * + * @retval true The transmission procedure was scheduled. + * @retval false The driver could not schedule the transmission procedure. + */ +bool nrf_802154_request_transmit_raw_at(uint8_t * p_data, + uint32_t t0, + uint32_t dt, + const nrf_802154_transmit_at_metadata_t * p_metadata); + +/** + * @brief Requests a call to @ref nrf_802154_delayed_trx_transmit_cancel. + * + * @retval true The delayed transmission was scheduled and successfully cancelled. + * @retval false No delayed transmission was scheduled. + */ +bool nrf_802154_request_transmit_at_cancel(void); + +/** + * @brief Requests a call to @ref nrf_802154_delayed_trx_receive. + * + * @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler, + * in microseconds (us). + * @param[in] dt Delta of delay time from @p t0, in microseconds (us). + * @param[in] timeout Reception timeout (counted from @p t0 + @p dt), in microseconds (us). + * @param[in] channel Radio channel on which the frame is to be received. + * @param[in] id Identifier of the scheduled reception window. If the reception has been + * scheduled successfully, the value of this parameter can be used in + * @ref nrf_802154_receive_at_cancel to cancel it. + * + * @retval true The reception procedure was scheduled. + * @retval false The driver could not schedule the reception procedure. + */ +bool nrf_802154_request_receive_at(uint32_t t0, + uint32_t dt, + uint32_t timeout, + uint8_t channel, + uint32_t id); + +/** + * @brief Requests a call to @ref nrf_802154_delayed_trx_receive_cancel. + * + * @param[in] id Identifier of the delayed reception window to be cancelled. If the provided + * value does not refer to any scheduled or active receive window, the function + * returns false. + * + * @retval true The delayed reception was scheduled and successfully cancelled. + * @retval false No delayed reception was scheduled. + */ +bool nrf_802154_request_receive_at_cancel(uint32_t id); + +#endif // NRF_802154_DELAYED_TRX_ENABLED + /** *@} **/ diff --git a/drivers/nrf_802154/driver/src/nrf_802154_request_direct.c b/drivers/nrf_802154/driver/src/nrf_802154_request_direct.c index 20101ee..4b9d0d0 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_request_direct.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_request_direct.c @@ -44,6 +44,7 @@ #include #include "nrf_802154_core.h" +#include "mac_features/nrf_802154_delayed_trx.h" #include "hal/nrf_radio.h" #define REQUEST_FUNCTION_PARMS(func_core, ...) \ @@ -108,6 +109,8 @@ bool nrf_802154_request_cca(nrf_802154_term_t term_lvl) REQUEST_FUNCTION_PARMS(nrf_802154_core_cca, term_lvl) } +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl) { REQUEST_FUNCTION_PARMS(nrf_802154_core_continuous_carrier, term_lvl) @@ -119,6 +122,8 @@ bool nrf_802154_request_modulated_carrier(nrf_802154_term_t term_lvl, REQUEST_FUNCTION_PARMS(nrf_802154_core_modulated_carrier, term_lvl, p_data) } +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + bool nrf_802154_request_buffer_free(uint8_t * p_data) { REQUEST_FUNCTION_PARMS(nrf_802154_core_notify_buffer_free, p_data) @@ -148,3 +153,38 @@ bool nrf_802154_request_rssi_measurement_get(int8_t * p_rssi) { REQUEST_FUNCTION_PARMS(nrf_802154_core_last_rssi_measurement_get, p_rssi) } + +static inline bool are_frame_properties_valid(const nrf_802154_transmitted_frame_props_t * p_props) +{ + return p_props->dynamic_data_is_set || !(p_props->is_secured); +} + +#if NRF_802154_DELAYED_TRX_ENABLED +bool nrf_802154_request_transmit_raw_at(uint8_t * p_data, + uint32_t t0, + uint32_t dt, + const nrf_802154_transmit_at_metadata_t * p_metadata) +{ + REQUEST_FUNCTION_PARMS(nrf_802154_delayed_trx_transmit, p_data, t0, dt, p_metadata); +} + +bool nrf_802154_request_transmit_at_cancel(void) +{ + REQUEST_FUNCTION(nrf_802154_delayed_trx_transmit_cancel); +} + +bool nrf_802154_request_receive_at(uint32_t t0, + uint32_t dt, + uint32_t timeout, + uint8_t channel, + uint32_t id) +{ + REQUEST_FUNCTION_PARMS(nrf_802154_delayed_trx_receive, t0, dt, timeout, channel, id); +} + +bool nrf_802154_request_receive_at_cancel(uint32_t id) +{ + REQUEST_FUNCTION_PARMS(nrf_802154_delayed_trx_receive_cancel, id); +} + +#endif diff --git a/drivers/nrf_802154/driver/src/nrf_802154_request_swi.c b/drivers/nrf_802154/driver/src/nrf_802154_request_swi.c index 5d33f3a..ca11eb8 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_request_swi.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_request_swi.c @@ -52,9 +52,11 @@ #include "nrf_802154_queue.h" #include "nrf_802154_rx_buffer.h" #include "nrf_802154_swi.h" +#include "nrf_802154_types.h" #include "nrf_802154_utils.h" #include "hal/nrf_radio.h" #include "hal/nrf_egu.h" +#include "mac_features/nrf_802154_delayed_trx.h" #include "platform/nrf_802154_irq.h" #include @@ -85,6 +87,10 @@ typedef enum REQ_TYPE_RSSI_MEASURE, REQ_TYPE_RSSI_GET, REQ_TYPE_ANTENNA_UPDATE, + REQ_TYPE_TRANSMIT_AT, + REQ_TYPE_TRANSMIT_AT_CANCEL, + REQ_TYPE_RECEIVE_AT, + REQ_TYPE_RECEIVE_AT_CANCEL, } nrf_802154_req_type_t; /// Request data in request queue. @@ -133,6 +139,7 @@ typedef struct bool * p_result; ///< CCA request result. } cca; ///< CCA request details. +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED struct { nrf_802154_term_t term_lvl; ///< Request priority. @@ -145,6 +152,7 @@ typedef struct const uint8_t * p_data; ///< Pointer to a buffer to modulate the carrier wave with. bool * p_result; ///< Modulated carrier request result. } modulated_carrier; ///< Modulated carrier request details. +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED struct { @@ -178,7 +186,41 @@ typedef struct { bool * p_result; ///< Antenna update request result. } antenna_update; ///< Antenna update request details. - } data; ///< Request data depending on its type. + +#if NRF_802154_DELAYED_TRX_ENABLED + struct + { + uint8_t * p_data; + uint32_t t0; + uint32_t dt; + const nrf_802154_transmit_at_metadata_t * p_metadata; + bool * p_result; + } transmit_at; + + struct + { + bool * p_result; + } transmit_at_cancel; + + struct + { + uint32_t t0; + uint32_t dt; + uint32_t timeout; + uint8_t channel; + uint32_t id; + bool * p_result; + } receive_at; + + struct + { + uint32_t id; + bool * p_result; + } receive_at_cancel; + +#endif // NRF_802154_DELAYED_TRX_ENABLED + + } data; ///< Request data depending on its type. } nrf_802154_req_data_t; /**@brief Instance of a requests queue */ @@ -388,6 +430,8 @@ static void swi_cca(nrf_802154_term_t term_lvl, bool * p_result) req_exit(); } +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + /** * @brief Requests entering the @ref RADIO_STATE_CONTINUOUS_CARRIER state from the SWI priority. * @@ -426,6 +470,8 @@ static void swi_modulated_carrier(nrf_802154_term_t term_lvl, req_exit(); } +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + /** * @brief Notifies the core module that the given buffer is not used anymore and can be freed. * @@ -527,6 +573,68 @@ static void swi_rssi_measurement_get(int8_t * p_rssi, bool * p_result) req_exit(); } +#if NRF_802154_DELAYED_TRX_ENABLED +static void swi_transmit_at(uint8_t * p_data, + uint32_t t0, + uint32_t dt, + const nrf_802154_transmit_at_metadata_t * p_metadata, + bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_TRANSMIT_AT; + p_slot->data.transmit_at.p_data = p_data; + p_slot->data.transmit_at.t0 = t0; + p_slot->data.transmit_at.dt = dt; + p_slot->data.transmit_at.p_metadata = p_metadata; + p_slot->data.transmit_at.p_result = p_result; + + req_exit(); +} + +static void swi_transmit_at_cancel(bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_TRANSMIT_AT_CANCEL; + p_slot->data.transmit_at_cancel.p_result = p_result; + + req_exit(); +} + +static void swi_receive_at(uint32_t t0, + uint32_t dt, + uint32_t timeout, + uint8_t channel, + uint32_t id, + bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_RECEIVE_AT; + p_slot->data.receive_at.t0 = t0; + p_slot->data.receive_at.dt = dt; + p_slot->data.receive_at.timeout = timeout; + p_slot->data.receive_at.channel = channel; + p_slot->data.receive_at.id = id; + p_slot->data.receive_at.p_result = p_result; + + req_exit(); +} + +static void swi_receive_at_cancel(uint32_t id, bool * p_result) +{ + nrf_802154_req_data_t * p_slot = req_enter(); + + p_slot->type = REQ_TYPE_RECEIVE_AT_CANCEL; + p_slot->data.receive_at_cancel.id = id; + p_slot->data.receive_at_cancel.p_result = p_result; + + req_exit(); +} + +#endif // NRF_802154_DELAYED_TRX_ENABLED + void nrf_802154_request_init(void) { nrf_802154_queue_init(&m_requests_queue, @@ -588,6 +696,7 @@ bool nrf_802154_request_cca(nrf_802154_term_t term_lvl) REQUEST_FUNCTION(nrf_802154_core_cca, swi_cca, term_lvl) } +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED bool nrf_802154_request_continuous_carrier(nrf_802154_term_t term_lvl) { REQUEST_FUNCTION(nrf_802154_core_continuous_carrier, @@ -604,6 +713,8 @@ bool nrf_802154_request_modulated_carrier(nrf_802154_term_t term_lvl, p_data) } +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + bool nrf_802154_request_buffer_free(uint8_t * p_data) { REQUEST_FUNCTION(nrf_802154_core_notify_buffer_free, swi_buffer_free, p_data) @@ -636,6 +747,36 @@ bool nrf_802154_request_rssi_measurement_get(int8_t * p_rssi) p_rssi) } +#if NRF_802154_DELAYED_TRX_ENABLED +bool nrf_802154_request_transmit_raw_at(uint8_t * p_data, + uint32_t t0, + uint32_t dt, + const nrf_802154_transmit_at_metadata_t * p_metadata) +{ + REQUEST_FUNCTION(nrf_802154_delayed_trx_transmit, swi_transmit_at, p_data, t0, dt, p_metadata); +} + +bool nrf_802154_request_transmit_at_cancel(void) +{ + REQUEST_FUNCTION_NO_ARGS(nrf_802154_delayed_trx_transmit_cancel, swi_transmit_at_cancel); +} + +bool nrf_802154_request_receive_at(uint32_t t0, + uint32_t dt, + uint32_t timeout, + uint8_t channel, + uint32_t id) +{ + REQUEST_FUNCTION(nrf_802154_delayed_trx_receive, swi_receive_at, t0, dt, timeout, channel, id); +} + +bool nrf_802154_request_receive_at_cancel(uint32_t id) +{ + REQUEST_FUNCTION(nrf_802154_delayed_trx_receive_cancel, swi_receive_at_cancel, id); +} + +#endif // NRF_802154_DELAYED_TRX_ENABLED + /**@brief Handles REQ_EVENT on NRF_802154_EGU_INSTANCE */ static void irq_handler_req_event(void) { @@ -680,6 +821,8 @@ static void irq_handler_req_event(void) *(p_slot->data.cca.p_result) = nrf_802154_core_cca(p_slot->data.cca.term_lvl); break; +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + case REQ_TYPE_CONTINUOUS_CARRIER: *(p_slot->data.continuous_carrier.p_result) = nrf_802154_core_continuous_carrier( @@ -692,6 +835,8 @@ static void irq_handler_req_event(void) p_slot->data.modulated_carrier.p_data); break; +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + case REQ_TYPE_BUFFER_FREE: *(p_slot->data.buffer_free.p_result) = nrf_802154_core_notify_buffer_free(p_slot->data.buffer_free.p_data); @@ -719,6 +864,35 @@ static void irq_handler_req_event(void) *(p_slot->data.antenna_update.p_result) = nrf_802154_core_antenna_update(); break; +#if NRF_802154_DELAYED_TRX_ENABLED + case REQ_TYPE_TRANSMIT_AT: + *(p_slot->data.transmit_at.p_result) = + nrf_802154_delayed_trx_transmit(p_slot->data.transmit_at.p_data, + p_slot->data.transmit_at.t0, + p_slot->data.transmit_at.dt, + p_slot->data.transmit_at.p_metadata); + break; + + case REQ_TYPE_TRANSMIT_AT_CANCEL: + *(p_slot->data.transmit_at_cancel.p_result) = + nrf_802154_delayed_trx_transmit_cancel(); + break; + + case REQ_TYPE_RECEIVE_AT: + *(p_slot->data.receive_at.p_result) = + nrf_802154_delayed_trx_receive(p_slot->data.receive_at.t0, + p_slot->data.receive_at.dt, + p_slot->data.receive_at.timeout, + p_slot->data.receive_at.channel, + p_slot->data.receive_at.id); + break; + + case REQ_TYPE_RECEIVE_AT_CANCEL: + *(p_slot->data.receive_at_cancel.p_result) = + nrf_802154_delayed_trx_receive_cancel(p_slot->data.receive_at_cancel.id); + break; +#endif // NRF_802154_DELAYED_TRX_ENABLED + default: assert(false); } diff --git a/drivers/nrf_802154/driver/src/nrf_802154_rssi.h b/drivers/nrf_802154/driver/src/nrf_802154_rssi.h index ecd1ef1..0051b0b 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_rssi.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_rssi.h @@ -38,7 +38,7 @@ #include /** - * @defgroup nrf_802154_rssi RSSI calculations used internally in the 802.15.4 driver + * @defgroup nrf_802154_rssi RSSI measurement function * @{ * @ingroup nrf_802154 * @brief RSSI calculations used internally in the 802.15.4 driver. diff --git a/drivers/nrf_802154/driver/src/nrf_802154_swi.c b/drivers/nrf_802154/driver/src/nrf_802154_swi.c index 4108c10..a4e9217 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_swi.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_swi.c @@ -48,7 +48,6 @@ #include "nrf_802154.h" #include "nrf_802154_config.h" #include "nrf_802154_peripherals.h" -#include "nrf_802154_utils.h" #include "platform/nrf_802154_irq.h" #if NRF_802154_INTERNAL_SWI_IRQ_HANDLING diff --git a/drivers/nrf_802154/driver/src/nrf_802154_trx.c b/drivers/nrf_802154/driver/src/nrf_802154_trx.c index aaed348..b2937ec 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_trx.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_trx.c @@ -41,7 +41,6 @@ #include "nrf_802154_config.h" #include "nrf_802154_const.h" -#include "nrf_802154_nrfx_addons.h" #include "nrf_802154_types.h" #include "nrf_802154_peripherals.h" #include "nrf_802154_pib.h" @@ -57,8 +56,8 @@ #include "nrf_802154_procedures_duration.h" #include "nrf_802154_critical_section.h" #include "mpsl_fem_config_common.h" -#include "mpsl_fem_protocol_api.h" #include "platform/nrf_802154_irq.h" +#include "protocol/mpsl_fem_protocol_api.h" #include "nrf_802154_sl_ant_div.h" @@ -76,6 +75,7 @@ #elif defined(NRF5340_XXAA) #define PPI_CCAIDLE_FEM 0 #define RADIO_BASE NRF_RADIO_NS_BASE +#define FICR_BASE NRF_FICR_NS_BASE #endif #if NRF_802154_DISABLE_BCC_MATCHING @@ -133,9 +133,8 @@ void nrf_802154_radio_irq_handler(void); ///< Prototype required by internal RAD /// Common parameters for the FEM handling. static const mpsl_fem_event_t m_activate_rx_cc0 = { - .type = MPSL_FEM_EVENT_TYPE_TIMER, - .override_ppi = false, - .event.timer = + .type = MPSL_FEM_EVENT_TYPE_TIMER, + .event.timer = { .p_timer_instance = NRF_802154_TIMER_INSTANCE, .compare_channel_mask = ((1 << NRF_TIMER_CC_CHANNEL0) | (1 << NRF_TIMER_CC_CHANNEL2)), @@ -147,9 +146,8 @@ static const mpsl_fem_event_t m_activate_rx_cc0 = static const mpsl_fem_event_t m_activate_tx_cc0 = { - .type = MPSL_FEM_EVENT_TYPE_TIMER, - .override_ppi = false, - .event.timer = + .type = MPSL_FEM_EVENT_TYPE_TIMER, + .event.timer = { .p_timer_instance = NRF_802154_TIMER_INSTANCE, .compare_channel_mask = ((1 << NRF_TIMER_CC_CHANNEL0) | (1 << NRF_TIMER_CC_CHANNEL2)), @@ -161,10 +159,14 @@ static const mpsl_fem_event_t m_activate_tx_cc0 = static const mpsl_fem_event_t m_ccaidle = { - .type = MPSL_FEM_EVENT_TYPE_GENERIC, - .override_ppi = true, - .ppi_ch_id = PPI_CCAIDLE_FEM, - .event.generic.register_address = ((uint32_t)RADIO_BASE + (uint32_t)NRF_RADIO_EVENT_CCAIDLE) + .type = MPSL_FEM_EVENT_TYPE_GENERIC, +#if defined(NRF52_SERIES) + .override_ppi = true, + .ppi_ch_id = PPI_CCAIDLE_FEM, + .event.generic.event = ((uint32_t)RADIO_BASE + (uint32_t)NRF_RADIO_EVENT_CCAIDLE) +#elif defined(NRF53_SERIES) + .event.generic.event = NRF_802154_DPPI_RADIO_CCAIDLE +#endif }; /**@brief Fal event used by @ref nrf_802154_trx_transmit_ack and @ref txack_finish */ @@ -207,8 +209,12 @@ static void receive_ack_abort(void); static void transmit_frame_abort(void); static void transmit_ack_abort(void); static void standalone_cca_abort(void); + +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED static void continuous_carrier_abort(void); static void modulated_carrier_abort(void); + +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED static void energy_detection_abort(void); /** Clear flags describing frame being received. */ @@ -310,6 +316,9 @@ static void fem_for_lna_reset(void) nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN); nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK); nrf_802154_trx_ppi_for_fem_clear(); + /* There is no need to explicitly deactivate LNA pin during reset as mpsl_fem_abort_set is used + * to provide a deactivation mechanism on DISABLED event. + */ } /** Configure FEM to set PA at appropriate time. @@ -406,31 +415,51 @@ static void fem_for_tx_reset(bool cca) static void device_config_254_apply_tx(void) { uint32_t ficr_reg1 = *(volatile uint32_t *)0x10000330UL; + uint32_t ficr_reg2 = *(volatile uint32_t *)0x10000334UL; + uint32_t ficr_reg3 = *(volatile uint32_t *)0x10000338UL; - /* Check if the device is fixed by testing FICR register value. - * - * Only one of the FICR register is tested to optimize the procedure. All the registers shall - * have consistent values, i.e. all registers contain reset values or all registers contain - * values that shall be written to to the radio registers. If it is not true, then it is - * a hardware bug. - */ + /* Check if the device is fixed by testing every FICR register's value separately. */ if (ficr_reg1 != 0xffffffffUL) { volatile uint32_t * p_radio_reg1 = (volatile uint32_t *)0x4000174cUL; - volatile uint32_t * p_radio_reg2 = (volatile uint32_t *)0x40001584UL; - volatile uint32_t * p_radio_reg3 = (volatile uint32_t *)0x40001588UL; - - uint32_t ficr_reg2 = *(volatile uint32_t *)0x10000334UL; - uint32_t ficr_reg3 = *(volatile uint32_t *)0x10000338UL; *p_radio_reg1 = ficr_reg1; + } + + if (ficr_reg2 != 0xffffffffUL) + { + volatile uint32_t * p_radio_reg2 = (volatile uint32_t *)0x40001584UL; + *p_radio_reg2 = ficr_reg2; + } + + if (ficr_reg3 != 0xffffffffUL) + { + volatile uint32_t * p_radio_reg3 = (volatile uint32_t *)0x40001588UL; + *p_radio_reg3 = ficr_reg3; } } #endif +/** @brief Applies ERRATA-117 + * + * Shall be called after setting RADIO mode to NRF_RADIO_MODE_IEEE802154_250KBIT. + */ +#if defined(NRF5340_XXAA) +static void errata_117_apply(void) +{ + /* Register at 0x01FF0084. */ + uint32_t ficr_reg = *(volatile uint32_t *)(FICR_BASE + 0x84UL); + /* Register at 0x41008588. */ + volatile uint32_t * p_radio_reg = (volatile uint32_t *)(RADIO_BASE + 0x588UL); + + *p_radio_reg = ficr_reg; +} + +#endif + void nrf_802154_trx_module_reset(void) { m_trx_state = TRX_STATE_DISABLED; @@ -478,6 +507,11 @@ void nrf_802154_trx_enable(void) nrf_radio_mode_set(NRF_RADIO, NRF_RADIO_MODE_IEEE802154_250KBIT); +#if defined(NRF5340_XXAA) + // Apply ERRATA-117 after setting RADIO mode to NRF_RADIO_MODE_IEEE802154_250KBIT. + errata_117_apply(); +#endif + memset(&packet_conf, 0, sizeof(packet_conf)); packet_conf.lflen = 8; packet_conf.plen = NRF_RADIO_PREAMBLE_LENGTH_32BIT_ZERO; @@ -490,6 +524,8 @@ void nrf_802154_trx_enable(void) // Configure CRC nrf_radio_crc_configure(NRF_RADIO, CRC_LENGTH, NRF_RADIO_CRC_ADDR_IEEE802154, CRC_POLYNOMIAL); + nrf_802154_trx_ppi_for_enable(); + // Configure CCA cca_configuration_update(); @@ -509,6 +545,9 @@ void nrf_802154_trx_enable(void) defined(NRF52811_XXAA) mpsl_fem_abort_set(nrf_radio_event_address_get(NRF_RADIO, NRF_RADIO_EVENT_DISABLED), PPI_CHGRP_ABORT); +#elif defined(NRF53_SERIES) + mpsl_fem_abort_set(NRF_802154_DPPI_RADIO_DISABLED, + 0U); /* The group parameter is ignored by FEM for nRF53 */ #endif mpsl_fem_deactivate_now(MPSL_FEM_ALL); @@ -554,6 +593,7 @@ static void ppi_all_clear(void) nrf_802154_trx_ppi_for_fem_clear(); break; +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case TRX_STATE_CONTINUOUS_CARRIER: nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_TXEN, false); nrf_802154_trx_ppi_for_fem_clear(); @@ -563,6 +603,7 @@ static void ppi_all_clear(void) nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_TXEN, false); nrf_802154_trx_ppi_for_fem_clear(); break; +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED case TRX_STATE_ENERGY_DETECTION: nrf_802154_trx_ppi_for_ramp_up_clear(NRF_RADIO_TASK_RXEN, false); @@ -572,29 +613,13 @@ static void ppi_all_clear(void) default: assert(false); } + nrf_802154_trx_ppi_for_disable(); } static void fem_power_down_now(void) { mpsl_fem_deactivate_now(MPSL_FEM_ALL); - - if (nrf_802154_trx_ppi_for_fem_powerdown_set(NRF_802154_TIMER_INSTANCE, NRF_TIMER_CC_CHANNEL0)) - { - // FEM requires timer to run to perform powering down operation - nrf_timer_event_clear(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE0); - - nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_START); - - while (!nrf_timer_event_check(NRF_802154_TIMER_INSTANCE, NRF_TIMER_EVENT_COMPARE0)) - { - // Wait until the event is set. - // The waiting takes several microseconds - } - - nrf_timer_shorts_disable(NRF_802154_TIMER_INSTANCE, NRF_TIMER_SHORT_COMPARE0_STOP_MASK); - nrf_timer_task_trigger(NRF_802154_TIMER_INSTANCE, NRF_TIMER_TASK_SHUTDOWN); - nrf_802154_trx_ppi_for_fem_powerdown_clear(); - } + mpsl_fem_disable(); } void nrf_802154_trx_disable(void) @@ -622,15 +647,9 @@ void nrf_802154_trx_disable(void) nrf_radio_power_set(NRF_RADIO, true); -#if defined(NRF52840_XXAA) || \ - defined(NRF52833_XXAA) || \ - defined(NRF52820_XXAA) || \ - defined(NRF52811_XXAA) + mpsl_fem_lna_configuration_clear(); + mpsl_fem_pa_configuration_clear(); mpsl_fem_abort_clear(); -#endif - - // TODO: Deconfigure FAL PA and LNA here? - mpsl_fem_deactivate_now(MPSL_FEM_ALL); if (m_trx_state != TRX_STATE_IDLE) { @@ -774,11 +793,13 @@ void nrf_802154_trx_antenna_update(void) case TRX_STATE_STANDALONE_CCA: case TRX_STATE_RXACK: case TRX_STATE_TXFRAME: +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case TRX_STATE_CONTINUOUS_CARRIER: case TRX_STATE_MODULATED_CARRIER: tx_antenna_update(); break; +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED default: /* Intentionally empty */ break; @@ -1502,6 +1523,7 @@ void nrf_802154_trx_abort(void) standalone_cca_abort(); break; +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED case TRX_STATE_CONTINUOUS_CARRIER: continuous_carrier_abort(); break; @@ -1509,6 +1531,7 @@ void nrf_802154_trx_abort(void) case TRX_STATE_MODULATED_CARRIER: modulated_carrier_abort(); break; +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED case TRX_STATE_ENERGY_DETECTION: energy_detection_abort(); @@ -1746,6 +1769,8 @@ static void standalone_cca_abort(void) nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); } +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + void nrf_802154_trx_continuous_carrier(void) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); @@ -1865,6 +1890,8 @@ static void modulated_carrier_abort() nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); } +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + void nrf_802154_trx_energy_detection(uint32_t ed_count) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_LOW); @@ -2521,3 +2548,57 @@ void nrf_802154_trx_swi_irq_handler(void) } #endif + +const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_end_event_handle_get(void) +{ + static const nrf_802154_sl_event_handle_t r = { +#if defined(DPPI_PRESENT) + .event_addr = NRF_802154_DPPI_RADIO_END, + .shared = true +#else + .event_addr = (uint32_t)&NRF_RADIO->EVENTS_END +#endif + }; + + return &r; +} + +const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_ready_event_handle_get(void) +{ + static const nrf_802154_sl_event_handle_t r = { +#if defined(DPPI_PRESENT) + .event_addr = NRF_802154_DPPI_RADIO_READY, + .shared = true +#else + .event_addr = (uint32_t)&NRF_RADIO->EVENTS_READY +#endif + }; + + return &r; +} + +const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_crcok_event_handle_get(void) +{ + static const nrf_802154_sl_event_handle_t r = { + .event_addr = (uint32_t)&NRF_RADIO->EVENTS_CRCOK, +#if defined(DPPI_PRESENT) + .shared = false +#endif + }; + + return &r; +} + +const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_phyend_event_handle_get(void) +{ + static const nrf_802154_sl_event_handle_t r = { +#if defined(DPPI_PRESENT) + .event_addr = NRF_802154_DPPI_RADIO_PHYEND, + .shared = true +#else + .event_addr = (uint32_t)&NRF_RADIO->EVENTS_PHYEND +#endif + }; + + return &r; +} diff --git a/drivers/nrf_802154/driver/src/nrf_802154_trx.h b/drivers/nrf_802154/driver/src/nrf_802154_trx.h index 647e2ed..3397817 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_trx.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_trx.h @@ -46,6 +46,7 @@ #include #include "nrf_802154_config.h" +#include "nrf_802154_sl_types.h" #ifdef __cplusplus extern "C" { @@ -157,8 +158,7 @@ void nrf_802154_trx_disable(void); * @brief Updates currently used antenna. * * This function sets the antenna to be used based on antenna diversity interface - * configuration and TRX state. See @ref nrf_802154_sl_ant_div_mode_set, - * @ref nrf_802154_sl_ant_div_antenna_set. + * configuration and TRX state. */ void nrf_802154_trx_antenna_update(void); @@ -350,7 +350,7 @@ void nrf_802154_trx_transmit_frame(const void * p_tra /**@brief Puts the trx module into transmit ACK mode. * - * @note This function may be called from @ref nrf_802154_trx_receive_received handler only. + * @note This function may be called from @ref nrf_802154_trx_receive_frame_received handler only. * This is because in this condition only the TIMER peripheral is running and allows timed transmission. * * @param[in] p_transmit_buffer Pointer to a buffer containing ACK frame to be transmitted. @@ -384,6 +384,8 @@ bool nrf_802154_trx_go_idle(void); */ void nrf_802154_trx_standalone_cca(void); +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + /**@brief Starts generating continuous carrier. * * Generation of a continuous carrier generates no handlers. It may be terminated by a call to @@ -410,6 +412,8 @@ void nrf_802154_trx_modulated_carrier(const void * p_transmit_buffer); /** @brief Restarts generating modulated carrier.*/ void nrf_802154_trx_modulated_carrier_restart(void); +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + /**@brief Puts trx module into energy detection mode. * * Operation ends up with a call to @ref nrf_802154_trx_energy_detection_finished handler. @@ -459,7 +463,7 @@ extern void nrf_802154_trx_receive_ack_started(void); * * @note This handler may be triggered several times during receive of a preamble * of a frame. It can be followed by call to @ref nrf_802154_trx_receive_frame_started - * (if enabled) and then by @ref nrf_802154_trx_receive_frame_crcok or + * (if enabled) and then by @ref nrf_802154_trx_receive_frame_received or * @ref nrf_802154_trx_receive_frame_crcerror, but there is possibility * that it will not be followed by these calls (In case when the RADIO didn't found * full preamble.). If implementation of this handler starts some @@ -486,7 +490,7 @@ extern void nrf_802154_trx_receive_frame_started(void); /**@brief Handler called during reception of a frame, when given number of bytes is received. * - * This handler is called from an ISR when given number of bytes (see @ref nrf_802154_trx_receive) + * This handler is called from an ISR when given number of bytes (see @ref nrf_802154_trx_receive_frame) * have been just received. * * @note If the handler decides to abort receive by a call to @ref nrf_802154_trx_abort or @@ -591,7 +595,7 @@ extern void nrf_802154_trx_receive_ack_crcerror(void); /**@brief Handler called when a cca operation during transmit attempt started. * * This handler is called from an ISR when: - * - transmit operation with cca has been started with a call to @ref nrf_802154_transmit_frame(cca=true). + * - transmit operation with cca has been started with a call to @ref nrf_802154_trx_transmit_frame(cca=true). * - transmit operation was started with parameter @c notifications_mask containing * TRX_TRANSMIT_NOTIFICATION_CCASTARTED * - the RADIO peripheral started CCA operation. @@ -604,7 +608,7 @@ extern void nrf_802154_trx_transmit_frame_ccastarted(void); /**@brief Handler called when a cca operation during transmit attempt was successful. * * This handler is called from an ISR when: - * - transmit operation with cca has been started with a call to @ref nrf_802154_transmit_frame(cca=true). + * - transmit operation with cca has been started with a call to @ref nrf_802154_trx_transmit_frame(cca=true). * - the RADIO detected that channel was free. * * When this handler is called following holds: @@ -619,7 +623,7 @@ extern void nrf_802154_trx_transmit_frame_ccaidle(void); /**@brief Handler called when a cca operation during transmit attempt failed. * * This handler is called from an ISR when: - * - transmit operation with cca has been started with a call to @ref nrf_802154_transmit_frame(cca=true). + * - transmit operation with cca has been started with a call to @ref nrf_802154_trx_transmit_frame(cca=true). * - the RADIO detected that channel was busy. * * When this handler is called following holds: @@ -759,11 +763,34 @@ extern void nrf_802154_trx_standalone_cca_finished(bool channel_was_idle); * - @ref nrf_802154_trx_go_idle, * - @ref nrf_802154_trx_disable. * - * @param channel_was_idle Informs implementation of the handler if channel was idle. - * true means the channel was idle, false means the channel was busy. + * @param ed_sample Sample of detected energy. */ extern void nrf_802154_trx_energy_detection_finished(uint8_t ed_sample); +/**@brief Returns RADIO->EVENTS_END handle that hardware can subscribe to. + * + * @return RADIO->EVENTS_END handle that hardware can subscribe to. + */ +const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_end_event_handle_get(void); + +/**@brief Returns RADIO->EVENTS_READY handle that hardware can subscribe to. + * + * @return RADIO->EVENTS_READY handle that hardware can subscribe to. + */ +const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_ready_event_handle_get(void); + +/**@brief Returns RADIO->EVENTS_CRCOK handle that hardware can subscribe to. + * + * @return RADIO->EVENTS_CRCOK handle that hardware can subscribe to. + */ +const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_crcok_event_handle_get(void); + +/**@brief Returns RADIO->EVENTS_PHYEND handle that hardware can subscribe to. + * + * @return RADIO->EVENTS_PHYEND handle that hardware can subscribe to. + */ +const nrf_802154_sl_event_handle_t * nrf_802154_trx_radio_phyend_event_handle_get(void); + #ifdef __cplusplus } #endif diff --git a/drivers/nrf_802154/driver/src/nrf_802154_trx_dppi.c b/drivers/nrf_802154/driver/src/nrf_802154_trx_dppi.c index 1c0c3f9..d55f7fd 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_trx_dppi.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_trx_dppi.c @@ -54,11 +54,45 @@ #define DPPI_CHGRP_RAMP_UP NRF_DPPI_CHANNEL_GROUP0 ///< PPI group used to disable self-disabling PPIs #define DPPI_CHGRP_RAMP_UP_DIS_TASK NRF_DPPI_TASK_CHG0_DIS ///< PPI task used to disable self-disabling PPIs -#define PPI_DISABLED_EGU NRF_802154_DPPI_RADIO_DISABLED_TO_EGU +#define PPI_DISABLED_EGU NRF_802154_DPPI_RADIO_DISABLED #define PPI_EGU_RAMP_UP NRF_802154_DPPI_EGU_TO_RADIO_RAMP_UP #define PPI_TIMER_TX_ACK NRF_802154_DPPI_TIMER_COMPARE_TO_RADIO_TXEN #define PPI_RADIO_SYNC_EGU_SYNC NRF_802154_DPPI_RADIO_SYNC_TO_EGU_SYNC +void nrf_802154_trx_ppi_for_enable(void) +{ + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_DISABLED, PPI_DISABLED_EGU); + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_READY, NRF_802154_DPPI_RADIO_READY); + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS, NRF_802154_DPPI_RADIO_ADDRESS); + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_END, NRF_802154_DPPI_RADIO_END); + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_PHYEND, NRF_802154_DPPI_RADIO_PHYEND); + nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE, NRF_802154_DPPI_RADIO_CCAIDLE); + nrf_dppi_channels_enable(NRF_DPPIC, + (1UL << PPI_DISABLED_EGU) | + (1UL << NRF_802154_DPPI_RADIO_READY) | + (1UL << NRF_802154_DPPI_RADIO_ADDRESS) | + (1UL << NRF_802154_DPPI_RADIO_END) | + (1UL << NRF_802154_DPPI_RADIO_PHYEND) | + (1UL << NRF_802154_DPPI_RADIO_CCAIDLE)); +} + +void nrf_802154_trx_ppi_for_disable(void) +{ + nrf_dppi_channels_disable(NRF_DPPIC, + (1UL << PPI_DISABLED_EGU) | + (1UL << NRF_802154_DPPI_RADIO_READY) | + (1UL << NRF_802154_DPPI_RADIO_ADDRESS) | + (1UL << NRF_802154_DPPI_RADIO_END) | + (1UL << NRF_802154_DPPI_RADIO_PHYEND) | + (1UL << NRF_802154_DPPI_RADIO_CCAIDLE)); + nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_CCAIDLE); + nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_PHYEND); + nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_END); + nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_ADDRESS); + nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_READY); + nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED); +} + void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task, bool start_timer) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH); @@ -77,11 +111,9 @@ void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task, bool star } nrf_egu_subscribe_set(NRF_802154_EGU_INSTANCE, EGU_TASK, PPI_DISABLED_EGU); - nrf_radio_publish_set(NRF_RADIO, NRF_RADIO_EVENT_DISABLED, PPI_DISABLED_EGU); nrf_dppi_channels_enable(NRF_DPPIC, - (1UL << PPI_EGU_RAMP_UP) | - (1UL << PPI_DISABLED_EGU)); + (1UL << PPI_EGU_RAMP_UP)); nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); } @@ -91,8 +123,7 @@ void nrf_802154_trx_ppi_for_ramp_up_clear(nrf_radio_task_t ramp_up_task, bool st nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH); nrf_dppi_channels_disable(NRF_DPPIC, - (1UL << PPI_EGU_RAMP_UP) | - (1UL << PPI_DISABLED_EGU)); + (1UL << PPI_EGU_RAMP_UP)); nrf_egu_publish_clear(NRF_802154_EGU_INSTANCE, EGU_EVENT); nrf_radio_subscribe_clear(NRF_RADIO, ramp_up_task); @@ -105,7 +136,6 @@ void nrf_802154_trx_ppi_for_ramp_up_clear(nrf_radio_task_t ramp_up_task, bool st } nrf_egu_subscribe_clear(NRF_802154_EGU_INSTANCE, EGU_TASK); - nrf_radio_publish_clear(NRF_RADIO, NRF_RADIO_EVENT_DISABLED); nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); } @@ -189,26 +219,6 @@ void nrf_802154_trx_ppi_for_fem_clear(void) nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); } -bool nrf_802154_trx_ppi_for_fem_powerdown_set(NRF_TIMER_Type * p_instance, - uint32_t compare_channel) -{ - nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH); - - // TODO: Implement this function when FEM API supports nRF53 - - nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); - return false; -} - -void nrf_802154_trx_ppi_for_fem_powerdown_clear(void) -{ - nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH); - - // TODO: Implement this function when FEM API supports nRF53 - - nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); -} - uint32_t nrf_802154_trx_ppi_group_for_abort_get(void) { // TODO: Implement it when external event (like coex) can abort radio operation diff --git a/drivers/nrf_802154/driver/src/nrf_802154_trx_ppi.c b/drivers/nrf_802154/driver/src/nrf_802154_trx_ppi.c index a867b05..06f8e25 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_trx_ppi.c +++ b/drivers/nrf_802154/driver/src/nrf_802154_trx_ppi.c @@ -45,7 +45,7 @@ #include "nrf_802154_debug_log.h" #include "nrf_802154_peripherals.h" -#include "mpsl_fem_protocol_api.h" +#include "protocol/mpsl_fem_protocol_api.h" #include "hal/nrf_egu.h" #include "hal/nrf_ppi.h" @@ -66,6 +66,16 @@ #define PPI_TIMER_TX_ACK NRF_802154_PPI_TIMER_COMPARE_TO_RADIO_TXEN ///< PPI that connects TIMER COMPARE event with RADIO TXEN task #define PPI_RADIO_SYNC_EGU_SYNC NRF_802154_PPI_RADIO_SYNC_TO_EGU_SYNC ///< PPI that connects RADIO SYNC event with EGU task for SYNC channel +void nrf_802154_trx_ppi_for_enable(void) +{ + // Intentionally empty. +} + +void nrf_802154_trx_ppi_for_disable(void) +{ + // Intentionally empty. +} + void nrf_802154_trx_ppi_for_ramp_up_set(nrf_radio_task_t ramp_up_task, bool start_timer) { nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH); @@ -226,33 +236,6 @@ void nrf_802154_trx_ppi_for_fem_clear(void) nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); } -bool nrf_802154_trx_ppi_for_fem_powerdown_set(NRF_TIMER_Type * p_instance, - uint32_t compare_channel) -{ - nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH); - - // PPI_EGU_TIMER_START is reused here on purpose, to save resources, - // as fem powerdown cannot be scheduled simultaneously with fem ramp-up. - bool result = mpsl_fem_prepare_powerdown(p_instance, - compare_channel, - PPI_EGU_TIMER_START, - nrf_radio_event_address_get(NRF_RADIO, - NRF_RADIO_EVENT_DISABLED)); - - nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); - - return result; -} - -void nrf_802154_trx_ppi_for_fem_powerdown_clear(void) -{ - nrf_802154_log_function_enter(NRF_802154_LOG_VERBOSITY_HIGH); - - nrf_ppi_channel_disable(NRF_PPI, PPI_EGU_TIMER_START); - - nrf_802154_log_function_exit(NRF_802154_LOG_VERBOSITY_HIGH); -} - uint32_t nrf_802154_trx_ppi_group_for_abort_get(void) { return (uint32_t)PPI_CHGRP_ABORT; diff --git a/drivers/nrf_802154/driver/src/nrf_802154_trx_ppi_api.h b/drivers/nrf_802154/driver/src/nrf_802154_trx_ppi_api.h index e978911..60f1be8 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_trx_ppi_api.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_trx_ppi_api.h @@ -46,6 +46,21 @@ #include "hal/nrf_egu.h" #include "hal/nrf_radio.h" +/** + * @brief Configures (D)PPI connections required for TRX operation. + * + * Actions performed by this function in DPPI variant: + * - RADIO_DISABLED event is published to DPPI designated by NRF_802154_DPPI_RADIO_DISABLED + * - NRF_RADIO_EVENT_CCAIDLE is published to DPPI designated by NRF_802154_DPPI_RADIO_CCAIDLE + * The DPPIs mentioned above may be then subscribed to. + */ +void nrf_802154_trx_ppi_for_enable(void); + +/** + * @brief Clears (D)PPI connections required for TRX operation. + */ +void nrf_802154_trx_ppi_for_disable(void); + /** * @brief Set PPIs to connect RADIO DISABLED event with tasks needed to ramp up. * @@ -103,7 +118,7 @@ bool nrf_802154_trx_ppi_for_ramp_up_was_triggered(void); void nrf_802154_trx_ppi_for_ack_tx_set(void); /** - * @brief Clear PPIs to connect TIMER event with radio TXEN task, needed to ramp up for ACK TX. See @ref void nrf_802154_trx_ppi_for_ack_tx_set + * @brief Clear PPIs to connect TIMER event with radio TXEN task, needed to ramp up for ACK TX. See @ref nrf_802154_trx_ppi_for_ack_tx_set */ void nrf_802154_trx_ppi_for_ack_tx_clear(void); @@ -118,27 +133,6 @@ void nrf_802154_trx_ppi_for_fem_set(void); */ void nrf_802154_trx_ppi_for_fem_clear(void); -/** - * @brief Prepare FEM to enter powerdown state. - * - * @param[in] p_instance Timer instance that is used to schedule the transition to the Power Down state. - * @param[in] compare_channel Compare channel to hold a value for the timer. - * - * @note This function and @ref nrf_802154_trx_ppi_for_fem_powerdown_clear looks not symetrical. - * It seems it could be better designed. We shall refactor it when porting FEM support to - * nRF53 family. - * - * @retval true FEM powerdown procedure has started. - * @retval false FEM powerdown procedure is not needed. - */ -bool nrf_802154_trx_ppi_for_fem_powerdown_set(NRF_TIMER_Type * p_instance, - uint32_t compare_channel); - -/** - * @brief Unconfigure PPIs needed to enter the powerdown state by FEM. - */ -void nrf_802154_trx_ppi_for_fem_powerdown_clear(void); - /** * @brief Get PPI group id used for disabling radio operations by an external event. */ diff --git a/drivers/nrf_802154/driver/src/nrf_802154_tx_work_buffer.h b/drivers/nrf_802154/driver/src/nrf_802154_tx_work_buffer.h index d8b4c61..a772ce3 100644 --- a/drivers/nrf_802154/driver/src/nrf_802154_tx_work_buffer.h +++ b/drivers/nrf_802154/driver/src/nrf_802154_tx_work_buffer.h @@ -100,9 +100,8 @@ const uint8_t * nrf_802154_tx_work_buffer_get(const uint8_t * p_original_frame); * buffer. This function performs all necessary updates of the original buffer in place. * * @param[inout] p_original_frame Pointer to the original frame to be transmitted. - * @param[out] p_frame_props Pointer to a structure to which @ref m_is_secured and - * @ref m_is_dynamic_data_updated flags' values are to be - * stored. + * @param[out] p_frame_props Pointer to a structure to which properties of the frame + * to be transmitted are stored. */ void nrf_802154_tx_work_buffer_original_frame_update( uint8_t * p_original_frame, diff --git a/drivers/nrf_802154/serialization/include/host/nrf_802154.h b/drivers/nrf_802154/serialization/include/host/nrf_802154.h index 8b77631..a6e1c9f 100644 --- a/drivers/nrf_802154/serialization/include/host/nrf_802154.h +++ b/drivers/nrf_802154/serialization/include/host/nrf_802154.h @@ -48,10 +48,28 @@ #include "nrf_802154_config.h" #include "nrf_802154_types.h" +/** + * @brief Timestamp value indicating that the timestamp is inaccurate. + */ +#define NRF_802154_NO_TIMESTAMP 0 + +/** + * @brief Invalid delayed timeslot identifier. + */ +#define NRF_802154_RESERVED_INVALID_ID UINT32_MAX + /** * @brief Reception window identifier reserved for immediate reception. */ -#define NRF_802154_RESERVED_IMM_RX_WINDOW_ID (UINT32_MAX - 1) +#define NRF_802154_RESERVED_IMM_RX_WINDOW_ID (UINT32_MAX - 1) + +/** + * @brief Upper bound for delayed reception window identifiers used by the application. + * + * All integers ranging from 0 to @ref NRF_802154_RESERVED_DRX_ID_UPPER_BOUND (inclusive) + * can be used by the application as identifiers of delayed reception windows. + */ +#define NRF_802154_RESERVED_DRX_ID_UPPER_BOUND (UINT32_MAX - 4) /** * @brief Select the source matching algorithm. @@ -77,7 +95,7 @@ void nrf_802154_src_addr_matching_method_set(nrf_802154_src_addr_match_t match_m * - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 * For more information, see @ref nrf_802154_src_addr_match_t. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @param[in] p_addr Array of bytes containing the address of the node (little-endian). * @param[in] extended If the given address is an extended MAC address or a short MAC address. @@ -106,7 +124,7 @@ bool nrf_802154_ack_data_set(const uint8_t * p_addr, * - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 * For more information, see @ref nrf_802154_src_addr_match_t. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @param[in] p_addr Array of bytes containing the address of the node (little-endian). * @param[in] extended If the given address is an extended MAC address or a short MAC address. @@ -150,7 +168,7 @@ void nrf_802154_auto_pending_bit_set(bool enabled); * - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 * For more information, see @ref nrf_802154_src_addr_match_t. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @note This function makes a copy of the given address. * @@ -172,7 +190,7 @@ bool nrf_802154_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended); * - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 * For more information, see @ref nrf_802154_src_addr_match_t. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @param[in] p_addr Array of bytes containing the address of the node (little-endian). * @param[in] extended If the given address is an extended MAC address or a short MAC address. @@ -192,13 +210,28 @@ bool nrf_802154_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended * - For Standard-compliant, @ref NRF_802154_SRC_ADDR_MATCH_ALWAYS_1 * For more information, see @ref nrf_802154_src_addr_match_t. * - * The method can be set during initialization phase by calling @ref nrf_802154_src_matching_method. + * The method can be set during initialization phase by calling @ref nrf_802154_src_addr_matching_method_set. * * @param[in] extended If the function is to remove all extended MAC addresses or all short * addresses. */ void nrf_802154_pending_bit_for_addr_reset(bool extended); +/** + * @brief Configures the radio CCA mode and threshold. + * + * @param[in] p_cca_cfg Pointer to the CCA configuration structure. Only fields relevant to + * the selected mode are updated. + */ +void nrf_802154_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cca_cfg); + +/** + * @brief Gets the current radio CCA configuration. + * + * @param[out] p_cca_cfg Pointer to the structure for the current CCA configuration. + */ +void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cca_cfg); + /** * @brief Initializes the 802.15.4 driver. * @@ -235,6 +268,59 @@ bool nrf_802154_sleep(void); */ bool nrf_802154_receive(void); +/** + * @brief Requests reception at the specified time. + * + * This function works as a delayed version of @ref nrf_802154_receive. It is asynchronous. + * It queues the delayed reception using the Radio Scheduler module. + * If the delayed reception cannot be performed (@ref nrf_802154_receive_at would return false) + * or the requested reception timeslot is denied, @ref nrf_802154_receive_failed is called + * with the @ref NRF_802154_RX_ERROR_DELAYED_TIMESLOT_DENIED argument. + * + * If the requested reception time is in the past, the function returns false and does not + * schedule reception. + * + * A scheduled reception can be cancelled by a call to @ref nrf_802154_receive_at_cancel. + * + * @note The identifier @p id must be unique. It must not have the same value as identifiers + * of other delayed timeslots active at the moment, so that it can be mapped unambiguously + * to an active delayed operation if the request is successful. In particular, none of the reserved + * identifiers can be used. + * + * @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler, + * in microseconds (us). + * @param[in] dt Delta of delay time from @p t0, in microseconds (us). + * @param[in] timeout Reception timeout (counted from @p t0 + @p dt), in microseconds (us). + * @param[in] channel Radio channel on which the frame is to be received. + * @param[in] id Identifier of the scheduled reception window. If the reception has been + * scheduled successfully, the value of this parameter can be used in + * @ref nrf_802154_receive_at_cancel to cancel it. + * + * @retval true The reception procedure was scheduled. + * @retval false The driver could not schedule the reception procedure. + */ +bool nrf_802154_receive_at(uint32_t t0, + uint32_t dt, + uint32_t timeout, + uint8_t channel, + uint32_t id); + +/** + * @brief Cancels a delayed reception scheduled by a call to @ref nrf_802154_receive_at. + * + * If the receive window has been scheduled but has not started yet, this function prevents + * entering the receive window. If the receive window has been scheduled and has already started, + * the radio remains in the receive state, but a window timeout will not be reported. + * + * @param[in] id Identifier of the delayed reception window to be cancelled. If the provided + * value does not refer to any scheduled or active receive window, the function + * returns false. + * + * @retval true The delayed reception was scheduled and successfully cancelled. + * @retval false No delayed reception was scheduled. + */ +bool nrf_802154_receive_at_cancel(uint32_t id); + /** @brief Sets the channel on which the radio is to operate. * * @param[in] channel Channel number (11-26). @@ -312,6 +398,36 @@ void nrf_802154_promiscuous_set(bool enabled); */ bool nrf_802154_cca(void); +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + +/** + * @brief Changes the radio state to continuous carrier. + * + * @note When the radio is emitting continuous carrier signals, it blocks all transmissions on the + * selected channel. This function is to be called only during radio tests. Do not + * use it during normal device operation. + * + * @retval true The continuous carrier procedure was scheduled. + * @retval false The driver could not schedule the continuous carrier procedure. + */ +bool nrf_802154_continuous_carrier(void); + +/** + * @brief Changes the radio state to modulated carrier. + * + * @note When the radio is emitting modulated carrier signals, it blocks all transmissions on the + * selected channel. This function is to be called only during radio tests. Do not + * use it during normal device operation. + * + * @param[in] p_data Pointer to a buffer to modulate the carrier with. The first byte is the data length. + * + * @retval true The modulated carrier procedure was scheduled. + * @retval false The driver could not schedule the modulated carrier procedure. + */ +bool nrf_802154_modulated_carrier(const uint8_t * p_data); + +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + /** * @brief Changes the radio state to energy detection. * @@ -366,8 +482,11 @@ bool nrf_802154_energy_detection(uint32_t time_us); * The CRC is computed automatically by the radio hardware. Therefore, * the FCS field can contain any bytes. * @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data - * to transmit and additional parameters for the procedure. - * If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used. + * to transmit. If @c NULL following metadata are used: + * Field | Value + * ----------------|----------------------------------------------------- + * @c frame_props | @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT + * @c cca | @c true * * @retval true The transmission procedure was scheduled. * @retval false The driver could not schedule the transmission procedure. @@ -375,6 +494,13 @@ bool nrf_802154_energy_detection(uint32_t time_us); bool nrf_802154_transmit_raw(uint8_t * p_data, const nrf_802154_transmit_metadata_t * p_metadata); +/** + * @} + * @defgroup nrf_802154_csma CSMA-CA procedure + * @{ + */ +#if NRF_802154_CSMA_CA_ENABLED || defined(DOXYGEN) + /** * @brief Performs the CSMA-CA procedure and transmits a frame in case of success. * @@ -391,7 +517,10 @@ bool nrf_802154_transmit_raw(uint8_t * p_data, * * @param[in] p_data Pointer to the frame to transmit. See also @ref nrf_802154_transmit_raw. * @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data - * to transmit. If NULL, @ref NRF_802154_TRANSMIT_METADATA_DEFAULT_INIT is used. + * to transmit. If @c NULL following metadata are used: + * Field | Value + * ----------------|----------------------------------------------------- + * @c frame_props | @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT * * @retval true The chain of CSMA-CA and transmission procedure was scheduled. * @retval false The driver could not schedule the procedure chain. @@ -399,6 +528,132 @@ bool nrf_802154_transmit_raw(uint8_t * p_data, bool nrf_802154_transmit_csma_ca_raw(uint8_t * p_data, const nrf_802154_transmit_csma_ca_metadata_t * p_metadata); +/** + * @brief Sets the minimum value of the backoff exponent (BE) in the CSMA-CA algorithm. + * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * + * @param[in] min_be Minimum value of the backoff exponent. + * + * @retval true When value provided by @p min_be has been set successfully. + * @retval false Otherwise. + */ +bool nrf_802154_csma_ca_min_be_set(uint8_t min_be); + +/** + * @brief Gets the minimum value of the backoff exponent (BE) in the CSMA-CA algorithm. + * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * + * @return Current minimum value of the backoff exponent. + */ +uint8_t nrf_802154_csma_ca_min_be_get(void); + +/** + * @brief Sets the maximum value of the backoff exponent (BE) in the CSMA-CA algorithm. + * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * + * @param[in] max_be Maximum value of the backoff exponent. + * + * @retval true When value provided by @p max_be has been set successfully. + * @retval false Otherwise. + */ +bool nrf_802154_csma_ca_max_be_set(uint8_t max_be); + +/** + * @brief Gets the maximum value of the backoff exponent (BE) in the CSMA-CA algorithm. + * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * + * @return Current maximum value of the backoff exponent. + */ +uint8_t nrf_802154_csma_ca_max_be_get(void); + +/** + * @brief Sets the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring + * a channel access failure. + * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * + * @param[in] max_backoffs Maximum number of backoffs. + */ +void nrf_802154_csma_ca_max_backoffs_set(uint8_t max_backoffs); + +/** + * @brief Gets the maximum number of backoffs the CSMA-CA algorithm will attempt before declaring + * a channel access failure. + * + * @note This function is available if @ref NRF_802154_CSMA_CA_ENABLED is enabled. + * + * @return Current maximum number of backoffs. + */ +uint8_t nrf_802154_csma_ca_max_backoffs_get(void); + +#endif // NRF_802154_CSMA_CA_ENABLED + +/** + * @brief Requests transmission at the specified time. + * + * @note This function is implemented in a zero-copy fashion. It passes the given buffer pointer to + * the RADIO peripheral. + * + * + * This function works as a delayed version of @ref nrf_802154_transmit_raw. It is asynchronous. + * It queues the delayed transmission using the Radio Scheduler module and performs it + * at the specified time. + * + * If the delayed transmission is successfully performed, @ref nrf_802154_transmitted_raw is called. + * If the delayed transmission cannot be performed ( @ref nrf_802154_transmit_raw would return @c false) + * or the requested transmission timeslot is denied, @ref nrf_802154_transmit_failed with the + * @ref NRF_802154_TX_ERROR_TIMESLOT_DENIED argument is called. + * + * This function is designed to transmit the first symbol of SHR at the given time. + * + * If the requested transmission time is in the past, the function returns @c false and does not + * schedule transmission. + * + * A successfully scheduled transmission can be cancelled by a call + * to @ref nrf_802154_transmit_at_cancel. + * + * @param[in] p_data Pointer to the array with data to transmit. The first byte must contain + * the frame length (including FCS). The following bytes contain data. + * The CRC is computed automatically by the radio hardware. Therefore, + * the FCS field can contain any bytes. + * @param[in] t0 Base of delay time - absolute time used by the Timer Scheduler, + * in microseconds (us). + * @param[in] dt Delta of delay time from @p t0, in microseconds (us). + * @param[in] p_metadata Pointer to metadata structure. Contains detailed properties of data + * to transmit. If @c NULL following metadata are used: + * Field | Value + * ----------------|----------------------------------------------------- + * @c frame_props | @ref NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT + * @c cca | @c true + * @c channel | As returned by @ref nrf_802154_channel_get + * + * @retval true The transmission procedure was scheduled. + * @retval false The driver could not schedule the transmission procedure. + */ +bool nrf_802154_transmit_raw_at(uint8_t * p_data, + uint32_t t0, + uint32_t dt, + const nrf_802154_transmit_at_metadata_t * p_metadata); + +/** + * @brief Cancels a delayed transmission scheduled by a call to @ref nrf_802154_transmit_raw_at. + * + * If a delayed transmission has been scheduled but the transmission has not been started yet, + * a call to this function prevents the transmission. If the transmission is ongoing, + * it will not be aborted. + * + * If a delayed transmission has not been scheduled (or has already finished), this function does + * not change state and returns false. + * + * @retval true The delayed transmission was scheduled and successfully cancelled. + * @retval false No delayed transmission was scheduled. + */ +bool nrf_802154_transmit_at_cancel(void); + /** * @brief Notifies the driver that the buffer containing the received frame is not used anymore. * @@ -437,6 +692,24 @@ int8_t nrf_802154_tx_power_get(void); */ int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level); +/** + * @brief Calculates the timestamp of the first symbol of the preamble in a received frame. + * + * @param[in] end_timestamp Timestamp of the end of the last symbol in the frame, + * in microseconds. + * @param[in] psdu_length Number of bytes in the frame PSDU. + * + * @return Timestamp of the beginning of the first preamble symbol of a given frame, + * in microseconds. + */ +uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t psdu_length); + +/** + * @} + * @defgroup nrf_802154_capabilities Radio driver run-time capabilities feature. + * @{ + */ + /** * @brief Gets nRF 802.15.4 Radio Driver Capabilities. * @@ -454,4 +727,73 @@ nrf_802154_capabilities_t nrf_802154_capabilities_get(void); */ uint32_t nrf_802154_time_get(void); +/** + * @} + * @defgroup nrf_802154_security Radio driver MAC security feature. + * @{ + */ + +/** + * @brief Sets nRF 802.15.4 Radio Driver Global MAC Frame Counter. + * + * The driver automatically increments the counter in every outgoing frame + * which uses the Global MAC Frame Counter. + * This call is meant to set the initial value of the frame counter. + * + * @param[in] frame_counter Global MAC Frame Counter to set. + */ +void nrf_802154_security_global_frame_counter_set(uint32_t frame_counter); + +/** + * @brief Store the 802.15.4 MAC Security Key inside the nRF 802.15.4 Radio Driver. + * + * @param[in] p_key Pointer to the key to store. Refer to @ref nrf_802154_key_t for details. + * Storing the key copies the content of the key and key ID into the Radio Driver. + * This input parameter can be destroyed after the call. + * + * @note This function is not reentrant and must be called from thread context only. + * + * @retval NRF_802154_SECURITY_ERROR_NONE Storing of key is successful. + * @retval NRF_802154_SECURITY_ERROR_TYPE_NOT_SUPPORTED Type of the key is not supported. + * @retval NRF_802154_SECURITY_ERROR_MODE_NOT_SUPPORTED ID mode of the key is not supported. + * @retval NRF_802154_SECURITY_ERROR_ALREADY_PRESENT Failed to store the key - key of such id is already + * present. Remove the key first to overwrite. + * @retval NRF_802154_SECURITY_ERROR_STORAGE_FULL Failed to store the key - storage full. + */ +nrf_802154_security_error_t nrf_802154_security_key_store(nrf_802154_key_t * p_key); + +/** + * @brief Remove the 802.15.4 MAC Security Key from the nRF 802.15.4 Radio Driver. + * + * @param[in] p_id Pointer to the ID of the key to remove. + * + * @note This function is not reentrant and must be called from thread context only. + * + * @retval NRF_802154_SECURITY_ERROR_NONE Removal of key is successful. + * @retval NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND Failed to remove the key - no such key found. + */ +nrf_802154_security_error_t nrf_802154_security_key_remove(nrf_802154_key_id_t * p_id); + +/** + * @} + * @defgroup nrf_802154_ie_writer Radio driver Information Element data injection feature. + * @{ + */ + +/** + * @brief Sets the value of CSL period to inject into the CSL information element. + * + * @param[in] period CSL period value. + */ +void nrf_802154_csl_writer_period_set(uint16_t period); + +/** @} */ + +/** + * @brief Get time stamps of events gathered by the last operation. + * + * @param[out] p_stat_timestamps Structure that will be filled with current time stamps of events. + */ +void nrf_802154_stat_timestamps_get(nrf_802154_stat_timestamps_t * p_stat_timestamps); + #endif diff --git a/drivers/nrf_802154/serialization/include/host/nrf_802154_config.h b/drivers/nrf_802154/serialization/include/host/nrf_802154_config.h index d71f2e7..19fbe13 100644 --- a/drivers/nrf_802154/serialization/include/host/nrf_802154_config.h +++ b/drivers/nrf_802154/serialization/include/host/nrf_802154_config.h @@ -44,7 +44,6 @@ extern "C" { #endif /** - * @} * @defgroup nrf_802154_config_csma CSMA/CA procedure configuration * @{ */ @@ -62,12 +61,59 @@ extern "C" { #endif #endif +/** + *@} + **/ + +/** + * @defgroup nrf_802154_config_dtrx Delayed operations configuration + * @{ + */ + +/** + * @def NRF_802154_DELAYED_TRX_ENABLED + * + * If the delayed transmission and the receive window features are available. + * + */ +#if !defined(CONFIG_NRF_802154_SL_OPENSOURCE) +#ifndef NRF_802154_DELAYED_TRX_ENABLED +#define NRF_802154_DELAYED_TRX_ENABLED 1 +#endif +#endif + +/** + * @} + * @defgroup nrf_802154_config_security Security configuration + * @{ + */ + +/** + * @def NRF_802154_SECURITY_KEY_STORAGE_SIZE + * + * Configures the number of keys which are available in the Key Storage. + * This configuration is implementation-independent. + */ +#ifndef NRF_802154_SECURITY_KEY_STORAGE_SIZE +#define NRF_802154_SECURITY_KEY_STORAGE_SIZE 3 +#endif + +/** + *@} + **/ + +/** + * @def NRF_802154_CARRIER_FUNCTIONS_ENABLED + * + * Enables functions used for test purposes: nrf_802154_continuous_carrier and + * nrf_802154_modulated_carrier + */ +#ifndef NRF_802154_CARRIER_FUNCTIONS_ENABLED +#define NRF_802154_CARRIER_FUNCTIONS_ENABLED 1 +#endif + #ifdef __cplusplus } #endif #endif // NRF_802154_CONFIG_H__ - -/** - *@} - **/ diff --git a/drivers/nrf_802154/serialization/include/host/nrf_802154_const.h b/drivers/nrf_802154/serialization/include/host/nrf_802154_const.h index 95321db..2d9aa38 100644 --- a/drivers/nrf_802154/serialization/include/host/nrf_802154_const.h +++ b/drivers/nrf_802154/serialization/include/host/nrf_802154_const.h @@ -40,13 +40,190 @@ #ifndef NRF_802154_CONST_H_ #define NRF_802154_CONST_H_ -#define MAX_PACKET_SIZE 127 ///< Maximum size of the radio packet. -#define PAN_ID_SIZE 2 ///< Size of the PAN ID. +#define RAW_LENGTH_OFFSET 0 ///< Byte containing the frame length in a raw frame. +#define RAW_PAYLOAD_OFFSET 1 ///< Offset of the frame payload in a raw frame -#define EXTENDED_ADDRESS_SIZE 8 ///< Size of the Extended Mac Address. -#define SHORT_ADDRESS_SIZE 2 ///< Size of the Short Mac Address. +#define ACK_HEADER_WITH_PENDING 0x12 ///< The first byte of an ACK frame containing a pending bit. +#define ACK_HEADER_WITHOUT_PENDING 0x02 ///< The first byte of an ACK frame without a pending bit. -#define ED_MIN_DBM (-92) ///< dBm value corresponding to value 0 in the EDSAMPLE register. -#define ED_RESULT_FACTOR 4 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral. +#define ACK_REQUEST_OFFSET 1 ///< Byte containing the ACK request bit (+1 for the frame length byte). +#define ACK_REQUEST_BIT (1 << 5) ///< ACK request bit. + +#define ASN_IN_NONCE_BIT 0x40 ///< Bit containing the ASN in Nonce field. + +#define DEST_ADDR_TYPE_OFFSET 2 ///< Byte containing the destination address type (+1 for the frame length byte). +#define DEST_ADDR_TYPE_MASK 0x0c ///< Mask of bits containing the destination address type. +#define DEST_ADDR_TYPE_EXTENDED 0x0c ///< Bits containing the extended destination address type. +#define DEST_ADDR_TYPE_NONE 0x00 ///< Bits containing a not-present destination address type. +#define DEST_ADDR_TYPE_SHORT 0x08 ///< Bits containing the short destination address type. +#define DEST_ADDR_OFFSET 6 ///< Offset of the destination address in the Data frame (+1 for the frame length byte). + +#define DSN_OFFSET 3 ///< Byte containing the DSN value (+1 for the frame length byte). +#define DSN_SUPPRESS_OFFSET 2 ///< Byte containing the DSN suppression field. +#define DSN_SUPPRESS_BIT 0x01 ///< Bits containing the DSN suppression field. + +#define FRAME_COUNTER_SUPPRESS_BIT 0x20 ///< Bit containing the Frame Counter Suppression field. + +#define FRAME_PENDING_OFFSET 1 ///< Byte containing a pending bit (+1 for the frame length byte). +#define FRAME_PENDING_BIT (1 << 4) ///< Pending bit. + +#define FRAME_TYPE_OFFSET 1 ///< Byte containing the frame type bits (+1 for the frame length byte). +#define FRAME_TYPE_MASK 0x07 ///< Mask of bits containing the frame type. +#define FRAME_TYPE_ACK 0x02 ///< Bits containing the ACK frame type. +#define FRAME_TYPE_BEACON 0x00 ///< Bits containing the Beacon frame type. +#define FRAME_TYPE_COMMAND 0x03 ///< Bits containing the Command frame type. +#define FRAME_TYPE_DATA 0x01 ///< Bits containing the Data frame type. +#define FRAME_TYPE_EXTENDED 0x07 ///< Bits containing the Extended frame type. +#define FRAME_TYPE_FRAGMENT 0x06 ///< Bits containing the Fragment or the Frak frame type. +#define FRAME_TYPE_MULTIPURPOSE 0x05 ///< Bits containing the Multipurpose frame type. + +#define FRAME_VERSION_OFFSET 2 ///< Byte containing the frame version bits (+1 for the frame length byte). +#define FRAME_VERSION_MASK 0x30 ///< Mask of bits containing the frame version. +#define FRAME_VERSION_0 0x00 ///< Bits containing the frame version 0b00. +#define FRAME_VERSION_1 0x10 ///< Bits containing the frame version 0b01. +#define FRAME_VERSION_2 0x20 ///< Bits containing the frame version 0b10. +#define FRAME_VERSION_3 0x30 ///< Bits containing the frame version 0b11. + +#define IE_HEADER_LENGTH_MASK 0x3f ///< Mask of bits containing the length of an IE header content. +#define IE_PRESENT_OFFSET 2 ///< Byte containing the IE Present bit. +#define IE_PRESENT_BIT 0x02 ///< Bits containing the IE Present field. + +#define KEY_ID_MODE_0 0 ///< Value of the 0x00 Key Identifier Mode. +#define KEY_ID_MODE_1 1 ///< Value of the 0x01 Key Identifier Mode. +#define KEY_ID_MODE_2 2 ///< Value of the 0x10 Key Identifier Mode. +#define KEY_ID_MODE_3 3 ///< Value of the 0x11 Key Identifier Mode. + +#define KEY_ID_MODE_MASK 0x18 ///< Mask of bits containing Key Identifier Mode in the Security Control field. +#define KEY_ID_MODE_BIT_OFFSET 3 ///< Number of bits the Key Identifier Mode is offset in the Security Control field. +#define KEY_ID_MODE_0_MASK 0 ///< Bits containing the 0x00 Key Identifier Mode. +#define KEY_ID_MODE_1_MASK 0x08 ///< Bits containing the 0x01 Key Identifier Mode. +#define KEY_ID_MODE_2_MASK 0x10 ///< Bits containing the 0x10 Key Identifier Mode. +#define KEY_ID_MODE_3_MASK 0x18 ///< Bits containing the 0x11 Key Identifier Mode. + +#define KEY_SRC_KEY_ID_MODE_0_SIZE 0 ///< Size of the Key Source field when Key Identifier Mode equals 0. +#define KEY_SRC_KEY_ID_MODE_1_SIZE 0 ///< Size of the Key Source field when Key Identifier Mode equals 1. +#define KEY_SRC_KEY_ID_MODE_2_SIZE 4 ///< Size of the Key Source field when Key Identifier Mode equals 2. +#define KEY_SRC_KEY_ID_MODE_3_SIZE 8 ///< Size of the Key Source field when Key Identifier Mode equals 3. + +#define KEY_IDX_SIZE 1 ///< Size of the Key Index field + +#define MAC_CMD_COMMAND_ID_SIZE 1 ///< Size of the MAC Command ID field. +#define MAC_CMD_ASSOC_REQ 0x01 ///< Command frame identifier for MAC Association request. +#define MAC_CMD_ASSOC_RESP 0x02 ///< Command frame identifier for MAC Association response. +#define MAC_CMD_DISASSOC_NOTIFY 0x03 ///< Command frame identifier for MAC Disaccociation notification. +#define MAC_CMD_DATA_REQ 0x04 ///< Command frame identifier for MAC Data Requests. +#define MAC_CMD_PANID_CONFLICT 0x05 ///< Command frame identifier for MAC PAN ID conflict notification. +#define MAC_CMD_ORPHAN_NOTIFY 0x06 ///< Command frame identifier for MAC Orphan notification. +#define MAC_CMD_BEACON_REQ 0x07 ///< Command frame identifier for MAC Beacon. +#define MAC_CMD_COORD_REALIGN 0x08 ///< Command frame identifier for MAC Coordinator realignment. +#define MAC_CMD_GTS_REQUEST 0x09 ///< Command frame identifier for MAC GTS request. + +#define PAN_ID_COMPR_OFFSET 1 ///< Byte containing the PAN ID compression bit (+1 for the frame length byte). +#define PAN_ID_COMPR_MASK 0x40 ///< PAN ID compression bit. + +#define PAN_ID_OFFSET 4 ///< Offset of PAN ID in the Data frame (+1 for the frame length byte). + +#define PHR_OFFSET 0 ///< Offset of the PHY header in a frame. +#define PHR_LENGTH_MASK 0x7f ///< Mask of the PHR length field + +#define PSDU_OFFSET 1 ///< Offset of the PHY payload. + +#define SECURITY_ENABLED_OFFSET 1 ///< Byte containing the Security Enabled bit. +#define SECURITY_ENABLED_BIT 0x08 ///< Bits containing the Security Enabled field. +#define SECURITY_LEVEL_MASK 0x07 ///< Mask of bits containing the Security level field. +#define SECURITY_LEVEL_NONE 0x00 ///< Bits indicating a frame with no security attributes (0b000). +#define SECURITY_LEVEL_MIC_32 0x01 ///< Bits containing the 32-bit Message Integrity Code (0b001). +#define SECURITY_LEVEL_MIC_64 0x02 ///< Bits containing the 64-bit Message Integrity Code (0b010). +#define SECURITY_LEVEL_MIC_128 0x03 ///< Bits containing the 128-bit Message Integrity Code (0b011). +#define SECURITY_LEVEL_ENC_MIC_32 0x05 ///< Bits containing the 32-bit Encrypted Message Integrity Code (0b101). +#define SECURITY_LEVEL_ENC_MIC_64 0x06 ///< Bits containing the 64-bit Encrypted Message Integrity Code (0b110). +#define SECURITY_LEVEL_ENC_MIC_128 0x07 ///< Bits containing the 128-bit Encrypted Message Integrity Code (0b111). +#define SECURITY_LEVEL_MIC_LEVEL_MASK 0x03 ///< Mask of bits encoding the Message Integrity Code length. + +#define SRC_ADDR_TYPE_EXTENDED 0xc0 ///< Bits containing the extended source address type. +#define SRC_ADDR_TYPE_NONE 0x00 ///< Bits containing a not-present source address type. +#define SRC_ADDR_TYPE_MASK 0xc0 ///< Mask of bits containing the source address type. +#define SRC_ADDR_TYPE_OFFSET 2 ///< Byte containing the source address type (+1 for the frame length byte). +#define SRC_ADDR_TYPE_SHORT 0x80 ///< Bits containing the short source address type. + +#define SRC_ADDR_OFFSET_SHORT_DST 8 ///< Offset of the source address in the Data frame if the destination address is short. +#define SRC_ADDR_OFFSET_EXTENDED_DST 14 ///< Offset of the source address in the Data frame if the destination address is extended. + +#define DSN_SIZE 1 ///< Size of the Sequence Number field. +#define FCF_SIZE 2 ///< Size of the FCF field. +#define FCS_SIZE 2 ///< Size of the FCS field. +#define FRAME_COUNTER_SIZE 4 ///< Size of the Frame Counter field. +#define IE_HEADER_SIZE 2 ///< Size of the obligatory IE Header field elements. +#define IMM_ACK_LENGTH 5 ///< Length of the ACK frame. +#define KEY_ID_MODE_1_SIZE 1 ///< Size of the 0x01 Key Identifier Mode field. +#define KEY_ID_MODE_2_SIZE 5 ///< Size of the 0x10 Key Identifier Mode field. +#define KEY_ID_MODE_3_SIZE 9 ///< Size of the 0x11 Key Identifier Mode field. +#define MAX_PACKET_SIZE 127 ///< Maximum size of the radio packet. +#define MIC_32_SIZE 4 ///< Size of MIC with the MIC-32 and ENC-MIC-32 security attributes. +#define MIC_64_SIZE 8 ///< Size of MIC with the MIC-64 and ENC-MIC-64 security attributes. +#define MIC_128_SIZE 16 ///< Size of MIC with the MIC-128 and ENC-MIC-128 security attributes. +#define PAN_ID_SIZE 2 ///< Size of the PAN ID. +#define PHR_SIZE 1 ///< Size of the PHR field. +#define SECURITY_CONTROL_SIZE 1 ///< Size of the Security Control field. + +#define AES_CCM_KEY_SIZE 16 ///< Size of AES CCM Key. + +#define EXTENDED_ADDRESS_SIZE 8 ///< Size of the Extended Mac Address. +#define SHORT_ADDRESS_SIZE 2 ///< Size of the Short Mac Address. + +#define TURNAROUND_TIME 192UL ///< RX-to-TX or TX-to-RX turnaround time (aTurnaroundTime), in microseconds (us). +#define CCA_TIME 128UL ///< Time required to perform CCA detection (aCcaTime), in microseconds (us). +#define UNIT_BACKOFF_PERIOD (TURNAROUND_TIME + CCA_TIME) ///< Number of symbols in the basic time period used by CSMA-CA algorithm (aUnitBackoffPeriod), in (us). + +#define PHY_US_PER_SYMBOL 16 ///< Duration of a single symbol in microseconds (us). +#define PHY_SYMBOLS_PER_OCTET 2 ///< Number of symbols in a single byte (octet). +#define PHY_SHR_SYMBOLS 10 ///< Number of symbols in the Synchronization Header (SHR). + +#define ED_RESULT_MAX 0xff ///< Maximal ED result. + +#define BROADCAST_ADDRESS ((uint8_t[SHORT_ADDRESS_SIZE]) {0xff, 0xff}) ///< Broadcast short address. + +#define MIN_SIFS_PERIOD_US 192 ///< Minimum Short IFS period default value in us. +#define MIN_LIFS_PERIOD_US 640 ///< Minimum Long IFS period default value in us. +#define MAX_SIFS_FRAME_SIZE 18 ///< Maximum frame length which can be followed by the Short Interframe Space. + +#define NRF_802154_RESERVED_CSMACA_ID (UINT32_MAX - 2) ///< Delayed timeslot identifier reserved for CSMA/CA procedure. +#define NRF_802154_RESERVED_DTX_ID (UINT32_MAX - 3) ///< Delayed timeslot identifier reserved for delayed transmissions. + +#define IE_VENDOR_ID 0x00 ///< Vendor-specific IE identifier +#define IE_VENDOR_SIZE_MIN 3 ///< Vendor-specific IE minimum length +#define IE_VENDOR_OUI_OFFSET 0 ///< Vendor-specific IE OUI offset + +#define IE_VENDOR_THREAD_SUBTYPE_OFFSET 3 ///< Thread Vendor-specific IE subtype offset +#define IE_VENDOR_THREAD_DATA_OFFSET 4 ///< Thread Vendor-specific IE DATA offset +#define IE_VENDOR_THREAD_OUI 0xeab89b ///< Thread Vendor-specific IE OUI +#define IE_VENDOR_THREAD_SIZE_MIN 4 ///< Thread Vendor-specific IE minimum length + +#define IE_VENDOR_THREAD_ACK_PROBING_ID 0x00 ///< Thread Vendor-specific ACK Probing IE subtype ID +#define IE_VENDOR_THREAD_ACK_SIZE_MIN 5 ///< Thread Vendor-specific ACK Probing IE minimum size +#define IE_VENDOR_THREAD_ACK_SIZE_MAX 6 ///< Thread Vendor-specific ACK Probing IE maximum size +#define IE_VENDOR_THREAD_RSSI_TOKEN 0x01 ///< Thread Vendor-specific ACK Probing IE RSSI value placeholder +#define IE_VENDOR_THREAD_MARGIN_TOKEN 0x02 ///< Thread Vendor-specific ACK Probing IE Link margin value placeholder +#define IE_VENDOR_THREAD_LQI_TOKEN 0x03 ///< Thread Vendor-specific ACK Probing IE LQI value placeholder +#define IE_VENDOR_THREAD_RSSI_FLOOR -130 ///< Thread Vendor-specific ACK Probing RSSI floor value used for scaling +#define IE_VENDOR_THREAD_MARGIN_FLOOR 0 ///< Thread Vendor-specific ACK Probing margin floor value used for scaling +#define IE_VENDOR_THREAD_RSSI_CEIL 0 ///< Thread Vendor-specific ACK Probing RSSI ceil value used for scaling +#define IE_VENDOR_THREAD_MARGIN_CEIL 130 ///< Thread Vendor-specific ACK Probing margin ceil value used for scaling +#define IE_CSL_SYMBOLS_PER_UNIT 10 ///< Number of symbols per phase/period unit +#define IE_CSL_PERIOD_MAX 0xffff ///< Maximum CSL IE phase/period value +#define IE_CSL_SIZE_MIN 4 ///< Minimal size of the CSL IE +#define IE_CSL_ID 0x1a ///< CSL IE identifier + +#define IE_HT1 0x7e ///< Information Element Header Termination type 1 +#define IE_HT2 0x7f ///< Information Element Header Termination type 2 +#define IE_LENGTH_MASK 0x7f ///< Information element length mask +#define IE_LENGTH_OFFSET 0x00 ///< Information element length offset +#define IE_ID_OFFSET_0 0x00 ///< Offset of the octet containing the first part of the IE identifier. +#define IE_ID_OFFSET_1 0x01 ///< Offset of the octed containing the second part of the IE identifier. +#define IE_DATA_OFFSET 0x02 ///< Information element data offset +#define IE_HEADER_ELEMENT_ID_OFFSET 0x07 ///< Bit offset of Element ID field in a Header IE header. + +#define ED_MIN_DBM (-92) ///< dBm value corresponding to value 0 in the EDSAMPLE register. +#define ED_RESULT_FACTOR 4 ///< Factor needed to calculate the ED result based on the data from the RADIO peripheral. #endif // NRF_802154_CONST_H_ diff --git a/drivers/nrf_802154/serialization/include/host/nrf_802154_types.h b/drivers/nrf_802154/serialization/include/host/nrf_802154_types.h index 54518db..052f538 100644 --- a/drivers/nrf_802154/serialization/include/host/nrf_802154_types.h +++ b/drivers/nrf_802154/serialization/include/host/nrf_802154_types.h @@ -88,7 +88,24 @@ typedef uint8_t nrf_802154_ed_error_t; */ typedef uint8_t nrf_802154_cca_error_t; -#define NRF_802154_CCA_ERROR_ABORTED 0x01 // !< Procedure was aborted by another operation. +#define NRF_802154_CCA_ERROR_ABORTED 0x01 // !< Procedure was aborted by another operation. + +/** @brief RADIO Clear Channel Assessment modes. */ +#define NRF_RADIO_CCA_MODE_ED 0x00 +#define NRF_RADIO_CCA_MODE_CARRIER 0x01 +#define NRF_RADIO_CCA_MODE_CARRIER_AND_ED 0x02 +#define NRF_RADIO_CCA_MODE_CARRIER_OR_ED 0x03 + +/** + * @brief Structure for configuring CCA. + */ +typedef struct +{ + uint8_t mode; // !< CCA mode. + uint8_t ed_threshold; // !< Busy threshold of the CCA energy. Not used in @ref NRF_RADIO_CCA_MODE_CARRIER. + uint8_t corr_threshold; // !< Busy threshold of the CCA correlator. Not used in @ref NRF_RADIO_CCA_MODE_ED. + uint8_t corr_limit; // !< Limit of occurrences above the busy threshold of the CCA correlator. Not used in @ref NRF_RADIO_CCA_MODE_ED. +} nrf_802154_cca_cfg_t; /** * @brief Types of data that can be set in an ACK message. @@ -102,7 +119,7 @@ typedef uint8_t nrf_802154_ack_data_t; * @brief Methods of source address matching. * * You can use one of the following methods that can be set during the initialization phase - * by calling @ref nrf_802154_src_matching_method: + * by calling @ref nrf_802154_src_addr_matching_method_set: * - For Thread: @ref NRF_802154_SRC_ADDR_MATCH_THREAD -- The pending bit is set only for the addresses found in the list. * - For Zigbee: @ref NRF_802154_SRC_ADDR_MATCH_ZIGBEE -- The pending bit is cleared only for the short addresses found in the list.\n * This method does not set pending bit in non-command and non-data-request frames. @@ -140,6 +157,25 @@ typedef uint32_t nrf_802154_capabilities_t; #define NRF_802154_CAPABILITY_TIMESTAMP (1UL << 6UL) // !< Frame timestamping supported #define NRF_802154_CAPABILITY_SECURITY (1UL << 7UL) // !< Frame security supported +/** + * @brief Type of structure holding time stamps of certain events. + */ +typedef struct +{ + /**@brief Time stamp of last CSMA/CA procedure started. */ + uint32_t last_csmaca_start_timestamp; + /**@brief Time stamp of last CCA start attempt. */ + uint32_t last_cca_start_timestamp; + /**@brief Time stamp of last CCA attempt finished with CCA IDLE (channel was free to transmit). */ + uint32_t last_cca_idle_timestamp; + /**@brief Time stamp when last bit of transmitted frame was sent on the air. */ + uint32_t last_tx_end_timestamp; + /**@brief Time stamp when last bit of acknowledge frame was received */ + uint32_t last_ack_end_timestamp; + /**@brief Time stamp when last bit of received frame was received. */ + uint32_t last_rx_end_timestamp; +} nrf_802154_stat_timestamps_t; + /** * @brief Structure with frame properties associated with the transmission operation. * @@ -181,6 +217,16 @@ typedef struct bool cca; // !< If the driver is to perform a CCA procedure before transmission. } nrf_802154_transmit_metadata_t; +/** + * @brief Structure with transmit request metadata for scheduling transmission at a specific time. + */ +typedef struct +{ + nrf_802154_transmitted_frame_props_t frame_props; // !< Properties of the frame to be transmitted. + bool cca; // !< If the driver is to perform a CCA procedure before transmission. + uint8_t channel; // !< Radio channel on which the frame is to be transmitted. +} nrf_802154_transmit_at_metadata_t; + /** * @brief Structure with transmit request metadata for transmission preceded by CSMA-CA procedure. */ @@ -213,6 +259,59 @@ typedef struct } data; // !< Result values that are valid only for successful operations. } nrf_802154_transmit_done_metadata_t; +/** + * @brief Possible errors during key handling. + */ +typedef uint8_t nrf_802154_security_error_t; + +#define NRF_802154_SECURITY_ERROR_NONE 0x00 // !< There is no error. +#define NRF_802154_SECURITY_ERROR_STORAGE_FULL 0x01 // !< The key storage is full - removal of stored keys is needed. +#define NRF_802154_SECURITY_ERROR_KEY_NOT_FOUND 0x02 // !< The provided key was not found inside the storage. +#define NRF_802154_SECURITY_ERROR_ALREADY_PRESENT 0x03 // !< The storage already has the key of the same ID. +#define NRF_802154_SECURITY_ERROR_TYPE_NOT_SUPPORTED 0x04 // !< The provided key type is not supported. +#define NRF_802154_SECURITY_ERROR_MODE_NOT_SUPPORTED 0x05 // !< The provided key id mode is not supported. +#define NRF_802154_SECURITY_ERROR_FRAME_COUNTER_OVERFLOW 0x06 // !< The associated frame counter overflowed. + +/** + * @brief Types of keys which can be used with the nRF 802.15.4 Radio Driver. + * + * Possible values: + * - @ref NRF_802154_KEY_CLEARTEXT, + * + */ +typedef uint32_t nrf_802154_key_type_t; + +#define NRF_802154_KEY_CLEARTEXT 0x00 // !< Key stored in clear text. + +/** + * @brief Type holding the value of Key Id Mode of the key stored in nRF 802.15.4 Radio Driver. + */ +typedef uint8_t nrf_802154_key_id_mode_t; + +/** + * @brief Type holding the value of Key Id for the keys stored in nRF 802.15.4 Radio Driver. + */ +typedef struct +{ + nrf_802154_key_id_mode_t mode; // !< Key Id Mode (0..3) + uint8_t * p_key_id; // !< Pointer to the Key Id field +} nrf_802154_key_id_t; + +/** + * @brief Type of structure holding a 802.15.4 MAC Security Key. + */ +typedef struct +{ + union + { + uint8_t * p_cleartext_key; // !< Pointer to the cleartext representation of the key. + } value; // !< Union holding different representations of the key. + nrf_802154_key_id_t id; // !< Key Id of the key. + nrf_802154_key_type_t type; // !< @ref nrf_802154_key_type_t type of the key used. + uint32_t frame_counter; // !< Frame counter to use in case @ref use_global_frame_counter is set to false. + bool use_global_frame_counter; // !< Whether to use the global frame counter instead of the one defined in this structure. +} nrf_802154_key_t; + /** *@} **/ diff --git a/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel.h b/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel.h index 9dfc824..1d7c602 100644 --- a/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel.h +++ b/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel.h @@ -60,12 +60,12 @@ extern "C" { #endif /* CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT */ /** - * @brief Maximal size of a Spinel frame in 802.15.4 serializaiton. + * @brief Maximal size of a Spinel frame in 802.15.4 serialization. */ -#define NRF_802154_SPINEL_FRAME_MAX_SIZE 256 +#define NRF_802154_SPINEL_FRAME_MAX_SIZE 296 /** - * @brief Buffer size for Spinel frame in 802.15.4 serializaiton. + * @brief Buffer size for Spinel frame in 802.15.4 serialization. * * This macro can used as a replacement for @ref SPINEL_FRAME_BUFFER_SIZE in 802.15.4 serialization * to reduce memory required for Spinel frame processing. diff --git a/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel_datatypes.h b/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel_datatypes.h index e5475c1..593db52 100644 --- a/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel_datatypes.h +++ b/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel_datatypes.h @@ -273,6 +273,120 @@ typedef enum SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET = SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 34, + /** + * Vendor property for nrf_802154_cca_cfg_get serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_GET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 35, + + /** + * Vendor property for nrf_802154_cca_cfg_set serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_SET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 36, + + /** + * Vendor property for nrf_802154_transmit_raw_at serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW_AT = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 37, + + /** + * Vendor property for nrf_802154_transmit_at_cancel serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_AT_CANCEL = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 38, + + /** + * Vendor property for nrf_802154_receive_at serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 39, + + /** + * Vendor property for nrf_802154_receive_at_cancel serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT_CANCEL = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 40, + + /** + * Vendor property for nrf_802154_security_global_frame_counter_set serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 41, + + /** + * Vendor property for nrf_802154_security_key_store serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_STORE = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 42, + + /** + * Vendor property for nrf_802154_security_key_remove serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_REMOVE = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 43, + + /** + * Vendor property for nrf_802154_csl_writer_period_set serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSL_WRITER_PERIOD_SET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 44, + + /** + * Vendor property for nrf_802154_csma_ca_min_be_set serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_SET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 45, + + /** + * Vendor property for nrf_802154_csma_ca_min_be_get serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_GET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 46, + + /** + * Vendor property for nrf_802154_csma_ca_max_be_set serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_SET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 47, + + /** + * Vendor property for nrf_802154_csma_ca_max_be_get serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_GET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 48, + + /** + * Vendor property for nrf_802154_csma_ca_max_backoffs_set serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_SET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 49, + + /** + * Vendor property for nrf_802154_csma_ca_max_backoffs_get serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 50, + + /** + * Vendor property for nrf_802154_stat_timestamps_get serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_STAT_TIMESTAMPS_GET = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 51, + + /** + * Vendor property for nrf_802154_continuous_carrier serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CONTINUOUS_CARRIER = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 52, + + /** + * Vendor property for nrf_802154_modulated_carrier serialization. + */ + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_MODULATED_CARRIER = + SPINEL_PROP_VENDOR_NORDIC_NRF_802154__BEGIN + 53, + } spinel_prop_vendor_key_t; /** @@ -370,41 +484,204 @@ typedef enum */ #define SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_METADATA_S \ SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S /* frame_props */ + /** * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_METADATA_S data type. */ #define NRF_802154_TRANSMIT_CSMA_CA_METADATA_ENCODE(tx_metadata) \ NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE((tx_metadata).frame_props) + /** * @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_METADATA_S data type. */ #define NRF_802154_TRANSMIT_CSMA_CA_METADATA_DECODE(tx_metadata) \ NRF_802154_TRANSMITTED_FRAME_PROPS_DECODE((tx_metadata).frame_props) +/** + * @brief Spinel data type description for nrf_802154_csma_ca_min_be_set. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_SET SPINEL_DATATYPE_UINT8_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_min_be_set result. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_SET_RET SPINEL_DATATYPE_BOOL_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_min_be_get. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_GET SPINEL_DATATYPE_NULL_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_min_be_get result. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_GET_RET SPINEL_DATATYPE_UINT8_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_max_be_set. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_SET SPINEL_DATATYPE_UINT8_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_max_be_set result. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_SET_RET SPINEL_DATATYPE_BOOL_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_max_be_get. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_GET SPINEL_DATATYPE_NULL_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_max_be_get result. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_GET_RET SPINEL_DATATYPE_UINT8_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_max_backoffs_set. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BACKOFFS_SET SPINEL_DATATYPE_UINT8_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_max_backoffs_get. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET SPINEL_DATATYPE_NULL_S + +/** + * @brief Spinel data type description for nrf_802154_csma_ca_max_backoffs_get result. + */ +#define SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET_RET SPINEL_DATATYPE_UINT8_S + +/** + * @brief Spinel data type description for nrf_802154_transmit_at_metadata_t. + */ +#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_AT_METADATA_S \ + SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S /* frame_props */ \ + SPINEL_DATATYPE_BOOL_S /* cca */ \ + SPINEL_DATATYPE_UINT8_S /* channel */ + +/** + * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_AT_METADATA_S data type. + */ +#define NRF_802154_TRANSMIT_AT_METADATA_ENCODE(tx_at_metadata) \ + NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE((tx_at_metadata).frame_props), \ + ((tx_at_metadata).cca), \ + ((tx_at_metadata).channel) + +/** + * @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_AT_METADATA_S data type. + */ +#define NRF_802154_TRANSMIT_AT_METADATA_DECODE(tx_at_metadata) \ + NRF_802154_TRANSMITTED_FRAME_PROPS_DECODE((tx_at_metadata).frame_props), \ + (&(tx_at_metadata).cca), \ + (&(tx_at_metadata).channel) + +/** + * @brief Spinel data type description for nrf_802154_cca_cfg_t. + */ +#define SPINEL_DATATYPE_NRF_802154_CCA_CFG_S \ + SPINEL_DATATYPE_UINT8_S /* mode */ \ + SPINEL_DATATYPE_UINT8_S /* ed_threshold */ \ + SPINEL_DATATYPE_UINT8_S /* corr_threshold */ \ + SPINEL_DATATYPE_UINT8_S /* corr_limit */ + +/** + * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_CCA_CFG_S data type. + */ +#define NRF_802154_CCA_CFG_ENCODE(cca_cfg) \ + ((cca_cfg).mode), ((cca_cfg).ed_threshold), ((cca_cfg).corr_threshold), ((cca_cfg).corr_limit) + +/** + * @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_CCA_CFG_S data type. + */ +#define NRF_802154_CCA_CFG_DECODE(cca_cfg) \ + (&(cca_cfg).mode), \ + (&(cca_cfg).ed_threshold), \ + (&(cca_cfg).corr_threshold), \ + (&(cca_cfg).corr_limit) + +/** + * @brief Spinel data type description for nrf_802154_stat_timestamps_t + */ +#define SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_S \ + SPINEL_DATATYPE_UINT32_S \ + SPINEL_DATATYPE_UINT32_S \ + SPINEL_DATATYPE_UINT32_S \ + SPINEL_DATATYPE_UINT32_S \ + SPINEL_DATATYPE_UINT32_S \ + SPINEL_DATATYPE_UINT32_S + +/** + * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_S data type. + */ +#define NRF_802154_STAT_TIMESTAMPS_ENCODE(stat_timestamps) \ + ((stat_timestamps).last_csmaca_start_timestamp), \ + ((stat_timestamps).last_cca_start_timestamp), \ + ((stat_timestamps).last_cca_idle_timestamp), \ + ((stat_timestamps).last_tx_end_timestamp), \ + ((stat_timestamps).last_ack_end_timestamp), \ + ((stat_timestamps).last_rx_end_timestamp) + +/** + * @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_S data type. + */ +#define NRF_802154_STAT_TIMESTAMPS_DECODE(stat_timestamps) \ + (&(stat_timestamps).last_csmaca_start_timestamp), \ + (&(stat_timestamps).last_cca_start_timestamp), \ + (&(stat_timestamps).last_cca_idle_timestamp), \ + (&(stat_timestamps).last_tx_end_timestamp), \ + (&(stat_timestamps).last_ack_end_timestamp), \ + (&(stat_timestamps).last_rx_end_timestamp) + /** * @brief Spinel data type description for SPINEL_PROP_LAST_STATUS. */ -#define SPINEL_DATATYPE_SPINEL_PROP_LAST_STATUS SPINEL_DATATYPE_UINT_PACKED_S +#define SPINEL_DATATYPE_SPINEL_PROP_LAST_STATUS SPINEL_DATATYPE_UINT_PACKED_S /** * @brief Spinel data type description for nrf_802154_sleep. */ -#define SPINEL_DATATYPE_NRF_802154_SLEEP SPINEL_DATATYPE_NULL_S +#define SPINEL_DATATYPE_NRF_802154_SLEEP SPINEL_DATATYPE_NULL_S /** * @brief Spinel data type description for nrf_802154_sleep result. */ -#define SPINEL_DATATYPE_NRF_802154_SLEEP_RET SPINEL_DATATYPE_BOOL_S +#define SPINEL_DATATYPE_NRF_802154_SLEEP_RET SPINEL_DATATYPE_BOOL_S /** * @brief Spinel data type description for nrf_802154_receive. */ -#define SPINEL_DATATYPE_NRF_802154_RECEIVE SPINEL_DATATYPE_NULL_S +#define SPINEL_DATATYPE_NRF_802154_RECEIVE SPINEL_DATATYPE_NULL_S /** * @brief Spinel data type description for nrf_802154_receive result. */ -#define SPINEL_DATATYPE_NRF_802154_RECEIVE_RET SPINEL_DATATYPE_BOOL_S +#define SPINEL_DATATYPE_NRF_802154_RECEIVE_RET SPINEL_DATATYPE_BOOL_S + +/** + * @brief Spinel data type description for nrf_802154_receive_at. + */ +#define SPINEL_DATATYPE_NRF_802154_RECEIVE_AT \ + SPINEL_DATATYPE_UINT32_S /* t0 */ \ + SPINEL_DATATYPE_UINT32_S /* dt */ \ + SPINEL_DATATYPE_UINT32_S /* timeout */ \ + SPINEL_DATATYPE_UINT8_S /* channel */ \ + SPINEL_DATATYPE_UINT32_S /* window id */ \ + +/** + * @brief Spinel data type description for nrf_802154_receive_at result. + */ +#define SPINEL_DATATYPE_NRF_802154_RECEIVE_AT_RET SPINEL_DATATYPE_BOOL_S + +/** + * @brief Spinel data type description for nrf_802154_receive_at_cancel. + */ +#define SPINEL_DATATYPE_NRF_802154_RECEIVE_AT_CANCEL SPINEL_DATATYPE_UINT32_S + +/** + * @brief Spinel data type description for nrf_802154_receive_at_cancel result. + */ +#define SPINEL_DATATYPE_NRF_802154_RECEIVE_AT_CANCEL_RET SPINEL_DATATYPE_BOOL_S /** * @brief Spinel data type description for nrf_802154_pan_id_set. @@ -471,6 +748,26 @@ typedef enum */ #define SPINEL_DATATYPE_NRF_802154_ENERGY_DETECTION_FAILED SPINEL_DATATYPE_UINT8_S +/** + * @brief Spinel data type description for nrf_802154_continuous_carrier. + */ +#define SPINEL_DATATYPE_NRF_802154_CONTINUOUS_CARRIER SPINEL_DATATYPE_NULL_S + +/** + * @brief Spinel data type description for nrf_802154_nrf_802154_continuous_carrier result. + */ +#define SPINEL_DATATYPE_NRF_802154_CONTINUOUS_CARRIER_RET SPINEL_DATATYPE_BOOL_S + +/** + * @brief Spinel data type description for nrf_802154_modulated_carrier. + */ +#define SPINEL_DATATYPE_NRF_802154_MODULATED_CARRIER SPINEL_DATATYPE_DATA_S + +/** + * @brief Spinel data type description for nrf_802154_nrf_802154_modulated_carrier result. + */ +#define SPINEL_DATATYPE_NRF_802154_MODULATED_CARRIER_RET SPINEL_DATATYPE_BOOL_S + /** * @brief Spinel data type description for nrf_802154_tx_power_get. */ @@ -531,6 +828,16 @@ typedef enum */ #define SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW_RET SPINEL_DATATYPE_BOOL_S +/** + * @brief Spinel data type description for return value of nrf_802154_transmit_raw_at + */ +#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW_AT_RET SPINEL_DATATYPE_BOOL_S + +/** + * @brief Spinel data type description for return value of nrf_802154_transmit_at_cancel + */ +#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_AT_CANCEL_RET SPINEL_DATATYPE_BOOL_S + /** * @brief Spinel data type desription for nrf_802154_auto_pending_bit_set. */ @@ -606,6 +913,20 @@ typedef enum SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_METADATA_S \ SPINEL_DATATYPE_NRF_802154_HDATA_S /* Frame to transmit with its handle */ +/** + * @brief Spinel data type description for nrf_802154_transmit_raw_at + */ +#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW_AT \ + SPINEL_DATATYPE_NRF_802154_TRANSMIT_AT_METADATA_S \ + SPINEL_DATATYPE_UINT32_S /* t0 */ \ + SPINEL_DATATYPE_UINT32_S /* dt */ \ + SPINEL_DATATYPE_NRF_802154_HDATA_S /* Frame to transmit with its handle */ + +/** + * @brief Spinel data type description for nrf_802154_sleep. + */ +#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_AT_CANCEL SPINEL_DATATYPE_NULL_S + /** * @brief Spinel data type description for nrf_802154_transmit_done_metadata. */ @@ -621,7 +942,7 @@ typedef enum * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_DONE_METADATA_S data type. * * @param[in] metadata Transmit done metadata structure to be decoded. - * @param[in] ack_handle Variable containing handle to + * @param[in] ack_handle Variable containing handle to remote ack frame. */ #define NRF_802154_TRANSMIT_DONE_METADATA_ENCODE(metadata, ack_handle) \ NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE((metadata).frame_props), \ @@ -649,20 +970,104 @@ typedef enum &(metadata).data.transmitted.time, \ NRF_802154_HDATA_DECODE(ack_handle, (metadata).data.transmitted.p_ack, ack_length) +/** + * @brief Spinel data type description for nrf_802154_transmit_failed_metadata. + */ +#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED_METADATA_S \ + SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S /* Frame props */ + +/** + * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED_METADATA_S data type. + * + * @param[in] metadata Transmit failed metadata structure to be encoded. + */ +#define NRF_802154_TRANSMIT_FAILED_METADATA_ENCODE(metadata) \ + NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE((metadata).frame_props) + +/** + * @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED_METADATA_S data type. + * + * @param[out] metadata Transmit failed metadata structure to which store decoded data. + */ +#define NRF_802154_TRANSMIT_FAILED_METADATA_DECODE(metadata) \ + NRF_802154_TRANSMITTED_FRAME_PROPS_DECODE((metadata).frame_props) + /** * @brief Spinel data type description for nrf_802154_transmitted_raw. */ -#define SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW \ - SPINEL_DATATYPE_UINT32_S /* Handle to transmitted frame */ \ +#define SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW \ + SPINEL_DATATYPE_NRF_802154_HDATA_S /* Transmitted frame and its handle*/ \ SPINEL_DATATYPE_NRF_802154_TRANSMIT_DONE_METADATA_S /* Transmit done metadata */ +/** + * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW data type. + * + * @param[in] frame_handle Variable containing remote frame handle. + * @param[in] frame_data Pointer to contents of frame. + * @param[in] metadata Transmit done metadata structure to be encoded. + * @param[in] ack_handle Variable containing handle to received Ack. + */ +#define NRF_802154_TRANSMITTED_RAW_ENCODE(frame_handle, frame_data, metadata, ack_handle) \ + NRF_802154_HDATA_ENCODE(frame_handle, frame_data, frame_data[0] + 1), \ + NRF_802154_TRANSMIT_DONE_METADATA_ENCODE(metadata, ack_handle) + +/** + * @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW data type. + * + * @param[out] frame_handle Pointer variable to which store handle of transmitted frame. + * @param[out] frame_data Pointer to memory to which store contents of transmitted frame. + * @param[out] frame_length Variable to which store length of the decoded frame. + * @param[out] metadata Transmit done metadata structure to which store decoded data. + * @param[out] ack_handle Pointer variable to which store handle of ACK frame. + * @param[out] ack_length Variable to which store length of the decoded ACK frame. + */ +#define NRF_802154_TRANSMITTED_RAW_DECODE(frame_handle, \ + frame_data, \ + frame_length, \ + metadata, \ + ack_handle, \ + ack_length) \ + NRF_802154_HDATA_DECODE(frame_handle, frame_data, frame_length), \ + NRF_802154_TRANSMIT_DONE_METADATA_DECODE(metadata, ack_handle, ack_length) + /** * @brief Spinel data type description for nrf_802154_transmit_failed. */ -#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED \ - SPINEL_DATATYPE_UINT32_S /* Handle to transmitted frame */ \ - SPINEL_DATATYPE_UINT8_S /* Error code */ \ - SPINEL_DATATYPE_NRF_802154_TRANSMITTED_FRAME_PROPS_S /* Frame props */ +#define SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED \ + SPINEL_DATATYPE_NRF_802154_HDATA_S /* Frame that was attempted to be transmitted and its handle */ \ + SPINEL_DATATYPE_UINT8_S /* Error code */ \ + SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED_METADATA_S /* Transmit failed metadata */ + +/** + * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED data type. + * + * @param[in] frame_handle Variable containing remote frame handle. + * @param[in] frame_data Pointer to contents of frame. + * @param[in] error_code Error code to be encoded. + * @param[in] metadata Transmit failed metadata structure to be encoded. + */ +#define NRF_802154_TRANSMIT_FAILED_ENCODE(frame_handle, frame_data, error_code, metadata) \ + NRF_802154_HDATA_ENCODE(frame_handle, frame_data, frame_data[0] + 1), \ + error_code, \ + NRF_802154_TRANSMIT_FAILED_METADATA_ENCODE(metadata) + +/** + * @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED data type. + * + * @param[out] frame_handle Pointer variable to which store handle of frame failed to transmit. + * @param[out] frame_data Pointer to memory to which store contents of frame failed to transmit. + * @param[out] frame_length Variable to which store length of the decoded frame. + * @param[in] error_code Variable to which store decode error code. + * @param[out] metadata Transmit failed metadata structure to which store decoded data. + */ +#define NRF_802154_TRANSMIT_FAILED_DECODE(frame_handle, \ + frame_data, \ + frame_length, \ + error_code, \ + metadata) \ + NRF_802154_HDATA_DECODE(frame_handle, frame_data, frame_length), \ + &error_code, \ + NRF_802154_TRANSMIT_FAILED_METADATA_DECODE(metadata) /** * @brief Spinel data type description for nrf_802154_capabilities_get. @@ -684,6 +1089,129 @@ typedef enum */ #define SPINEL_DATATYPE_NRF_802154_TIME_GET_RET SPINEL_DATATYPE_UINT32_S +/** + * @brief Spinel data type description for nrf_802154_cca_cfg_get. + */ +#define SPINEL_DATATYPE_NRF_802154_CCA_CFG_GET SPINEL_DATATYPE_NULL_S + +/** + * @brief Spinel data type description for nrf_802154_cca_cfg_get_ret. + */ +#define SPINEL_DATATYPE_NRF_802154_CCA_CFG_GET_RET \ + SPINEL_DATATYPE_NRF_802154_CCA_CFG_S + +/** + * @brief Spinel data type description for nrf_802154_cca_cfg_get. + */ +#define SPINEL_DATATYPE_NRF_802154_CCA_CFG_SET \ + SPINEL_DATATYPE_NRF_802154_CCA_CFG_S + +/** + * @brief Spinel data type description for nrf_802154_security_global_frame_counter_set. + */ +#define SPINEL_DATATYPE_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET SPINEL_DATATYPE_UINT32_S + +/** + * @brief Spinel data type description for nrf_802154_security_key_store. + */ +#define SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_STORE \ + SPINEL_DATATYPE_STRUCT_S( \ + SPINEL_DATATYPE_DATA_S /* Key value */ \ + ) \ + SPINEL_DATATYPE_STRUCT_S( \ + SPINEL_DATATYPE_UINT8_S /* Key mode */ \ + SPINEL_DATATYPE_DATA_S /* Key ID */ \ + ) \ + SPINEL_DATATYPE_UINT32_S /* Key type */ \ + SPINEL_DATATYPE_UINT32_S /* Frame counter */ \ + SPINEL_DATATYPE_BOOL_S /* Whether to use global frame counter */ + +/** + * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_STORE data type. + * + * @param[in] key Key structure (of @ref nrf_802154_key_t type) to be encoded. + * @param[in] key_size Size of the key data, i.e. cleartext size. + * @param[in] key_id_size Size of the key id in @p key structure. + */ +#define NRF_802154_SECURITY_KEY_STORE_ENCODE(key, key_size, key_id_size) \ + (key).value.p_cleartext_key, \ + (key_size), \ + (key).id.mode, \ + (key).id.p_key_id, \ + (key_id_size), \ + (key).type, \ + (key).frame_counter, \ + (key).use_global_frame_counter + +/** + * @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_STORE data type. + * + * @param[out] key Key structure (of @ref nrf_802154_key_t type) to which store decoded data. + * @param[out] key_size Variable to which store size of the decoded key, i.e. cleartext size. + * @param[out] key_id_size Variable to which store size of the decoded key ID. + */ +#define NRF_802154_SECURITY_KEY_STORE_DECODE(key, key_size, key_id_size) \ + & (key).value.p_cleartext_key, \ + &(key_size), \ + &(key).id.mode, \ + &(key).id.p_key_id, \ + &(key_id_size), \ + &(key).type, \ + &(key).frame_counter, \ + &(key).use_global_frame_counter + +/** + * @brief Spinel data type description for nrf_802154_security_key_remove. + */ +#define SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_REMOVE \ + SPINEL_DATATYPE_STRUCT_S( \ + SPINEL_DATATYPE_UINT8_S /* Key mode */ \ + SPINEL_DATATYPE_DATA_S /* Key ID */ \ + ) + +/** + * @brief Encodes an instance of @ref SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_REMOVE data type. + * + * @param[in] key_id Key ID structure (of @ref nrf_802154_key_id_t type) to be encoded. + * @param[in] key_id_size Size of the key id in @p key_id structure. + */ +#define NRF_802154_SECURITY_KEY_REMOVE_ENCODE(key_id, key_id_size) \ + (key_id).mode, \ + (key_id).p_key_id, \ + (key_id_size) + +/** + * @brief Decodes an instance of @ref SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_STORE data type. + * + * @param[out] key_id Key ID structure (of @ref nrf_802154_key_id_t type) to which store decoded data. + * @param[out] key_id_size Variable to which store size of the decoded key ID. + */ +#define NRF_802154_SECURITY_KEY_REMOVE_DECODE(key_id, key_id_size) \ + & (key_id).mode, \ + &(key_id).p_key_id, \ + &(key_id_size) + +/** + * @brief Spinel data type description for return type for security commands. + */ +#define SPINEL_DATATYPE_NRF_802154_SECURITY_ERROR_RET SPINEL_DATATYPE_UINT8_S + +/** + * @brief Spinel data type description for nrf_802154_csl_writer_period_set. + */ +#define SPINEL_DATATYPE_NRF_802154_CSL_WRITER_PERIOD_SET SPINEL_DATATYPE_UINT16_S + +/** + * @brief Spinel data type description for nrf_802154_stat_timestamps_get + */ +#define SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_GET SPINEL_DATATYPE_NULL_S + +/** + * @brief Spinel data type description for nrf_802154_stat_timestamps_get_ret. + */ +#define SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_GET_RET \ + SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_S + #ifdef __cplusplus } #endif diff --git a/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel_dec_app.h b/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel_dec_app.h index 7cf63c4..07c2334 100644 --- a/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel_dec_app.h +++ b/drivers/nrf_802154/serialization/src/include/nrf_802154_spinel_dec_app.h @@ -48,6 +48,7 @@ #include "nrf_802154_serialization_error.h" #include "nrf_802154.h" +#include "nrf_802154_types.h" #ifdef __cplusplus extern "C" { @@ -84,6 +85,23 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_generic_bool( size_t property_data_len, bool * p_bool_response); +/** + * @brief Decode SPINEL_DATATYPE_UINT8_S. + * + * @note This is used to decode `uint8_t` responses for several kinds of requests in 802.15.4 radio driver. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * @param[out] p_uint8_response Pointer to decoded response value. + * + * @returns zero on success or negative error value on failure. + * + */ +nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_generic_uint8( + const void * p_property_data, + size_t property_data_len, + uint8_t * p_uint8_response); + /** * @brief Decode SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TX_POWER_GET. * @@ -132,7 +150,7 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_capabilities_get_r * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. * @param[in] property_data_len Size of the @ref p_property_data buffer. - * @param[out] p_capabilities Decoded capabilities. + * @param[out] p_time Decoded time. * * @returns zero on success or negative error value on failure. * @@ -142,6 +160,36 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_time_get_ret( size_t property_data_len, uint32_t * p_time); +/** + * @brief Decode SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_GET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * @param[out] p_cfg Decoded CCA configuration. + * + * @returns zero on success or negative error value on failure. + * + */ +nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_cca_cfg_get_ret( + const void * p_property_data, + size_t property_data_len, + nrf_802154_cca_cfg_t * p_cfg); + +/** + * @brief Decode SPINEL_PROP_VENDOR_NORDIC_NRF_802154_STAT_TIMESTAMPS_GET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * @param[out] p_stat_timestamps Decoded stat timestamps + * + * @returns zero on success or negative error value on failure. + * + */ +nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_stat_timestamps_get_ret( + const void * p_property_data, + size_t property_data_len, + nrf_802154_stat_timestamps_t * p_stat_timestamps); + /** * @brief Decode and dispatch SPINEL_CMD_PROP_VALUE_IS. * diff --git a/drivers/nrf_802154/serialization/src/nrf_802154_buffer_allocator.c b/drivers/nrf_802154/serialization/src/nrf_802154_buffer_allocator.c index a639b01..cda3fe0 100644 --- a/drivers/nrf_802154/serialization/src/nrf_802154_buffer_allocator.c +++ b/drivers/nrf_802154/serialization/src/nrf_802154_buffer_allocator.c @@ -45,7 +45,6 @@ #include #include #include -#include static uint8_t * buffer_alloc(nrf_802154_buffer_t * p_buffer_pool, size_t buffer_pool_len) { diff --git a/drivers/nrf_802154/serialization/src/nrf_802154_spinel_app.c b/drivers/nrf_802154/serialization/src/nrf_802154_spinel_app.c index 5ef8fa1..89e7534 100644 --- a/drivers/nrf_802154/serialization/src/nrf_802154_spinel_app.c +++ b/drivers/nrf_802154/serialization/src/nrf_802154_spinel_app.c @@ -61,6 +61,7 @@ #include "nrf_802154_buffer_mgr_src.h" #include "nrf_802154.h" +#include "nrf_802154_config.h" #include "nrf_802154_types.h" /** @@ -111,16 +112,14 @@ bail: /** * @brief Wait with timeout for some single bool property to be received. * - * @param[out] p_net_response Pointer to the bool variable which needs to be populated. - * @param[in] property_id Awaited property identifier. * @param[in] timeout Timeout in us. + * @param[out] p_net_response Pointer to the bool variable which needs to be populated. * * @returns zero on success or negative error value on failure. * */ -static nrf_802154_ser_err_t net_generic_bool_response_await( - bool * p_net_response, - uint32_t timeout) +static nrf_802154_ser_err_t net_generic_bool_response_await(uint32_t timeout, + bool * p_net_response) { nrf_802154_ser_err_t res; nrf_802154_spinel_notify_buff_t * p_notify_data = NULL; @@ -153,37 +152,37 @@ bail: } /** - * @brief Wait with timeout for channel property to be received. + * @brief Wait with timeout for some single uint8_t property to be received. * - * @param[in] timeout Timeout in us. - * @param[out] p_channel Pointer to the channel variable which needs to be populated. + * @param[in] timeout Timeout in us. + * @param[out] p_net_response Pointer to the uint8_t variable which needs to be populated. * * @returns zero on success or negative error value on failure. * */ -static nrf_802154_ser_err_t channel_await(uint32_t timeout, uint8_t * p_channel) +static nrf_802154_ser_err_t net_generic_uint8_response_await(uint32_t timeout, + uint8_t * p_net_response) { nrf_802154_ser_err_t res; nrf_802154_spinel_notify_buff_t * p_notify_data = NULL; SERIALIZATION_ERROR_INIT(error); - p_notify_data = nrf_802154_spinel_response_notifier_property_await( - timeout); + p_notify_data = nrf_802154_spinel_response_notifier_property_await(timeout); SERIALIZATION_ERROR_IF(p_notify_data == NULL, NRF_802154_SERIALIZATION_ERROR_RESPONSE_TIMEOUT, error, bail); - res = nrf_802154_spinel_decode_prop_channel(p_notify_data->data, - p_notify_data->data_len, - p_channel); + res = nrf_802154_spinel_decode_prop_generic_uint8(p_notify_data->data, + p_notify_data->data_len, + p_net_response); SERIALIZATION_ERROR_CHECK(res, error, bail); NRF_802154_SPINEL_LOG_BANNER_RESPONSE(); - NRF_802154_SPINEL_LOG_VAR_NAMED("%u", *p_channel, "channel"); + NRF_802154_SPINEL_LOG_VAR_NAMED("%u", *p_net_response, "net response"); bail: if (p_notify_data != NULL) @@ -322,6 +321,52 @@ bail: return error; } +/** + * @brief Wait with timeout for CCA configuration property to be received. + * + * @param[in] timeout Timeout in us. + * @param[out] p_cfg Pointer to the CCA configuration variable which needs to be populated. + * + * @returns zero on success or negative error value on failure. + * + */ +static nrf_802154_ser_err_t cca_cfg_await(uint32_t timeout, + nrf_802154_cca_cfg_t * p_cfg) +{ + nrf_802154_ser_err_t res; + nrf_802154_spinel_notify_buff_t * p_notify_data = NULL; + + SERIALIZATION_ERROR_INIT(error); + + p_notify_data = nrf_802154_spinel_response_notifier_property_await( + timeout); + + SERIALIZATION_ERROR_IF(p_notify_data == NULL, + NRF_802154_SERIALIZATION_ERROR_RESPONSE_TIMEOUT, + error, + bail); + + res = nrf_802154_spinel_decode_prop_nrf_802154_cca_cfg_get_ret(p_notify_data->data, + p_notify_data->data_len, + p_cfg); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + NRF_802154_SPINEL_LOG_BANNER_RESPONSE(); + NRF_802154_SPINEL_LOG_VAR_NAMED("%u", p_cfg->mode, "Mode"); + NRF_802154_SPINEL_LOG_VAR_NAMED("%u", p_cfg->ed_threshold, "ED threshold"); + NRF_802154_SPINEL_LOG_VAR_NAMED("%u", p_cfg->corr_threshold, "Corr threshold"); + NRF_802154_SPINEL_LOG_VAR_NAMED("%u", p_cfg->corr_limit, "Corr limit"); + +bail: + if (p_notify_data != NULL) + { + nrf_802154_spinel_response_notifier_free(p_notify_data); + } + + return error; +} + void nrf_802154_init(void) { nrf_802154_serialization_init(); @@ -345,8 +390,8 @@ bool nrf_802154_sleep(void) SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await(&sleep_remote_resp, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &sleep_remote_resp); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -374,8 +419,8 @@ bool nrf_802154_receive(void) SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await(&receive_remote_resp, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &receive_remote_resp); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -385,6 +430,75 @@ bail: return receive_remote_resp; } +bool nrf_802154_receive_at(uint32_t t0, + uint32_t dt, + uint32_t timeout, + uint8_t channel, + uint32_t id) +{ + nrf_802154_ser_err_t res; + bool rx_at_result = false; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT, + SPINEL_DATATYPE_NRF_802154_RECEIVE_AT, + t0, + dt, + timeout, + channel, + id); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &rx_at_result); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return rx_at_result; + +} + +bool nrf_802154_receive_at_cancel(uint32_t id) +{ + nrf_802154_ser_err_t res; + bool cancel_result = false; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT_CANCEL); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT_CANCEL, + SPINEL_DATATYPE_NRF_802154_RECEIVE_AT_CANCEL, + id); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &cancel_result); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return cancel_result; +} + void nrf_802154_pan_id_set(const uint8_t * p_pan_id) { nrf_802154_ser_err_t res; @@ -574,8 +688,8 @@ bool nrf_802154_ack_data_set(const uint8_t * p_addr, SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await(&ack_data_set_res, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &ack_data_set_res); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -610,8 +724,8 @@ bool nrf_802154_ack_data_clear(const uint8_t * p_addr, SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await(&ack_data_clear_res, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &ack_data_clear_res); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -668,8 +782,8 @@ bool nrf_802154_pending_bit_for_addr_set(const uint8_t * p_addr, bool extended) SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await(&addr_set_res, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &addr_set_res); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -701,8 +815,8 @@ bool nrf_802154_pending_bit_for_addr_clear(const uint8_t * p_addr, bool extended SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await(&addr_clr_res, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &addr_clr_res); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -784,7 +898,8 @@ uint8_t nrf_802154_channel_get(void) SERIALIZATION_ERROR_CHECK(res, error, bail); - res = channel_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, &channel); + res = net_generic_uint8_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &channel); SERIALIZATION_ERROR_CHECK(res, error, bail); bail: @@ -811,8 +926,8 @@ bool nrf_802154_cca(void) SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await(&cca_result, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &cca_result); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -822,6 +937,72 @@ bail: return cca_result; } +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + +bool nrf_802154_continuous_carrier(void) +{ + nrf_802154_ser_err_t res; + bool continuous_carrier_result = false; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CONTINUOUS_CARRIER); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CONTINUOUS_CARRIER, + SPINEL_DATATYPE_NRF_802154_CONTINUOUS_CARRIER, + NULL); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &continuous_carrier_result); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return continuous_carrier_result; +} + +bool nrf_802154_modulated_carrier(const uint8_t * p_data) +{ + nrf_802154_ser_err_t res; + bool modulated_carrier_result = false; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + NRF_802154_SPINEL_LOG_BUFF(p_data, RAW_PAYLOAD_OFFSET + p_data[0]); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_MODULATED_CARRIER); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_MODULATED_CARRIER, + SPINEL_DATATYPE_NRF_802154_MODULATED_CARRIER, + p_data, + RAW_PAYLOAD_OFFSET + p_data[0]); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &modulated_carrier_result); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return modulated_carrier_result; +} + +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + bool nrf_802154_energy_detection(uint32_t time_us) { nrf_802154_ser_err_t res; @@ -841,9 +1022,8 @@ bool nrf_802154_energy_detection(uint32_t time_us) SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await( - &ed_result, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &ed_result); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -853,6 +1033,8 @@ bail: return ed_result; } +#if NRF_802154_CSMA_CA_ENABLED + bool nrf_802154_transmit_csma_ca_raw(uint8_t * p_data, const nrf_802154_transmit_csma_ca_metadata_t * p_metadata) { @@ -892,8 +1074,8 @@ bool nrf_802154_transmit_csma_ca_raw(uint8_t SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await(&transmit_result, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &transmit_result); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -913,6 +1095,182 @@ bail: return transmit_result; } +bool nrf_802154_csma_ca_min_be_set(uint8_t min_be) +{ + nrf_802154_ser_err_t res; + bool result = false; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + NRF_802154_SPINEL_LOG_VAR("%u", min_be); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_SET); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_SET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_SET, + min_be); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &result); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return result; +} + +uint8_t nrf_802154_csma_ca_min_be_get(void) +{ + nrf_802154_ser_err_t res; + uint8_t min_be = 0; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_GET); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_GET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_GET, + &min_be); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_uint8_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &min_be); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return min_be; +} + +bool nrf_802154_csma_ca_max_be_set(uint8_t max_be) +{ + nrf_802154_ser_err_t res; + bool result = false; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + NRF_802154_SPINEL_LOG_VAR("%u", max_be); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_SET); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_SET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_SET, + max_be); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &result); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return result; +} + +uint8_t nrf_802154_csma_ca_max_be_get(void) +{ + nrf_802154_ser_err_t res; + uint8_t max_be = 0; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_GET); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_GET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_GET, + &max_be); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_uint8_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &max_be); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return max_be; +} + +void nrf_802154_csma_ca_max_backoffs_set(uint8_t max_backoffs) +{ + nrf_802154_ser_err_t res; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + NRF_802154_SPINEL_LOG_VAR("%u", max_backoffs); + + nrf_802154_spinel_response_notifier_lock_before_request(SPINEL_PROP_LAST_STATUS); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_SET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BACKOFFS_SET, + max_backoffs); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = status_ok_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return; +} + +uint8_t nrf_802154_csma_ca_max_backoffs_get(void) +{ + nrf_802154_ser_err_t res; + uint8_t max_backoffs = 0; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET, + &max_backoffs); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_uint8_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &max_backoffs); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return max_backoffs; +} + +#endif // NRF_802154_CSMA_CA_ENABLED + bool nrf_802154_transmit_raw(uint8_t * p_data, const nrf_802154_transmit_metadata_t * p_metadata) { @@ -953,8 +1311,8 @@ bool nrf_802154_transmit_raw(uint8_t * p_data, SERIALIZATION_ERROR_CHECK(res, error, bail); - res = net_generic_bool_response_await(&transmit_result, - CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &transmit_result); SERIALIZATION_ERROR_CHECK(res, error, bail); @@ -974,6 +1332,102 @@ bail: return transmit_result; } +bool nrf_802154_transmit_raw_at(uint8_t * p_data, + uint32_t t0, + uint32_t dt, + const nrf_802154_transmit_at_metadata_t * p_metadata) +{ + nrf_802154_ser_err_t res; + uint32_t data_handle; + bool transmit_result = false; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + NRF_802154_SPINEL_LOG_BUFF(p_data, p_data[0]); + + bool handle_added = nrf_802154_buffer_mgr_src_add(nrf_802154_spinel_src_buffer_mgr_get(), + p_data, + &data_handle); + + if (p_metadata == NULL) + { + static const nrf_802154_transmit_at_metadata_t metadata_default = + { + .frame_props = NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT, + .cca = true, + .channel = 11 + }; + + p_metadata = &metadata_default; + } + + SERIALIZATION_ERROR_IF(!handle_added, NRF_802154_SERIALIZATION_ERROR_NO_MEMORY, error, bail); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW_AT); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW_AT, + SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW_AT, + NRF_802154_TRANSMIT_AT_METADATA_ENCODE(*p_metadata), + t0, + dt, + NRF_802154_HDATA_ENCODE(data_handle, p_data, p_data[0])); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &transmit_result); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + return transmit_result; + +bail: + if (handle_added) + { + /* Rollback what we did until an error to avoid memory leak. */ + nrf_802154_buffer_mgr_src_remove_by_buffer_handle( + nrf_802154_spinel_src_buffer_mgr_get(), + data_handle); + } + + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return transmit_result; +} + +bool nrf_802154_transmit_at_cancel(void) +{ + nrf_802154_ser_err_t res; + bool cancel_result = false; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_AT_CANCEL); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_AT_CANCEL, + SPINEL_DATATYPE_NRF_802154_TRANSMIT_AT_CANCEL, + NULL); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_bool_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + &cancel_result); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return cancel_result; +} + void nrf_802154_buffer_free_raw(uint8_t * p_data) { nrf_802154_ser_err_t res; @@ -1100,7 +1554,7 @@ bail: uint32_t nrf_802154_time_get(void) { int32_t res; - uint32_t time; + uint32_t time = 0UL; SERIALIZATION_ERROR_INIT(error); @@ -1125,7 +1579,239 @@ bail: return time; } +void nrf_802154_cca_cfg_set(const nrf_802154_cca_cfg_t * p_cfg) +{ + nrf_802154_ser_err_t res; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + NRF_802154_SPINEL_LOG_VAR_NAMED("%u", p_cfg->mode, "Mode"); + NRF_802154_SPINEL_LOG_VAR_NAMED("%u", p_cfg->ed_threshold, "ED threshold"); + NRF_802154_SPINEL_LOG_VAR_NAMED("%u", p_cfg->corr_threshold, "Corr threshold"); + NRF_802154_SPINEL_LOG_VAR_NAMED("%u", p_cfg->corr_limit, "Corr limit"); + + nrf_802154_spinel_response_notifier_lock_before_request(SPINEL_PROP_LAST_STATUS); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_SET, + SPINEL_DATATYPE_NRF_802154_CCA_CFG_SET, + NRF_802154_CCA_CFG_ENCODE(*p_cfg)); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = status_ok_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return; +} + +void nrf_802154_cca_cfg_get(nrf_802154_cca_cfg_t * p_cfg) +{ + nrf_802154_ser_err_t res; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_GET); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_GET, + SPINEL_DATATYPE_NRF_802154_CCA_CFG_GET, + NULL); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = cca_cfg_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, p_cfg); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); +} + int8_t nrf_802154_dbm_from_energy_level_calculate(uint8_t energy_level) { return ED_MIN_DBM + (energy_level / ED_RESULT_FACTOR); } + +uint32_t nrf_802154_first_symbol_timestamp_get(uint32_t end_timestamp, uint8_t psdu_length) +{ + uint32_t frame_symbols = PHY_SHR_SYMBOLS; + + frame_symbols += (PHR_SIZE + psdu_length) * PHY_SYMBOLS_PER_OCTET; + + return end_timestamp - (frame_symbols * PHY_US_PER_SYMBOL); +} + +void nrf_802154_security_global_frame_counter_set(uint32_t frame_counter) +{ + nrf_802154_ser_err_t res; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request(SPINEL_PROP_LAST_STATUS); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET, + SPINEL_DATATYPE_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET, + frame_counter); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = status_ok_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return; +} + +nrf_802154_security_error_t nrf_802154_security_key_store(nrf_802154_key_t * p_key) +{ + nrf_802154_ser_err_t res; + nrf_802154_security_error_t err = NRF_802154_SECURITY_ERROR_NONE;; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_STORE); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_STORE, + SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_STORE, + NRF_802154_SECURITY_KEY_STORE_ENCODE(*p_key, AES_CCM_KEY_SIZE, KEY_ID_MODE_3_SIZE)); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_uint8_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, &err); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return err; +} + +nrf_802154_security_error_t nrf_802154_security_key_remove(nrf_802154_key_id_t * p_id) +{ + nrf_802154_ser_err_t res; + nrf_802154_security_error_t err = NRF_802154_SECURITY_ERROR_NONE;; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_REMOVE); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_REMOVE, + SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_REMOVE, + NRF_802154_SECURITY_KEY_REMOVE_ENCODE(*p_id, KEY_ID_MODE_3_SIZE)); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = net_generic_uint8_response_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, &err); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return err; +} + +void nrf_802154_csl_writer_period_set(uint16_t period) +{ + nrf_802154_ser_err_t res; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request(SPINEL_PROP_LAST_STATUS); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSL_WRITER_PERIOD_SET, + SPINEL_DATATYPE_NRF_802154_CSL_WRITER_PERIOD_SET, + period); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = status_ok_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); + + return; +} + +static nrf_802154_ser_err_t stat_timestamps_get_ret_await(uint32_t timeout, + nrf_802154_stat_timestamps_t * p_stat_timestamps) +{ + nrf_802154_ser_err_t res; + nrf_802154_spinel_notify_buff_t * p_notify_data = NULL; + + SERIALIZATION_ERROR_INIT(error); + + p_notify_data = nrf_802154_spinel_response_notifier_property_await( + timeout); + + SERIALIZATION_ERROR_IF(p_notify_data == NULL, + NRF_802154_SERIALIZATION_ERROR_RESPONSE_TIMEOUT, + error, + bail); + + res = nrf_802154_spinel_decode_prop_nrf_802154_stat_timestamps_get_ret( + p_notify_data->data, + p_notify_data->data_len, + p_stat_timestamps); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + NRF_802154_SPINEL_LOG_BANNER_RESPONSE(); + +bail: + if (p_notify_data != NULL) + { + nrf_802154_spinel_response_notifier_free(p_notify_data); + } + + return error; +} + +void nrf_802154_stat_timestamps_get(nrf_802154_stat_timestamps_t * p_stat_timestamps) +{ + nrf_802154_ser_err_t res; + + SERIALIZATION_ERROR_INIT(error); + + NRF_802154_SPINEL_LOG_BANNER_CALLING(); + + nrf_802154_spinel_response_notifier_lock_before_request( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_STAT_TIMESTAMPS_GET); + + res = nrf_802154_spinel_send_cmd_prop_value_set( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_STAT_TIMESTAMPS_GET, + SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_GET, + NULL); + + SERIALIZATION_ERROR_CHECK(res, error, bail); + + res = stat_timestamps_get_ret_await(CONFIG_NRF_802154_SER_DEFAULT_RESPONSE_TIMEOUT, + p_stat_timestamps); + SERIALIZATION_ERROR_CHECK(res, error, bail); + +bail: + SERIALIZATION_ERROR_RAISE_IF_FAILED(error); +} diff --git a/drivers/nrf_802154/serialization/src/nrf_802154_spinel_dec_app.c b/drivers/nrf_802154/serialization/src/nrf_802154_spinel_dec_app.c index 33a7049..70c7ef9 100644 --- a/drivers/nrf_802154/serialization/src/nrf_802154_spinel_dec_app.c +++ b/drivers/nrf_802154/serialization/src/nrf_802154_spinel_dec_app.c @@ -34,6 +34,7 @@ #include #include +#include #ifndef TEST #include @@ -50,6 +51,8 @@ #include "nrf_802154_buffer_mgr_src.h" #include "nrf_802154.h" +#include "nrf_802154_config.h" +#include "nrf_802154_const.h" /** * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_DONE. @@ -283,17 +286,21 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmitted_raw( uint32_t remote_ack_handle; void * p_ack; size_t ack_hdata_len; - void * p_frame; + size_t frame_hdata_len; + void * p_local_frame; + void * p_serialized_frame; void * p_ack_local_ptr = NULL; nrf_802154_transmit_done_metadata_t metadata = {0}; spinel_ssize_t siz = spinel_datatype_unpack(p_property_data, property_data_len, SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW, - &frame_handle, - NRF_802154_TRANSMIT_DONE_METADATA_DECODE(metadata, - remote_ack_handle, - ack_hdata_len)); + NRF_802154_TRANSMITTED_RAW_DECODE(frame_handle, + p_serialized_frame, + frame_hdata_len, + metadata, + remote_ack_handle, + ack_hdata_len)); p_ack = metadata.data.transmitted.p_ack; @@ -306,7 +313,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmitted_raw( bool frame_found = nrf_802154_buffer_mgr_src_search_by_buffer_handle( nrf_802154_spinel_src_buffer_mgr_get(), frame_handle, - &p_frame); + &p_local_frame); if (!frame_found) { @@ -346,9 +353,13 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmitted_raw( return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER; } + memcpy(p_local_frame, + p_serialized_frame, + NRF_802154_DATA_LEN_FROM_HDATA_LEN(frame_hdata_len)); + // Overwrite ACK frame pointer with a newly allocated one. metadata.data.transmitted.p_ack = p_ack_local_ptr; - nrf_802154_transmitted_raw(p_frame, &metadata); + nrf_802154_transmitted_raw(p_local_frame, &metadata); return NRF_802154_SERIALIZATION_ERROR_OK; } @@ -365,16 +376,19 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_failed( { uint32_t frame_handle; nrf_802154_tx_error_t tx_error; - void * p_frame; + void * p_serialized_frame; + void * p_local_frame; + size_t frame_hdata_len; nrf_802154_transmit_done_metadata_t metadata = {0}; spinel_ssize_t siz = spinel_datatype_unpack(p_property_data, property_data_len, SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED, - &frame_handle, - &tx_error, - NRF_802154_TRANSMITTED_FRAME_PROPS_DECODE(metadata. - frame_props)); + NRF_802154_TRANSMIT_FAILED_DECODE(frame_handle, + p_serialized_frame, + frame_hdata_len, + tx_error, + metadata)); if (siz < 0) { @@ -385,7 +399,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_failed( bool frame_found = nrf_802154_buffer_mgr_src_search_by_buffer_handle( nrf_802154_spinel_src_buffer_mgr_get(), frame_handle, - &p_frame); + &p_local_frame); if (!frame_found) { @@ -403,7 +417,11 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_failed( return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER; } - nrf_802154_transmit_failed(p_frame, tx_error, &metadata); + memcpy(p_local_frame, + p_serialized_frame, + NRF_802154_DATA_LEN_FROM_HDATA_LEN(frame_hdata_len)); + + nrf_802154_transmit_failed(p_local_frame, tx_error, &metadata); return NRF_802154_SERIALIZATION_ERROR_OK; } @@ -436,6 +454,20 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_generic_bool( NRF_802154_SERIALIZATION_ERROR_OK); } +nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_generic_uint8( + const void * p_property_data, + size_t property_data_len, + uint8_t * p_uint8_response) +{ + spinel_ssize_t siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_UINT8_S, + p_uint8_response); + + return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE : + NRF_802154_SERIALIZATION_ERROR_OK); +} + nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_tx_power_get_ret( const void * p_property_data, size_t property_data_len, @@ -450,19 +482,6 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_tx_power_get_ret( NRF_802154_SERIALIZATION_ERROR_OK); } -nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_channel(const void * p_property_data, - size_t property_data_len, - uint8_t * p_channel) -{ - spinel_ssize_t siz = spinel_datatype_unpack(p_property_data, - property_data_len, - SPINEL_DATATYPE_NRF_802154_CHANNEL_GET_RET, - p_channel); - - return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE : - NRF_802154_SERIALIZATION_ERROR_OK); -} - nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_capabilities_get_ret( const void * p_property_data, size_t property_data_len, @@ -491,6 +510,35 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_time_get_ret( NRF_802154_SERIALIZATION_ERROR_OK); } +nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_cca_cfg_get_ret( + const void * p_property_data, + size_t property_data_len, + nrf_802154_cca_cfg_t * p_cfg) +{ + spinel_ssize_t siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_CCA_CFG_GET_RET, + NRF_802154_CCA_CFG_DECODE(*p_cfg)); + + return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE : + NRF_802154_SERIALIZATION_ERROR_OK); +} + +nrf_802154_ser_err_t nrf_802154_spinel_decode_prop_nrf_802154_stat_timestamps_get_ret( + const void * p_property_data, + size_t property_data_len, + nrf_802154_stat_timestamps_t * p_stat_timestamps) +{ + spinel_ssize_t siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_GET_RET, + NRF_802154_STAT_TIMESTAMPS_DECODE( + *p_stat_timestamps)); + + return ((siz) < 0 ? NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE : + NRF_802154_SERIALIZATION_ERROR_OK); +} + nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_is( const void * p_cmd_data, size_t cmd_data_len) @@ -520,8 +568,18 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_is( // fall through case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE: // fall through - case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA: + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT: // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT_CANCEL: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA: + // fall through +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CONTINUOUS_CARRIER: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_MODULATED_CARRIER: + // fall through +#endif case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ENERGY_DETECTION: // fall through case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TX_POWER_GET: @@ -532,6 +590,12 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_is( // fall through case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TIME_GET: // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_GET: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_STORE: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_REMOVE: + // fall through case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PENDING_BIT_FOR_ADDR_SET: // fall through case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PENDING_BIT_FOR_ADDR_CLEAR: @@ -542,7 +606,27 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_is( // fall through case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW: // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW_AT: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_AT_CANCEL: + // fall through +#if NRF_802154_CSMA_CA_ENABLED case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_CSMA_CA_RAW: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_SET: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_GET: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_SET: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_GET: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_SET: + // fall through + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET: + // fall through +#endif // NRF_802154_CSMA_CA_ENABLED + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_STAT_TIMESTAMPS_GET: nrf_802154_spinel_response_notifier_property_notify(property, p_property_data, property_data_len); diff --git a/drivers/nrf_802154/serialization/src/nrf_802154_spinel_dec_net.c b/drivers/nrf_802154/serialization/src/nrf_802154_spinel_dec_net.c index 7154fdb..b0213ec 100644 --- a/drivers/nrf_802154/serialization/src/nrf_802154_spinel_dec_net.c +++ b/drivers/nrf_802154/serialization/src/nrf_802154_spinel_dec_net.c @@ -48,6 +48,9 @@ #include "nrf_802154_buffer_mgr_src.h" #include "nrf_802154.h" +#include "nrf_802154_config.h" + +static uint8_t * mp_transmit_at_frame; ///< Pointer to the frame that was requested to delay-transmit /** * @brief Deal with SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SLEEP request and send response. @@ -93,16 +96,90 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_receive(const void * p receive_response); } +/** + * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_receive_at( + const void * p_property_data, + size_t property_data_len) +{ + uint32_t t0; + uint32_t dt; + uint32_t timeout; + uint8_t channel; + uint32_t id; + spinel_ssize_t siz; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_RECEIVE_AT, + &t0, + &dt, + &timeout, + &channel, + &id); + + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + bool result = nrf_802154_receive_at(t0, dt, timeout, channel, id); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT, + SPINEL_DATATYPE_NRF_802154_RECEIVE_AT_RET, + result); +} + +/** + * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT_CANCEL. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_receive_at_cancel( + const void * p_property_data, + size_t property_data_len) +{ + uint32_t id; + spinel_ssize_t siz; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_RECEIVE_AT_CANCEL, + &id); + + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + bool result = nrf_802154_receive_at_cancel(id); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT_CANCEL, + SPINEL_DATATYPE_NRF_802154_RECEIVE_AT_CANCEL_RET, + result); +} + static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_channel_get(const void * p_property_data, size_t property_data_len) { (void)p_property_data; (void)property_data_len; + uint8_t channel = nrf_802154_channel_get(); + return nrf_802154_spinel_send_cmd_prop_value_is( SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CHANNEL_GET, SPINEL_DATATYPE_NRF_802154_CHANNEL_GET_RET, - nrf_802154_channel_get()); + channel); } static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_channel_set(const void * p_property_data, @@ -130,7 +207,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_channel_set(const void * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_PAN_ID_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pan_id_set( @@ -166,7 +243,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pan_id_set( * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SHORT_ADDRESS_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_short_address_set( @@ -202,7 +279,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_short_address_set( * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_EXTENDED_ADDRESS_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_extended_address_set( @@ -238,7 +315,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_extended_address_set( * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PAN_COORD_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pan_coord_set( @@ -267,7 +344,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pan_coord_set( * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PROMISCUOUS_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_promiscuous_set( @@ -296,7 +373,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_promiscuous_set( * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_cca(const void * p_property_data, @@ -312,11 +389,76 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_cca(const void * p_pro result); } +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + +/** + * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CONTINUOUS_CARRIER. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_continuous_carrier( + const void * p_property_data, + size_t property_data_len) +{ + (void)p_property_data; + (void)property_data_len; + + bool result = nrf_802154_continuous_carrier(); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CONTINUOUS_CARRIER, + SPINEL_DATATYPE_NRF_802154_CONTINUOUS_CARRIER_RET, + result); +} + +/** + * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_MODULATED_CARRIER. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_modulated_carrier( + const void * p_property_data, + size_t property_data_len) +{ + const void * p_buffer; + size_t p_buffer_len; + + spinel_ssize_t siz = spinel_datatype_unpack( + p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_MODULATED_CARRIER, + &p_buffer, + &p_buffer_len); + + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + if (p_buffer_len != RAW_PAYLOAD_OFFSET + ((uint8_t *)p_buffer)[0]) + { + return NRF_802154_SERIALIZATION_ERROR_REQUEST_INVALID; + } + + bool result = nrf_802154_modulated_carrier(p_buffer); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_MODULATED_CARRIER, + SPINEL_DATATYPE_NRF_802154_MODULATED_CARRIER_RET, + result); +} + +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + /** * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ENERGY_DETECTION. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_energy_detection( @@ -348,7 +490,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_energy_detection( * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_AUTO_PENDING_BIT_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_auto_pending_bit_set( const void * p_property_data, @@ -376,7 +518,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_auto_pending_bit_set( * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PENDING_BIT_FOR_ADDR_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pending_bit_for_addr_set( const void * p_property_data, @@ -424,7 +566,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pending_bit_for_addr_s * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PENDING_BIT_FOR_ADDR_CLEAR. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pending_bit_for_addr_clear( @@ -473,7 +615,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pending_bit_for_addr_c * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_PENDING_BIT_FOR_ADDR_RESET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pending_bit_for_addr_reset( @@ -502,7 +644,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_pending_bit_for_addr_r * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SRC_ADDR_MATCHING_METHOD_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_src_addr_matching_method_set( @@ -543,7 +685,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_src_addr_matching_meth * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ACK_DATA_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_ack_data_set( @@ -602,7 +744,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_ack_data_set( * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ACK_DATA_CLEAR. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_ack_data_clear( @@ -648,11 +790,13 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_ack_data_clear( ack_data_clear_res); } +#if NRF_802154_CSMA_CA_ENABLED + /** * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_TRANSMIT_CSMA_CA_RAW. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_csma_ca_raw( @@ -705,11 +849,174 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_csma_ca_raw( result); } +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_SET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_csma_ca_min_be_set( + const void * p_property_data, + size_t property_data_len) +{ + uint8_t min_be; + spinel_ssize_t siz; + bool result; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_CHANNEL_SET, + &min_be); + + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + result = nrf_802154_csma_ca_min_be_set(min_be); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_SET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_SET_RET, + result); +} + +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_GET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_csma_ca_min_be_get( + const void * p_property_data, + size_t property_data_len) +{ + (void)p_property_data; + (void)property_data_len; + + uint8_t min_be = nrf_802154_csma_ca_min_be_get(); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_GET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MIN_BE_GET_RET, + min_be); +} + +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_SET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_csma_ca_max_be_set( + const void * p_property_data, + size_t property_data_len) +{ + uint8_t max_be; + spinel_ssize_t siz; + bool result; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_CHANNEL_SET, + &max_be); + + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + result = nrf_802154_csma_ca_max_be_set(max_be); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_SET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_SET_RET, + result); +} + +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_GET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_csma_ca_max_be_get( + const void * p_property_data, + size_t property_data_len) +{ + (void)p_property_data; + (void)property_data_len; + + uint8_t max_be = nrf_802154_csma_ca_max_be_get(); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_GET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BE_GET_RET, + max_be); +} + +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BACKOFFS_SET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_csma_ca_max_backoffs_set( + const void * p_property_data, + size_t property_data_len) +{ + uint8_t max_backoffs; + spinel_ssize_t siz; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_CHANNEL_SET, + &max_backoffs); + + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + nrf_802154_csma_ca_max_backoffs_set(max_backoffs); + + return nrf_802154_spinel_send_prop_last_status_is(SPINEL_STATUS_OK); +} + +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to backoffs decoded. + * @param[in] property_data_len Size of the @ref p_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_csma_ca_max_backoffs_get( + const void * p_property_data, + size_t property_data_len) +{ + (void)p_property_data; + (void)property_data_len; + + uint8_t max_backoffs = nrf_802154_csma_ca_max_backoffs_get(); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET, + SPINEL_DATATYPE_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET_RET, + max_backoffs); +} + +#endif // NRF_802154_CSMA_CA_ENABLED + /** * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_raw( @@ -761,11 +1068,118 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_raw( result); } +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW_AT. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_raw_at( + const void * p_property_data, + size_t property_data_len) +{ + uint32_t remote_frame_handle; + const void * p_frame; + size_t frame_hdata_len; + void * p_local_frame_ptr; + nrf_802154_transmit_at_metadata_t tx_metadata; + uint32_t t0; + uint32_t dt; + + spinel_ssize_t siz = spinel_datatype_unpack( + p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW_AT, + NRF_802154_TRANSMIT_AT_METADATA_DECODE(tx_metadata), + &t0, + &dt, + NRF_802154_HDATA_DECODE(remote_frame_handle, p_frame, frame_hdata_len)); + + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + // Map the remote handle to locally accessible pointer and copy the buffer content there + bool frame_added = nrf_802154_buffer_mgr_dst_add( + nrf_802154_spinel_dst_buffer_mgr_get(), + remote_frame_handle, + p_frame, + NRF_802154_DATA_LEN_FROM_HDATA_LEN(frame_hdata_len), + &p_local_frame_ptr); + + if (!frame_added) + { + return NRF_802154_SERIALIZATION_ERROR_NO_MEMORY; + } + + bool result = nrf_802154_transmit_raw_at(p_local_frame_ptr, t0, dt, &tx_metadata); + + if (!result) + { + nrf_802154_buffer_mgr_dst_remove_by_local_pointer(nrf_802154_spinel_dst_buffer_mgr_get(), + p_local_frame_ptr); + } + else + { + // Latch the local pointer in case the transmission is cancelled + mp_transmit_at_frame = p_local_frame_ptr; + } + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW_AT, + SPINEL_DATATYPE_NRF_802154_TRANSMIT_RAW_AT_RET, + result); +} + +/** + * @brief Decode and dispatch SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_AT_CANCEL. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_transmit_at_cancel( + const void * p_property_data, + size_t property_data_len) +{ + (void)p_property_data; + (void)property_data_len; + + bool result = nrf_802154_transmit_at_cancel(); + + if (result) + { + // The transmission was cancelled successfully + if (!mp_transmit_at_frame) + { + // This should never happen + return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER; + } + + // Free the local frame pointer + bool removed = nrf_802154_buffer_mgr_dst_remove_by_local_pointer( + nrf_802154_spinel_dst_buffer_mgr_get(), + mp_transmit_at_frame); + + if (!removed) + { + return NRF_802154_SERIALIZATION_ERROR_INVALID_BUFFER; + } + } + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_AT_CANCEL, + SPINEL_DATATYPE_NRF_802154_TRANSMIT_AT_CANCEL_RET, + result); +} + /** * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_BUFFER_FREE_RAW. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_buffer_free_raw( @@ -814,7 +1228,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_buffer_free_raw( * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_TX_POWER_SET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_tx_power_set(const void * p_property_data, @@ -841,7 +1255,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_tx_power_set(const voi * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_TX_POWER_GET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_tx_power_get(const void * p_property_data, @@ -864,7 +1278,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_tx_power_get(const voi * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_CAPABILITIES_GET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_capabilities_get( @@ -888,7 +1302,7 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_capabilities_get( * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_TIME_GET. * * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. - * @param[in] property_data_len Size of the @ref p_data buffer. + * @param[in] property_data_len Size of the @ref p_property_data buffer. * */ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_time_get( @@ -908,6 +1322,188 @@ static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_time_get( time); } +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_cca_cfg_get(const void * p_property_data, + size_t property_data_len) +{ + (void)p_property_data; + (void)property_data_len; + + nrf_802154_cca_cfg_t cfg; + + nrf_802154_cca_cfg_get(&cfg); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_GET, + SPINEL_DATATYPE_NRF_802154_CCA_CFG_GET_RET, + NRF_802154_CCA_CFG_ENCODE(cfg)); +} + +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_stat_timestamps_get( + const void * p_property_data, + size_t property_data_len) +{ + (void)p_property_data; + (void)property_data_len; + + nrf_802154_stat_timestamps_t t; + + nrf_802154_stat_timestamps_get(&t); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_STAT_TIMESTAMPS_GET, + SPINEL_DATATYPE_NRF_802154_STAT_TIMESTAMPS_GET_RET, + NRF_802154_STAT_TIMESTAMPS_ENCODE(t)); +} + +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802514_cca_cfg_set(const void * p_property_data, + size_t property_data_len) +{ + nrf_802154_cca_cfg_t cfg; + spinel_ssize_t siz; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_CCA_CFG_SET, + NRF_802154_CCA_CFG_DECODE(cfg)); + + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + nrf_802154_cca_cfg_set(&cfg); + + return nrf_802154_spinel_send_prop_last_status_is(SPINEL_STATUS_OK); +} + +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_security_global_frame_counter_set( + const void * p_property_data, + size_t property_data_len) +{ + spinel_ssize_t siz; + uint32_t frame_counter; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET, + &frame_counter); + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + nrf_802154_security_global_frame_counter_set(frame_counter); + + return nrf_802154_spinel_send_prop_last_status_is(SPINEL_STATUS_OK); +} + +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_STORE. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_security_key_store( + const void * p_property_data, + size_t property_data_len) +{ + spinel_ssize_t siz; + nrf_802154_key_t key = {0}; + uint32_t key_size; + uint32_t key_id_size; + nrf_802154_security_error_t err; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_STORE, + NRF_802154_SECURITY_KEY_STORE_DECODE(key, key_size, key_id_size)); + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + err = nrf_802154_security_key_store(&key); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_STORE, + SPINEL_DATATYPE_NRF_802154_SECURITY_ERROR_RET, + err); +} + +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_REMOVE. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_security_key_remove( + const void * p_property_data, + size_t property_data_len) +{ + spinel_ssize_t siz; + uint8_t key_id_data[KEY_ID_MODE_3_SIZE]; + nrf_802154_key_id_t key_id = {.p_key_id = key_id_data}; + uint32_t key_id_size; + nrf_802154_security_error_t err; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_SECURITY_KEY_REMOVE, + NRF_802154_SECURITY_KEY_REMOVE_DECODE(key_id, key_id_size)); + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + err = nrf_802154_security_key_remove(&key_id); + + return nrf_802154_spinel_send_cmd_prop_value_is( + SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_REMOVE, + SPINEL_DATATYPE_NRF_802154_SECURITY_ERROR_RET, + err); +} + +#if NRF_802154_DELAYED_TRX_ENABLED && NRF_802154_IE_WRITER_ENABLED + +/** + * @brief Decode and dispatch SPINEL_DATATYPE_NRF_802154_CSL_WRITER_PERIOD_SET. + * + * @param[in] p_property_data Pointer to a buffer that contains data to be decoded. + * @param[in] property_data_len Size of the @ref p_property_data buffer. + * + */ +static nrf_802154_ser_err_t spinel_decode_prop_nrf_802154_csl_writer_period_set( + const void * p_property_data, + size_t property_data_len) +{ + spinel_ssize_t siz; + uint16_t csl_period; + + siz = spinel_datatype_unpack(p_property_data, + property_data_len, + SPINEL_DATATYPE_NRF_802154_CSL_WRITER_PERIOD_SET, + &csl_period); + if (siz < 0) + { + return NRF_802154_SERIALIZATION_ERROR_DECODING_FAILURE; + } + + nrf_802154_csl_writer_period_set(csl_period); + + return nrf_802154_spinel_send_prop_last_status_is(SPINEL_STATUS_OK); +} + +#endif // NRF_802154_DELAYED_TRX_ENABLED && NRF_802154_IE_WRITER_ENABLED + nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_cmd_data, size_t cmd_data_len) { @@ -936,6 +1532,13 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_ case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE: return spinel_decode_prop_nrf_802154_receive(p_property_data, property_data_len); + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT: + return spinel_decode_prop_nrf_802154_receive_at(p_property_data, property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_RECEIVE_AT_CANCEL: + return spinel_decode_prop_nrf_802154_receive_at_cancel(p_property_data, + property_data_len); + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CHANNEL_GET: return spinel_decode_prop_nrf_802514_channel_get(p_property_data, property_data_len); @@ -983,6 +1586,18 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_ case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA: return spinel_decode_prop_nrf_802154_cca(p_property_data, property_data_len); +#if NRF_802154_CARRIER_FUNCTIONS_ENABLED + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CONTINUOUS_CARRIER: + return spinel_decode_prop_nrf_802154_continuous_carrier(p_property_data, + property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_MODULATED_CARRIER: + return spinel_decode_prop_nrf_802154_modulated_carrier(p_property_data, + property_data_len); + +#endif // NRF_802154_CARRIER_FUNCTIONS_ENABLED + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ENERGY_DETECTION: return spinel_decode_prop_nrf_802154_energy_detection(p_property_data, property_data_len); @@ -993,13 +1608,47 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_ case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TX_POWER_GET: return spinel_decode_prop_nrf_802154_tx_power_get(p_property_data, property_data_len); +#if NRF_802154_CSMA_CA_ENABLED case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_CSMA_CA_RAW: return spinel_decode_prop_nrf_802154_transmit_csma_ca_raw(p_property_data, property_data_len); + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_SET: + return spinel_decode_prop_nrf_802514_csma_ca_min_be_set(p_property_data, + property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MIN_BE_GET: + return spinel_decode_prop_nrf_802514_csma_ca_min_be_get(p_property_data, + property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_SET: + return spinel_decode_prop_nrf_802514_csma_ca_max_be_set(p_property_data, + property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BE_GET: + return spinel_decode_prop_nrf_802514_csma_ca_max_be_get(p_property_data, + property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_SET: + return spinel_decode_prop_nrf_802514_csma_ca_max_backoffs_set(p_property_data, + property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSMA_CA_MAX_BACKOFFS_GET: + return spinel_decode_prop_nrf_802514_csma_ca_max_backoffs_get(p_property_data, + property_data_len); +#endif // NRF_802154_CSMA_CA_ENABLED + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW: return spinel_decode_prop_nrf_802154_transmit_raw(p_property_data, property_data_len); + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_RAW_AT: + return spinel_decode_prop_nrf_802154_transmit_raw_at(p_property_data, + property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_AT_CANCEL: + return spinel_decode_prop_nrf_802154_transmit_at_cancel(p_property_data, + property_data_len); + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_BUFFER_FREE_RAW: return spinel_decode_prop_nrf_802154_buffer_free_raw(p_property_data, property_data_len); @@ -1012,6 +1661,12 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_ return spinel_decode_prop_nrf_802154_time_get(p_property_data, property_data_len); + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_GET: + return spinel_decode_prop_nrf_802514_cca_cfg_get(p_property_data, property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CCA_CFG_SET: + return spinel_decode_prop_nrf_802514_cca_cfg_set(p_property_data, property_data_len); + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_ACK_DATA_SET: return spinel_decode_prop_nrf_802154_ack_data_set(p_property_data, property_data_len); @@ -1020,6 +1675,28 @@ nrf_802154_ser_err_t nrf_802154_spinel_decode_cmd_prop_value_set(const void * p_ return spinel_decode_prop_nrf_802154_ack_data_clear(p_property_data, property_data_len); + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_GLOBAL_FRAME_COUNTER_SET: + return spinel_decode_prop_nrf_802154_security_global_frame_counter_set(p_property_data, + property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_STORE: + return spinel_decode_prop_nrf_802154_security_key_store(p_property_data, + property_data_len); + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_SECURITY_KEY_REMOVE: + return spinel_decode_prop_nrf_802154_security_key_remove(p_property_data, + property_data_len); + +#if NRF_802154_DELAYED_TRX_ENABLED && NRF_802154_IE_WRITER_ENABLED + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_CSL_WRITER_PERIOD_SET: + return spinel_decode_prop_nrf_802154_csl_writer_period_set(p_property_data, + property_data_len); +#endif // NRF_802154_DELAYED_TRX_ENABLED && NRF_802154_IE_WRITER_ENABLED + + case SPINEL_PROP_VENDOR_NORDIC_NRF_802154_STAT_TIMESTAMPS_GET: + return spinel_decode_prop_nrf_802514_stat_timestamps_get(p_property_data, + property_data_len); + default: NRF_802154_SPINEL_LOG_RAW("Unsupported property: %s(%u)\n", spinel_prop_key_to_cstr(property), diff --git a/drivers/nrf_802154/serialization/src/nrf_802154_spinel_net.c b/drivers/nrf_802154/serialization/src/nrf_802154_spinel_net.c index e27f324..2145421 100644 --- a/drivers/nrf_802154/serialization/src/nrf_802154_spinel_net.c +++ b/drivers/nrf_802154/serialization/src/nrf_802154_spinel_net.c @@ -283,15 +283,8 @@ void nrf_802154_transmitted_raw(uint8_t * p_fr { uint32_t remote_frame_handle; uint32_t ack_handle = 0; - uint32_t ack_len = 0; uint8_t * p_ack = p_metadata->data.transmitted.p_ack; - /* Forcefully overwrite frame's properties due to KRKNWK-10114 not being implemented. - * This overwrite makes state of the frame consistent with its properties. - */ - ((nrf_802154_transmit_done_metadata_t *)p_metadata)->frame_props = - NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT; - SERIALIZATION_ERROR_INIT(error); NRF_802154_SPINEL_LOG_BANNER_CALLING(); @@ -323,16 +316,13 @@ void nrf_802154_transmitted_raw(uint8_t * p_fr local_transmitted_frame_ptr_free((void *)p_frame); SERIALIZATION_ERROR(NRF_802154_SERIALIZATION_ERROR_NO_MEMORY, error, bail); } - - ack_len = p_ack[0]; } // Serialize the call nrf_802154_ser_err_t res = nrf_802154_spinel_send_cmd_prop_value_is( SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMITTED_RAW, SPINEL_DATATYPE_NRF_802154_TRANSMITTED_RAW, - remote_frame_handle, - NRF_802154_TRANSMIT_DONE_METADATA_ENCODE(*p_metadata, ack_handle)); + NRF_802154_TRANSMITTED_RAW_ENCODE(remote_frame_handle, p_frame, *p_metadata, ack_handle)); // Free the local frame pointer no matter the result of serialization local_transmitted_frame_ptr_free((void *)p_frame); @@ -357,12 +347,6 @@ void nrf_802154_transmit_failed(uint8_t * p_fr NRF_802154_SPINEL_LOG_BANNER_CALLING(); NRF_802154_SPINEL_LOG_BUFF(p_frame, p_frame[0]); - /* Forcefully overwrite frame's properties due to KRKNWK-10114 not being implemented. - * This overwrite makes state of the frame consistent with its properties. - */ - ((nrf_802154_transmit_done_metadata_t *)p_metadata)->frame_props = - NRF_802154_TRANSMITTED_FRAME_PROPS_DEFAULT_INIT; - // Search for the handle to the original frame buffer based on the local pointer bool frame_found = nrf_802154_buffer_mgr_dst_search_by_local_pointer( nrf_802154_spinel_dst_buffer_mgr_get(), @@ -379,9 +363,7 @@ void nrf_802154_transmit_failed(uint8_t * p_fr nrf_802154_ser_err_t res = nrf_802154_spinel_send_cmd_prop_value_is( SPINEL_PROP_VENDOR_NORDIC_NRF_802154_TRANSMIT_FAILED, SPINEL_DATATYPE_NRF_802154_TRANSMIT_FAILED, - remote_frame_handle, - tx_error, - NRF_802154_TRANSMITTED_FRAME_PROPS_ENCODE(p_metadata->frame_props)); + NRF_802154_TRANSMIT_FAILED_ENCODE(remote_frame_handle, p_frame, tx_error, *p_metadata)); // Free the local frame pointer no matter the result of serialization local_transmitted_frame_ptr_free((void *)p_frame); diff --git a/drivers/nrf_802154/sl/include/nrf_802154_sl_ant_div.h b/drivers/nrf_802154/sl/include/nrf_802154_sl_ant_div.h index 67638b8..35b4068 100644 --- a/drivers/nrf_802154/sl/include/nrf_802154_sl_ant_div.h +++ b/drivers/nrf_802154/sl/include/nrf_802154_sl_ant_div.h @@ -341,7 +341,7 @@ void nrf_802154_sl_ant_div_rx_preamble_detected_notify(void); bool nrf_802154_sl_ant_div_rx_frame_started_notify(void); /** - * @brief Notification to be called when frame is received successfuly. + * @brief Notification to be called when frame is received successfully. */ void nrf_802154_sl_ant_div_rx_frame_received_notify(void); diff --git a/drivers/nrf_802154/sl/include/nrf_802154_sl_crit_sect_if.h b/drivers/nrf_802154/sl/include/nrf_802154_sl_crit_sect_if.h new file mode 100644 index 0000000..977f02c --- /dev/null +++ b/drivers/nrf_802154/sl/include/nrf_802154_sl_crit_sect_if.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#ifndef NRF_802154_SL_CRIT_SECT_IF_H__ +#define NRF_802154_SL_CRIT_SECT_IF_H__ + +#include + +/** + * @defgroup nrf_802154_sl_crit_sect_if Interface of the critical section. + * @{ + */ + +/** + * @brief Pointer to function used to enter critical section. + */ +typedef bool (* nrf_802154_sl_crit_sect_enter_t)(void); + +/** + * @brief Pointer to function used to exit critical section. + */ +typedef void (* nrf_802154_sl_crit_sect_exit_t)(void); + +/** + * @brief Structure that holds interface of Radio Driver critical sections. + */ +typedef struct +{ + nrf_802154_sl_crit_sect_enter_t enter; + nrf_802154_sl_crit_sect_exit_t exit; +} nrf_802154_sl_crit_sect_interface_t; + +/** + * @brief Initializes the critical section interface. + * + * After the call SL library can use @ref nrf_802154_sl_crit_sect_enter and + * @ref nrf_802154_sl_crit_sect_exit to use critical section provided by the Radio Driver. + * + * @param[in] p_crit_sect_interface Pointer to a critical section interface of the Radio Driver. + * It must point to static data for lifetime of Radio Driver. + */ +void nrf_802154_sl_crit_sect_init( + const nrf_802154_sl_crit_sect_interface_t * p_crit_sect_interface); + +/** + * @brief Enters into the critical section. + * + * @retval true Code entered into the critical section. + * @retval false Critical section was already taken, could not enter into critical section. + */ +static inline bool nrf_802154_sl_crit_sect_enter(void) +{ + extern const nrf_802154_sl_crit_sect_interface_t * gp_nrf_802154_sl_crit_sect_interface; + + return gp_nrf_802154_sl_crit_sect_interface->enter(); +} + +/** + * @brief Exits out of the critical section. + */ +static inline void nrf_802154_sl_crit_sect_exit(void) +{ + extern const nrf_802154_sl_crit_sect_interface_t * gp_nrf_802154_sl_crit_sect_interface; + + return gp_nrf_802154_sl_crit_sect_interface->exit(); +} + +/** + *@} + **/ + +#endif // NRF_802154_SL_CRIT_SECT_IF_H__ diff --git a/drivers/nrf_802154/sl/include/nrf_802154_sl_periphs.h b/drivers/nrf_802154/sl/include/nrf_802154_sl_periphs.h index 52339d8..0c7c22b 100644 --- a/drivers/nrf_802154/sl/include/nrf_802154_sl_periphs.h +++ b/drivers/nrf_802154/sl/include/nrf_802154_sl_periphs.h @@ -42,7 +42,38 @@ #include #include +#if defined(DPPI_PRESENT) +#include "hal/nrf_dppi.h" +#else #include "hal/nrf_ppi.h" +#endif + +/** + * @def NRF_802154_EGU_INSTANCE_NO + * + * Id of the EGU instance used by the driver to synchronize DPPIs and for requests and + * notifications if SWI is in use. + * + */ +#ifndef NRF_802154_EGU_INSTANCE_NO +#define NRF_802154_EGU_INSTANCE_NO 0 +#endif + +/** + * @def NRF_802154_EGU_INSTANCE + * + * The EGU instance used by the driver to synchronize PPIs and for requests and notifications if + * SWI is in use. + * + * @note This option is used by the core module regardless of the driver configuration. + * + */ +#define NRF_802154_EGU_INSTANCE NRFX_CONCAT_2(NRF_EGU, NRF_802154_EGU_INSTANCE_NO) + +/** + * @def NRF_802154_EGU_TIMESTAMP_CHANNEL + */ +#define NRF_802154_EGU_TIMESTAMP_CHANNEL 4 /** * @def NRF_802154_RTC_INSTANCE_NO @@ -122,8 +153,12 @@ * */ #ifndef NRF_802154_PPI_RTC_COMPARE_TO_TIMER_CAPTURE +#if defined(DPPI_PRESENT) +#define NRF_802154_PPI_RTC_COMPARE_TO_TIMER_CAPTURE 13U +#else #define NRF_802154_PPI_RTC_COMPARE_TO_TIMER_CAPTURE NRF_PPI_CHANNEL13 #endif +#endif /** * @def NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE @@ -135,8 +170,12 @@ * */ #ifndef NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE +#if defined(DPPI_PRESENT) +#define NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE 11U +#else #define NRF_802154_PPI_TIMESTAMP_EVENT_TO_TIMER_CAPTURE NRF_PPI_CHANNEL14 #endif +#endif /** * @def NRF_802154_TIMESTAMP_PPI_CHANNELS_USED_MASK @@ -157,7 +196,11 @@ * */ #ifndef NRF_802154_PPI_TIMESTAMP_GROUP +#if defined(DPPI_PRESENT) +#define NRF_802154_PPI_TIMESTAMP_GROUP NRF_DPPI_CHANNEL_GROUP1 +#else #define NRF_802154_PPI_TIMESTAMP_GROUP NRF_PPI_CHANNEL_GROUP2 #endif +#endif #endif // NRF_802154_SL_PERIPHS_H__ diff --git a/drivers/nrf_802154/sl/include/nrf_802154_sl_types.h b/drivers/nrf_802154/sl/include/nrf_802154_sl_types.h new file mode 100644 index 0000000..f4edd04 --- /dev/null +++ b/drivers/nrf_802154/sl/include/nrf_802154_sl_types.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020 - 2021, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +/** + * @file Common types provided by the nRF 802.15.4 Service Layer. + * + */ + +#ifndef NRF_802154_SL_TYPES_H__ +#define NRF_802154_SL_TYPES_H__ + +#include +#include +#include + +/** + * @brief Handle of a hardware event. + * + * This handle can be used to trigger peripheral tasks through hardware. + */ +typedef struct +{ + /** + * @brief Actual handle to use when configuring hardware. + * + * On nRF52 series, this field represents an address of a hardware event + * that can be written to a PPI register. + * + * On nRF53 series, this field depending on @c shared might either represent + * an address of a hardware event that should publish to a DPPI channel, + * or a number of a DPPI channel that the hardware event of interest + * is already publishing to. + */ + uint32_t event_addr; + +#if defined(DPPI_PRESENT) + /** + * @brief Indicates if the event is already publishing to a DPPI channel. + */ + bool shared; + +#endif +} nrf_802154_sl_event_handle_t; + +#endif // NRF_802154_SL_TYPES_H__ diff --git a/drivers/nrf_802154/sl/include/rsch/nrf_802154_rsch_crit_sect.h b/drivers/nrf_802154/sl/include/rsch/nrf_802154_rsch_crit_sect.h index f4475ba..a2e86e9 100644 --- a/drivers/nrf_802154/sl/include/rsch/nrf_802154_rsch_crit_sect.h +++ b/drivers/nrf_802154/sl/include/rsch/nrf_802154_rsch_crit_sect.h @@ -43,33 +43,12 @@ * @defgroup nrf_802154_rsch_crit_sect RSCH event queue used during critical sections * @{ * @ingroup nrf_802154_rsch - * @brief The critical section implementation for the RSCH module. */ -/** - * @brief Pointer to function used to enter critical section. - */ -typedef bool (* nrf_802154_sl_crit_sect_enter_t)(void); - -/** - * @brief Pointer to function used to exit critical section. - */ -typedef void (* nrf_802154_sl_crit_sect_exit_t)(void); - -/** - * @brief Structure that holds interface of Radio Scheduler critical sections. - */ -typedef struct -{ - nrf_802154_sl_crit_sect_enter_t enter; - nrf_802154_sl_crit_sect_exit_t exit; -} nrf_802154_sl_crit_sect_interface_t; - /** * @brief Initializes the RSCH critical section module. */ -void nrf_802154_rsch_crit_sect_init( - const nrf_802154_sl_crit_sect_interface_t * p_crit_sect_interface); +void nrf_802154_rsch_crit_sect_init(void); /** * @brief Requests the priority level from RSCH through the critical section module. diff --git a/drivers/nrf_802154/sl/include/timer/nrf_802154_timer_coord.h b/drivers/nrf_802154/sl/include/timer/nrf_802154_timer_coord.h index 82466b5..55f6a38 100644 --- a/drivers/nrf_802154/sl/include/timer/nrf_802154_timer_coord.h +++ b/drivers/nrf_802154/sl/include/timer/nrf_802154_timer_coord.h @@ -43,6 +43,8 @@ #include #include +#include "nrf_802154_sl_types.h" + #ifdef __cplusplus extern "C" { #endif @@ -89,10 +91,9 @@ void nrf_802154_timer_coord_stop(void); /** * @brief Prepares for getting a precise timestamp of the given event. * - * @param[in] event_addr Address of the peripheral register corresponding to the event that - * is to be time-stamped. + * @param[in] p_event Pointer to structure describing a hardware event to be timestamped. */ -void nrf_802154_timer_coord_timestamp_prepare(uint32_t event_addr); +void nrf_802154_timer_coord_timestamp_prepare(const nrf_802154_sl_event_handle_t * p_event); /** * @brief Gets the timestamp of the recently prepared event. diff --git a/drivers/nrf_802154/sl/sl_opensource/CMakeLists.txt b/drivers/nrf_802154/sl/sl_opensource/CMakeLists.txt index 77d28a9..3a4a8c9 100644 --- a/drivers/nrf_802154/sl/sl_opensource/CMakeLists.txt +++ b/drivers/nrf_802154/sl/sl_opensource/CMakeLists.txt @@ -47,6 +47,7 @@ target_sources(nrf-802154-sl src/nrf_802154_sl_ant_div.c src/nrf_802154_sl_capabilities.c src/nrf_802154_sl_coex.c + src/nrf_802154_sl_crit_sect_if.c src/nrf_802154_sl_fem.c src/nrf_802154_sl_log.c src/nrf_802154_sl_rsch.c diff --git a/drivers/nrf_802154/sl/sl_opensource/include/mpsl_fem_protocol_api.h b/drivers/nrf_802154/sl/sl_opensource/include/protocol/mpsl_fem_protocol_api.h similarity index 85% rename from drivers/nrf_802154/sl/sl_opensource/include/mpsl_fem_protocol_api.h rename to drivers/nrf_802154/sl/sl_opensource/include/protocol/mpsl_fem_protocol_api.h index d45338a..17a919b 100644 --- a/drivers/nrf_802154/sl/sl_opensource/include/mpsl_fem_protocol_api.h +++ b/drivers/nrf_802154/sl/sl_opensource/include/protocol/mpsl_fem_protocol_api.h @@ -41,6 +41,22 @@ typedef enum MPSL_FEM_EVENT_TYPE_GENERIC /**< Generic Event type. */ } mpsl_fem_event_type_t; +/** @brief Type representing a multiple-subscribable hardware event. + * + * For nRF52 series this is an address of an event within a peripheral. This + * event can be written to @c EEP register of a PPI channel, to make the + * PPI channel be driven by the event. For nRF52 series an event can be + * published to multiple PPI channels by hardware design, which makes it possible + * for multiple tasks to subscribe to it. + * + * For nRF53 series this is a number of a DPPI channel which is configured + * in such a way that certain event publishes to the DPPI channel and the + * DPPI channel is enabled. Ensuring above is responsibility of an user + * of the provided API. Multiple tasks can then subscribe to the DPPI channel + * (by hardware design) thus indirectly to the event. + */ +typedef uint32_t mpsl_subscribable_hw_event_t; + /** @brief MPSL Front End Module event. */ typedef struct { @@ -73,17 +89,36 @@ typedef struct /** Parameters when type is @ref MPSL_FEM_EVENT_TYPE_GENERIC. */ struct { - /** Address of event register. */ - uint32_t register_address; + /** Event triggerring required FEM operation. */ + mpsl_subscribable_hw_event_t event; /** Generic event, used in case of type equal to @ref mpsl_fem_event_type_t::MPSL_FEM_EVENT_TYPE_GENERIC. */ } generic; } event; + +#if defined(NRF52_SERIES) /** False to ignore the PPI channel below and use the one set by application. True to use the PPI channel below. */ bool override_ppi; /** PPI channel to be used for this event. */ uint8_t ppi_ch_id; +#endif } mpsl_fem_event_t; +/** @brief Disable Front End Module. + * + * Some Front End Module devices can be explicitly disabled after PA and LNA activities are + * finished to preserve power. + * + * This function is intended to disable Front End Module shortly after radio operations are + * finished and the protocol does not expect more radio activities in short future, or passes + * radio control to other protocols in the system. + * + * Front End Module disabling process is synchronous and immediate. + * + * @retval 0 + * @retval -NRF_EPERM FEM is configured to enable PA or LNA. + */ +int32_t mpsl_fem_disable(void); + /** @brief Sets up PA using the provided events for the upcoming radio transmission. * * Multiple configurations can be provided by repeating calls to this function @@ -209,18 +244,19 @@ void mpsl_fem_deactivate_now(mpsl_fem_functionality_t type); /** @brief Instruct Front End Module to disable PA and LNA as soon as possible * using the group following the event. * - * @param[in] event Address of the event which is triggered when the abort condition occurs. - * @param[in] group PPI Group which shall be disabled when the abort event is triggered. + * @param[in] event An event which is triggered when the abort condition occurs. + * (See doc for @ref mpsl_subscribable_hw_event_t type.) + * @param[in] group (D)PPI Group which shall be disabled when the abort event is triggered. * * @retval 0 Setting of the abort sequence path is successful. * @retval -NRF_EPERM Setting of the abort sequence path could not be performed. */ -int32_t mpsl_fem_abort_set(uint32_t event, uint32_t group); +int32_t mpsl_fem_abort_set(mpsl_subscribable_hw_event_t event, uint32_t group); /** @brief Adds one more PPI channel to the PPI Group prepared by the * @ref mpsl_fem_abort_set function. * - * @param[in] channel_to_add PPI channel to add to the PPI group. + * @param[in] channel_to_add (D)PPI channel to add to the (D)PPI group. * @param[in] group The said PPI group. * * @retval 0 Setting of the abort sequence path is successful. @@ -231,7 +267,7 @@ int32_t mpsl_fem_abort_extend(uint32_t channel_to_add, uint32_t group); /** @brief Removes one PPI channel from the PPI Group prepared by the * @ref mpsl_fem_abort_set function. * - * @param[in] channel_to_remove PPI channel to remove from the PPI group. + * @param[in] channel_to_remove (D)PPI channel to remove from the (D)PPI group. * @param[in] group The said PPI group. * * @retval 0 Setting of the abort sequence path is successful. @@ -266,6 +302,8 @@ void mpsl_fem_cleanup(void); void mpsl_fem_pa_is_configured(int8_t * const p_gain); /** @brief Prepares the Front End Module to switch to the Power Down state. + * + * @deprecated This function is deprecated. Use @ref mpsl_fem_disable instead. * * This function makes sure the Front End Module shall be switched off in the * appropriate time, using the hardware timer and its compare channel. diff --git a/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_crit_sect_if.c b/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_crit_sect_if.c new file mode 100644 index 0000000..bd750e4 --- /dev/null +++ b/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_crit_sect_if.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2017 - 2021, Nordic Semiconductor ASA + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of Nordic Semiconductor ASA nor the names of its + * contributors may be used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + */ + +#include "nrf_802154_sl_crit_sect_if.h" + +/**@brief Pointer to an interface of critical section. */ +const nrf_802154_sl_crit_sect_interface_t * gp_nrf_802154_sl_crit_sect_interface; + +void nrf_802154_sl_crit_sect_init( + const nrf_802154_sl_crit_sect_interface_t * p_crit_sect_interface) +{ + gp_nrf_802154_sl_crit_sect_interface = p_crit_sect_interface; +} diff --git a/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_fem.c b/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_fem.c index 3e4e5d4..8e6004e 100644 --- a/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_fem.c +++ b/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_fem.c @@ -37,12 +37,17 @@ #include #include -#include "mpsl_fem_protocol_api.h" +#include "protocol/mpsl_fem_protocol_api.h" #ifdef __cplusplus extern "C" { #endif +int32_t mpsl_fem_disable(void) +{ + return 0; +} + int32_t mpsl_fem_pa_configuration_set(const mpsl_fem_event_t * const p_activate_event, const mpsl_fem_event_t * const p_deactivate_event) { diff --git a/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_rsch.c b/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_rsch.c index b4b0371..a235254 100644 --- a/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_rsch.c +++ b/drivers/nrf_802154/sl/sl_opensource/src/nrf_802154_sl_rsch.c @@ -157,6 +157,11 @@ bool nrf_802154_critical_section_rsch_event_is_pending(void) return false; } +void nrf_802154_critical_section_rsch_process_pending(void) +{ + // Intentionally empty +} + bool nrf_802154_rsch_delayed_timeslot_request(const rsch_dly_ts_param_t * p_dly_ts_param) { (void)p_dly_ts_param;