Skip to content

Commit 4acb098

Browse files
ankunsrlubos
authored andcommitted
[nrf noup] drivers: ieee802154_nrf5: add timeout for tx and cca
The Kconfig option `CONFIG_IEEE802154_NRF5_CALLOUT_TIMEOUT_MS` is added. When this option is set to non-zero value (by default), the transmit and cca operations are expected to finish (with any result) within given timeout. Reaching the timeout is a fatal error. Signed-off-by: Andrzej Kuros <[email protected]>
1 parent 0933a4b commit 4acb098

File tree

2 files changed

+62
-7
lines changed

2 files changed

+62
-7
lines changed

drivers/ieee802154/Kconfig.nrf5

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,17 @@ config IEEE802154_NRF5_DELAY_TRX_ACC
7878
Accuracy of the clock used for scheduling radio delayed operations (delayed transmission
7979
or delayed reception), in ppm.
8080

81+
config IEEE802154_NRF5_CALLOUT_TIMEOUT_MS
82+
int "Timeout in milliseconds of waiting for a callout that finishes a requested operation"
83+
default 10000
84+
help
85+
This parameter limits the maximum time that can pass between
86+
a request to the nRF 802.15.4 Radio Driver to the corresponding asynchronous callout
87+
notifying the result of the operation. Reaching this timeout is a fatal error
88+
of the nRF 802.15.4 Radio Driver thus rather big values are advised.
89+
Set this value to 0 to have no limit (equivalent to K_FOREVER) which turns off the
90+
timing-out feature.
91+
8192
config IEEE802154_NRF5_LOG_RX_FAILURES
8293
bool "Frame reception failures logging"
8394
help

drivers/ieee802154/ieee802154_nrf5.c

Lines changed: 51 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,26 @@ static enum ieee802154_hw_caps nrf5_get_capabilities(const struct device *dev)
238238
return nrf5_data.capabilities;
239239
}
240240

241+
FUNC_NORETURN static void nrf5_callback_timeout(void)
242+
{
243+
/* Callback from the radio driver did not come in specified timeout */
244+
__ASSERT(false, "802.15.4 callback timeout");
245+
k_oops();
246+
CODE_UNREACHABLE;
247+
}
248+
249+
static void nrf5_callback_sem_take(struct k_sem *sem, uint32_t additional_ms)
250+
{
251+
if (CONFIG_IEEE802154_NRF5_CALLOUT_TIMEOUT_MS == 0) {
252+
k_sem_take(sem, K_FOREVER);
253+
} else {
254+
if (k_sem_take(sem,
255+
K_MSEC(additional_ms + CONFIG_IEEE802154_NRF5_CALLOUT_TIMEOUT_MS)) != 0) {
256+
nrf5_callback_timeout();
257+
}
258+
}
259+
}
260+
241261
static int nrf5_cca(const struct device *dev)
242262
{
243263
struct nrf5_802154_data *nrf5_radio = NRF5_802154_DATA(dev);
@@ -250,7 +270,7 @@ static int nrf5_cca(const struct device *dev)
250270
/* The nRF driver guarantees that a callback will be called once
251271
* the CCA function is done, thus unlocking the semaphore.
252272
*/
253-
k_sem_take(&nrf5_radio->cca_wait, K_FOREVER);
273+
nrf5_callback_sem_take(&nrf5_radio->cca_wait, 0);
254274

255275
LOG_DBG("Channel free? %d", nrf5_radio->channel_free);
256276

@@ -480,8 +500,10 @@ static bool nrf5_tx_csma_ca(struct net_pkt *pkt, uint8_t *payload)
480500
#if defined(CONFIG_NET_PKT_TXTIME)
481501
/**
482502
* @brief Convert 32-bit target time to absolute 64-bit target time.
503+
* @param[in] target_time 32-bit time to convert
504+
* @param[in] now_us Result of @ref nrf_802154_time_get
483505
*/
484-
static uint64_t target_time_convert_to_64_bits(uint32_t target_time)
506+
static uint64_t target_time_convert_to_64_bits_from_given(uint32_t target_time, uint64_t now_us)
485507
{
486508
/**
487509
* Target time is provided as two 32-bit integers defining a moment in time
@@ -495,7 +517,6 @@ static uint64_t target_time_convert_to_64_bits(uint32_t target_time)
495517
* time. Let's assume that half of the 32-bit range can be used for specifying
496518
* target times in the future, and the other half - in the past.
497519
*/
498-
uint64_t now_us = nrf_802154_time_get();
499520
uint32_t now_us_wrapped = (uint32_t)now_us;
500521
uint32_t time_diff = target_time - now_us_wrapped;
501522
uint64_t result = UINT64_C(0);
@@ -545,7 +566,18 @@ static uint64_t target_time_convert_to_64_bits(uint32_t target_time)
545566
return result;
546567
}
547568

548-
static bool nrf5_tx_at(struct net_pkt *pkt, uint8_t *payload, bool cca)
569+
570+
#if defined(CONFIG_IEEE802154_CSL_ENDPOINT)
571+
/**
572+
* @brief Convert 32-bit target time to absolute 64-bit target time.
573+
*/
574+
static uint64_t target_time_convert_to_64_bits(uint32_t target_time)
575+
{
576+
return target_time_convert_to_64_bits_from_given(target_time, nrf_802154_time_get());
577+
}
578+
#endif
579+
580+
static bool nrf5_tx_at(struct net_pkt *pkt, uint8_t *payload, bool cca, uint32_t *time_ahead)
549581
{
550582
nrf_802154_transmit_at_metadata_t metadata = {
551583
.frame_props = {
@@ -561,7 +593,16 @@ static bool nrf5_tx_at(struct net_pkt *pkt, uint8_t *payload, bool cca)
561593
#endif
562594
},
563595
};
564-
uint64_t tx_at = target_time_convert_to_64_bits(net_pkt_txtime(pkt) / NSEC_PER_USEC);
596+
uint64_t now_us = nrf_802154_time_get();
597+
uint64_t tx_at = target_time_convert_to_64_bits_from_given(
598+
net_pkt_txtime(pkt) / NSEC_PER_USEC, now_us);
599+
600+
if (time_ahead != NULL) {
601+
*time_ahead = 0;
602+
if (tx_at > now_us) {
603+
*time_ahead = (uint32_t)(tx_at - now_us);
604+
}
605+
}
565606

566607
return nrf_802154_transmit_raw_at(payload, tx_at, &metadata);
567608
}
@@ -576,6 +617,7 @@ static int nrf5_tx(const struct device *dev,
576617
uint8_t payload_len = frag->len;
577618
uint8_t *payload = frag->data;
578619
bool ret = true;
620+
uint32_t callback_sem_take_additional_time = 0;
579621

580622
LOG_DBG("%p (%u)", payload, payload_len);
581623

@@ -601,7 +643,9 @@ static int nrf5_tx(const struct device *dev,
601643
case IEEE802154_TX_MODE_TXTIME_CCA:
602644
__ASSERT_NO_MSG(pkt);
603645
ret = nrf5_tx_at(pkt, nrf5_radio->tx_psdu,
604-
mode == IEEE802154_TX_MODE_TXTIME_CCA);
646+
mode == IEEE802154_TX_MODE_TXTIME_CCA,
647+
&callback_sem_take_additional_time);
648+
callback_sem_take_additional_time /= 1000;
605649
break;
606650
#endif /* CONFIG_NET_PKT_TXTIME */
607651
default:
@@ -620,7 +664,7 @@ static int nrf5_tx(const struct device *dev,
620664
nrf_802154_channel_get(), nrf_802154_tx_power_get());
621665

622666
/* Wait for the callback from the radio driver. */
623-
k_sem_take(&nrf5_radio->tx_wait, K_FOREVER);
667+
nrf5_callback_sem_take(&nrf5_radio->tx_wait, callback_sem_take_additional_time);
624668

625669
LOG_DBG("Result: %d", nrf5_data.tx_result);
626670

0 commit comments

Comments
 (0)