drivers: ieee802154_nrf5: fix target time for indirect transmission
After change in RD into 64-bit time, target time must be express in absolute 64-bit time. Upper layer e.g. OpenThread still utilizes only LSB of the RD time therefore the conversion is required. Make sure that target time is absolute 64-bit target time. Signed-off-by: Lukasz Maciejonczyk <lukasz.maciejonczyk@nordicsemi.no>
This commit is contained in:
parent
31502ad174
commit
5d5dcfa0b9
1 changed files with 68 additions and 68 deletions
|
@ -465,6 +465,73 @@ static bool nrf5_tx_csma_ca(struct net_pkt *pkt, uint8_t *payload)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_NET_PKT_TXTIME)
|
#if IS_ENABLED(CONFIG_NET_PKT_TXTIME)
|
||||||
|
/**
|
||||||
|
* @brief Convert 32-bit target time to absolute 64-bit target time.
|
||||||
|
*/
|
||||||
|
static uint64_t target_time_convert_to_64_bits(uint32_t target_time)
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Target time is provided as two 32-bit integers defining a moment in time
|
||||||
|
* in microsecond domain. In order to use bit-shifting instead of modulo
|
||||||
|
* division, calculations are performed in microsecond domain, not in RTC ticks.
|
||||||
|
*
|
||||||
|
* The target time can point to a moment in the future, but can be overdue
|
||||||
|
* as well. In order to determine what's the case and correctly set the
|
||||||
|
* absolute target time, it's necessary to compare the least significant
|
||||||
|
* 32 bits of the current time, 64-bit time with the provided 32-bit target
|
||||||
|
* time. Let's assume that half of the 32-bit range can be used for specifying
|
||||||
|
* target times in the future, and the other half - in the past.
|
||||||
|
*/
|
||||||
|
uint64_t now_us = nrf_802154_time_get();
|
||||||
|
uint32_t now_us_wrapped = (uint32_t)now_us;
|
||||||
|
uint32_t time_diff = target_time - now_us_wrapped;
|
||||||
|
uint64_t result = UINT64_C(0);
|
||||||
|
|
||||||
|
if (time_diff < 0x80000000) {
|
||||||
|
/**
|
||||||
|
* Target time is assumed to be in the future. Check if a 32-bit overflow
|
||||||
|
* occurs between the current time and the target time.
|
||||||
|
*/
|
||||||
|
if (now_us_wrapped > target_time) {
|
||||||
|
/**
|
||||||
|
* Add a 32-bit overflow and replace the least significant 32 bits
|
||||||
|
* with the provided target time.
|
||||||
|
*/
|
||||||
|
result = now_us + UINT32_MAX + 1;
|
||||||
|
result &= ~(uint64_t)UINT32_MAX;
|
||||||
|
result |= target_time;
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* Leave the most significant 32 bits and replace the least significant
|
||||||
|
* 32 bits with the provided target time.
|
||||||
|
*/
|
||||||
|
result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* Target time is assumed to be in the past. Check if a 32-bit overflow
|
||||||
|
* occurs between the target time and the current time.
|
||||||
|
*/
|
||||||
|
if (now_us_wrapped > target_time) {
|
||||||
|
/**
|
||||||
|
* Leave the most significant 32 bits and replace the least significant
|
||||||
|
* 32 bits with the provided target time.
|
||||||
|
*/
|
||||||
|
result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time;
|
||||||
|
} else {
|
||||||
|
/**
|
||||||
|
* Subtract a 32-bit overflow and replace the least significant
|
||||||
|
* 32 bits with the provided target time.
|
||||||
|
*/
|
||||||
|
result = now_us - UINT32_MAX - 1;
|
||||||
|
result &= ~(uint64_t)UINT32_MAX;
|
||||||
|
result |= target_time;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
static bool nrf5_tx_at(struct net_pkt *pkt, uint8_t *payload, bool cca)
|
static bool nrf5_tx_at(struct net_pkt *pkt, uint8_t *payload, bool cca)
|
||||||
{
|
{
|
||||||
nrf_802154_transmit_at_metadata_t metadata = {
|
nrf_802154_transmit_at_metadata_t metadata = {
|
||||||
|
@ -475,7 +542,7 @@ static bool nrf5_tx_at(struct net_pkt *pkt, uint8_t *payload, bool cca)
|
||||||
.cca = cca,
|
.cca = cca,
|
||||||
.channel = nrf_802154_channel_get(),
|
.channel = nrf_802154_channel_get(),
|
||||||
};
|
};
|
||||||
uint64_t tx_at = net_pkt_txtime(pkt) / NSEC_PER_USEC;
|
uint64_t tx_at = target_time_convert_to_64_bits(net_pkt_txtime(pkt) / NSEC_PER_USEC);
|
||||||
bool ret;
|
bool ret;
|
||||||
|
|
||||||
ret = nrf_802154_transmit_raw_at(payload,
|
ret = nrf_802154_transmit_raw_at(payload,
|
||||||
|
@ -737,73 +804,6 @@ static void nrf5_config_mac_keys(struct ieee802154_key *mac_keys)
|
||||||
#endif /* CONFIG_IEEE802154_2015 */
|
#endif /* CONFIG_IEEE802154_2015 */
|
||||||
|
|
||||||
#if defined(CONFIG_IEEE802154_CSL_ENDPOINT)
|
#if defined(CONFIG_IEEE802154_CSL_ENDPOINT)
|
||||||
/**
|
|
||||||
* @brief Convert 32-bit target time to absolute 64-bit target time.
|
|
||||||
*/
|
|
||||||
static uint64_t target_time_convert_to_64_bits(uint32_t target_time)
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* Target time is provided as two 32-bit integers defining a moment in time
|
|
||||||
* in microsecond domain. In order to use bit-shifting instead of modulo
|
|
||||||
* division, calculations are performed in microsecond domain, not in RTC ticks.
|
|
||||||
*
|
|
||||||
* The target time can point to a moment in the future, but can be overdue
|
|
||||||
* as well. In order to determine what's the case and correctly set the
|
|
||||||
* absolute target time, it's necessary to compare the least significant
|
|
||||||
* 32 bits of the current time, 64-bit time with the provided 32-bit target
|
|
||||||
* time. Let's assume that half of the 32-bit range can be used for specifying
|
|
||||||
* target times in the future, and the other half - in the past.
|
|
||||||
*/
|
|
||||||
uint64_t now_us = nrf_802154_time_get();
|
|
||||||
uint32_t now_us_wrapped = (uint32_t)now_us;
|
|
||||||
uint32_t time_diff = target_time - now_us_wrapped;
|
|
||||||
uint64_t result = UINT64_C(0);
|
|
||||||
|
|
||||||
if (time_diff < 0x80000000) {
|
|
||||||
/**
|
|
||||||
* Target time is assumed to be in the future. Check if a 32-bit overflow
|
|
||||||
* occurs between the current time and the target time.
|
|
||||||
*/
|
|
||||||
if (now_us_wrapped > target_time) {
|
|
||||||
/**
|
|
||||||
* Add a 32-bit overflow and replace the least significant 32 bits
|
|
||||||
* with the provided target time.
|
|
||||||
*/
|
|
||||||
result = now_us + UINT32_MAX + 1;
|
|
||||||
result &= ~(uint64_t)UINT32_MAX;
|
|
||||||
result |= target_time;
|
|
||||||
} else {
|
|
||||||
/**
|
|
||||||
* Leave the most significant 32 bits and replace the least significant
|
|
||||||
* 32 bits with the provided target time.
|
|
||||||
*/
|
|
||||||
result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/**
|
|
||||||
* Target time is assumed to be in the past. Check if a 32-bit overflow
|
|
||||||
* occurs between the target time and the current time.
|
|
||||||
*/
|
|
||||||
if (now_us_wrapped > target_time) {
|
|
||||||
/**
|
|
||||||
* Leave the most significant 32 bits and replace the least significant
|
|
||||||
* 32 bits with the provided target time.
|
|
||||||
*/
|
|
||||||
result = (now_us & (~(uint64_t)UINT32_MAX)) | target_time;
|
|
||||||
} else {
|
|
||||||
/**
|
|
||||||
* Subtract a 32-bit overflow and replace the least significant
|
|
||||||
* 32 bits with the provided target time.
|
|
||||||
*/
|
|
||||||
result = now_us - UINT32_MAX - 1;
|
|
||||||
result &= ~(uint64_t)UINT32_MAX;
|
|
||||||
result |= target_time;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void nrf5_receive_at(uint32_t start, uint32_t duration, uint8_t channel, uint32_t id)
|
static void nrf5_receive_at(uint32_t start, uint32_t duration, uint8_t channel, uint32_t id)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue