[radio] use a single variable for frame timestamp (#4015)

This commit replaces mSec and mUsec in otRadioFrame with a single
mTimestamp to record when the frame is received.

The timestamp MUST be the time when SFD was received when TIME_SYNC or
CSL (Thread 1.2) is enabled, otherwise, it is the time when rx was
done.

This change reduces memory required to represent a radio frame.
This commit is contained in:
Yakun Xu
2019-07-29 22:52:37 -07:00
committed by Jonathan Hui
parent 4cb7d1fe77
commit d041699ad3
24 changed files with 300 additions and 317 deletions
@@ -29,10 +29,6 @@
#ifndef OPENTHREAD_CORE_CC1352_CONFIG_CHECK_H_
#define OPENTHREAD_CORE_CC1352_CONFIG_CHECK_H_
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error "Platform cc1352 doesn't support configuration option: OPENTHREAD_CONFIG_ENABLE_TIME_SYNC"
#endif
#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
#error "Platform cc1352 doesn't support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT"
#endif
+9 -4
View File
@@ -1896,11 +1896,16 @@ static void cc1352RadioProcessReceiveQueue(otInstance *aInstance)
if (crcCorr->status.bCrcErr == 0 && (len - 2) < OT_RADIO_FRAME_MAX_SIZE)
{
#if OPENTHREAD_ENABLE_RAW_LINK_API
// TODO: Propagate CM0 timestamp
receiveFrame.mInfo.mRxInfo.mMsec = otPlatAlarmMilliGetNow();
receiveFrame.mInfo.mRxInfo.mUsec = 0; // Don't support microsecond timer for now.
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error Time sync requires the timestamp of SFD rather than that of rx done!
#else
if (otPlatRadioGetPromiscuous(aInstance))
#endif
{
// TODO: Propagate CM0 timestamp
// The current driver only supports milliseconds resolution.
receiveFrame.mInfo.mRxInfo.mTimestamp = otPlatAlarmMilliGetNow() * 1000;
}
receiveFrame.mLength = len;
receiveFrame.mPsdu = &(payload[1]);
@@ -29,10 +29,6 @@
#ifndef OPENTHREAD_CORE_CC2538_CONFIG_CHECK_H_
#define OPENTHREAD_CORE_CC2538_CONFIG_CHECK_H_
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error "Platform cc2538 doesn't support configuration option: OPENTHREAD_CONFIG_ENABLE_TIME_SYNC"
#endif
#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
#error "Platform cc2538 doesn't support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT"
#endif
+7 -3
View File
@@ -662,11 +662,15 @@ void readFrame(otInstance *aInstance)
length = HWREG(RFCORE_SFR_RFDATA);
otEXPECT(IEEE802154_MIN_LENGTH <= length && length <= IEEE802154_MAX_LENGTH);
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error Time sync requires the timestamp of SFD rather than that of rx done!
#else
// Timestamp
if (otPlatRadioGetPromiscuous(aInstance))
#endif
{
// Timestamp
sReceiveFrame.mInfo.mRxInfo.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrame.mInfo.mRxInfo.mUsec = 0; // Don't support microsecond timer for now.
// The current driver only supports milliseconds resolution.
sReceiveFrame.mInfo.mRxInfo.mTimestamp = otPlatAlarmMilliGetNow() * 1000;
}
// read psdu
@@ -29,10 +29,6 @@
#ifndef OPENTHREAD_CORE_CC2650_CONFIG_CHECK_H_
#define OPENTHREAD_CORE_CC2650_CONFIG_CHECK_H_
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error "Platform cc2650 doesn't support configuration option: OPENTHREAD_CONFIG_ENABLE_TIME_SYNC"
#endif
#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
#error "Platform cc2650 doesn't support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT"
#endif
+6 -2
View File
@@ -1845,11 +1845,15 @@ static void cc2650RadioProcessReceiveQueue(otInstance *aInstance)
if (crcCorr->status.bCrcErr == 0 && (len - 2) < OT_RADIO_FRAME_MAX_SIZE)
{
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error Time sync requires the timestamp of SFD rather than that of rx done!
#else
if (otPlatRadioGetPromiscuous(aInstance))
#endif
{
// TODO: Propagate CM0 timestamp
receiveFrame.mInfo.mRxInfo.mMsec = otPlatAlarmMilliGetNow();
receiveFrame.mInfo.mRxInfo.mUsec = 0; // Don't support microsecond timer for now.
// The current driver only supports milliseconds resolution.
receiveFrame.mInfo.mRxInfo.mTimestamp = otPlatAlarmMilliGetNow() * 1000;
}
receiveFrame.mLength = len;
@@ -29,10 +29,6 @@
#ifndef OPENTHREAD_CORE_CC2652_CONFIG_CHECK_H_
#define OPENTHREAD_CORE_CC2652_CONFIG_CHECK_H_
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error "Platform cc2652 doesn't support configuration option: OPENTHREAD_CONFIG_ENABLE_TIME_SYNC"
#endif
#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
#error "Platform cc2652 doesn't support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT"
#endif
+6 -2
View File
@@ -1877,11 +1877,15 @@ static void cc2652RadioProcessReceiveQueue(otInstance *aInstance)
if (crcCorr->status.bCrcErr == 0 && (len - 2) < OT_RADIO_FRAME_MAX_SIZE)
{
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error Time sync requires the timestamp of SFD rather than that of rx done!
#else
if (otPlatRadioGetPromiscuous(aInstance))
#endif
{
// TODO: Propagate CM0 timestamp
receiveFrame.mInfo.mRxInfo.mMsec = otPlatAlarmMilliGetNow();
receiveFrame.mInfo.mRxInfo.mUsec = 0; // Don't support microsecond timer for now.
// The current driver only supports milliseconds resolution.
receiveFrame.mInfo.mRxInfo.mTimestamp = otPlatAlarmMilliGetNow() * 1000;
}
receiveFrame.mLength = len;
@@ -29,10 +29,6 @@
#ifndef OPENTHREAD_CORE_KW41Z_CONFIG_CHECK_H_
#define OPENTHREAD_CORE_KW41Z_CONFIG_CHECK_H_
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error "Platform kw41z doesn't support configuration option: OPENTHREAD_CONFIG_ENABLE_TIME_SYNC"
#endif
#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
#error "Platform kw41z doesn't support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT"
#endif
+6 -3
View File
@@ -770,11 +770,14 @@ static bool rf_process_rx_frame(void)
/* Check if frame is valid */
otEXPECT_ACTION((IEEE802154_MIN_LENGTH <= temp) && (temp <= IEEE802154_MAX_LENGTH), status = false);
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error Time sync requires the timestamp of SFD rather than that of rx done!
#else
if (otPlatRadioGetPromiscuous(sInstance))
#endif
{
// Timestamp
sRxFrame.mInfo.mRxInfo.mMsec = otPlatAlarmMilliGetNow();
sRxFrame.mInfo.mRxInfo.mUsec = 0; // Don't support microsecond timer for now.
// The current driver only supports milliseconds resolution.
sRxFrame.mInfo.mRxInfo.mTimestamp = otPlatAlarmMilliGetNow() * 1000;
}
sRxFrame.mLength = temp;
+11 -16
View File
@@ -86,7 +86,6 @@ static uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE + 1];
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
static otRadioIeInfo sTransmitIeInfo;
static otRadioIeInfo sReceivedIeInfos[NRF_802154_RX_BUFFERS];
#endif
static otInstance *sInstance = NULL;
@@ -118,7 +117,7 @@ static void dataInit(void)
sTransmitFrame.mPsdu = sTransmitPsdu + 1;
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
sTransmitFrame.mIeInfo = &sTransmitIeInfo;
sTransmitFrame.mInfo.mTxInfo.mIeInfo = &sTransmitIeInfo;
#endif
sReceiveError = OT_ERROR_NONE;
@@ -712,9 +711,6 @@ void nrf_802154_received_raw(uint8_t *p_data, int8_t power, uint8_t lqi)
receivedFrame = &sReceivedFrames[i];
memset(receivedFrame, 0, sizeof(*receivedFrame));
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
receivedFrame->mIeInfo = &sReceivedIeInfos[i];
#endif
break;
}
}
@@ -737,17 +733,16 @@ void nrf_802154_received_raw(uint8_t *p_data, int8_t power, uint8_t lqi)
receivedFrame->mInfo.mRxInfo.mAckedWithFramePending = false;
}
if (otPlatRadioGetPromiscuous(sInstance))
{
uint64_t timestamp = nrf5AlarmGetCurrentTime();
receivedFrame->mInfo.mRxInfo.mMsec = timestamp / US_PER_MS;
receivedFrame->mInfo.mRxInfo.mUsec = timestamp - receivedFrame->mInfo.mRxInfo.mMsec * US_PER_MS;
}
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
// Get the timestamp when the SFD was received.
uint32_t offset =
(int32_t)otPlatAlarmMicroGetNow() - (int32_t)nrf_802154_first_symbol_timestamp_get(time, p_data[0]);
receivedFrame->mIeInfo->mTimestamp = otPlatTimeGet() - offset;
receivedFrame->mInfo.mRxInfo.mTimestamp = otPlatTimeGet() - offset;
#else
if (otPlatRadioGetPromiscuous(sInstance))
{
receivedFrame->mInfo.mRxInfo.mTimestamp = nrf5AlarmGetCurrentTime();
}
#endif
sAckedWithFramePending = false;
@@ -859,12 +854,12 @@ void nrf_802154_tx_started(const uint8_t *aFrame)
assert(aFrame == sTransmitPsdu);
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
if (sTransmitFrame.mIeInfo->mTimeIeOffset != 0)
if (sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0)
{
uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mIeInfo->mTimeIeOffset;
uint64_t time = otPlatTimeGet() + sTransmitFrame.mIeInfo->mNetworkTimeOffset;
uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
uint64_t time = otPlatTimeGet() + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset;
*timeIe = sTransmitFrame.mIeInfo->mTimeSyncSeq;
*timeIe = sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
*(++timeIe) = (uint8_t)(time & 0xff);
for (uint8_t i = 1; i < sizeof(uint64_t); i++)
+12 -17
View File
@@ -86,7 +86,6 @@ static uint8_t sTransmitPsdu[OT_RADIO_FRAME_MAX_SIZE + 1];
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
static otRadioIeInfo sTransmitIeInfo;
static otRadioIeInfo sReceivedIeInfos[NRF_802154_RX_BUFFERS];
#endif
static otInstance *sInstance = NULL;
@@ -118,7 +117,7 @@ static void dataInit(void)
sTransmitFrame.mPsdu = sTransmitPsdu + 1;
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
sTransmitFrame.mIeInfo = &sTransmitIeInfo;
sTransmitFrame.mInfo.mTxInfo.mIeInfo = &sTransmitIeInfo;
#endif
sReceiveError = OT_ERROR_NONE;
@@ -712,9 +711,6 @@ void nrf_802154_received_raw(uint8_t *p_data, int8_t power, uint8_t lqi)
receivedFrame = &sReceivedFrames[i];
memset(receivedFrame, 0, sizeof(*receivedFrame));
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
receivedFrame->mIeInfo = &sReceivedIeInfos[i];
#endif
break;
}
}
@@ -737,18 +733,17 @@ void nrf_802154_received_raw(uint8_t *p_data, int8_t power, uint8_t lqi)
receivedFrame->mInfo.mRxInfo.mAckedWithFramePending = false;
}
if (otPlatRadioGetPromiscuous(sInstance))
{
uint64_t timestamp = nrf5AlarmGetCurrentTime();
receivedFrame->mInfo.mRxInfo.mMsec = timestamp / US_PER_MS;
receivedFrame->mInfo.mRxInfo.mUsec = timestamp - receivedFrame->mInfo.mRxInfo.mMsec * US_PER_MS;
}
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
// Get the timestamp when the SFD was received.
uint32_t offset =
(int32_t)otPlatAlarmMicroGetNow() - (int32_t)nrf_802154_first_symbol_timestamp_get(time, p_data[0]);
receivedFrame->mIeInfo->mTimestamp = otPlatTimeGet() - offset;
#endif
receivedFrame->mInfo.mRxInfo.mTimestamp = otPlatTimeGet() - offset;
#else
if (otPlatRadioGetPromiscuous(sInstance))
{
receivedFrame->mInfo.mRxInfo.mTimestamp = nrf5AlarmGetCurrentTime();
}
#endif // OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
sAckedWithFramePending = false;
@@ -860,12 +855,12 @@ void nrf_802154_tx_started(const uint8_t *aFrame)
assert(aFrame == sTransmitPsdu);
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
if (sTransmitFrame.mIeInfo->mTimeIeOffset != 0)
if (sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0)
{
uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mIeInfo->mTimeIeOffset;
uint64_t time = otPlatTimeGet() + sTransmitFrame.mIeInfo->mNetworkTimeOffset;
uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
uint64_t time = otPlatTimeGet() + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset;
*timeIe = sTransmitFrame.mIeInfo->mTimeSyncSeq;
*timeIe = sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
*(++timeIe) = (uint8_t)(time & 0xff);
for (uint8_t i = 1; i < sizeof(uint64_t); i++)
+1 -1
View File
@@ -300,12 +300,12 @@ void platformAlarmProcess(otInstance *aInstance)
#endif // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER
}
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
uint64_t otPlatTimeGet(void)
{
return platformGetNow();
}
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
uint16_t otPlatTimeGetXtalAccuracy(void)
{
return 0;
+11 -16
View File
@@ -130,7 +130,6 @@ static otRadioFrame sAckFrame;
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
static otRadioIeInfo sTransmitIeInfo;
static otRadioIeInfo sReceivedIeInfo;
#endif
static uint8_t sExtendedAddress[OT_EXT_ADDRESS_SIZE];
@@ -497,11 +496,9 @@ void platformRadioInit(void)
sAckFrame.mPsdu = sAckMessage.mPsdu;
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
sTransmitFrame.mIeInfo = &sTransmitIeInfo;
sReceiveFrame.mIeInfo = &sReceivedIeInfo;
sTransmitFrame.mInfo.mTxInfo.mIeInfo = &sTransmitIeInfo;
#else
sTransmitFrame.mIeInfo = NULL;
sReceiveFrame.mIeInfo = NULL;
sTransmitFrame.mInfo.mTxInfo.mIeInfo = NULL;
#endif
}
@@ -637,13 +634,11 @@ static void radioReceive(otInstance *aInstance)
otEXPECT(sReceiveFrame.mChannel == sReceiveMessage.mChannel);
otEXPECT(sState == OT_RADIO_STATE_RECEIVE || sState == OT_RADIO_STATE_TRANSMIT);
// Timestamp
sReceiveFrame.mInfo.mRxInfo.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrame.mInfo.mRxInfo.mUsec = 0; // Don't support microsecond timer for now.
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
sReceiveFrame.mIeInfo->mTimestamp = otPlatTimeGet();
#endif
if (otPlatRadioGetPromiscuous(aInstance))
{
// Unable to simulate SFD, so use the rx done timestamp instead.
sReceiveFrame.mInfo.mRxInfo.mTimestamp = otPlatTimeGet();
}
if (sTxWait)
{
@@ -707,12 +702,12 @@ void radioSendMessage(otInstance *aInstance)
bool notifyFrameUpdated = false;
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
if (sTransmitFrame.mIeInfo->mTimeIeOffset != 0)
if (sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0)
{
uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mIeInfo->mTimeIeOffset;
uint64_t time = (uint64_t)((int64_t)otPlatTimeGet() + sTransmitFrame.mIeInfo->mNetworkTimeOffset);
uint8_t *timeIe = sTransmitFrame.mPsdu + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset;
uint64_t time = (uint64_t)((int64_t)otPlatTimeGet() + sTransmitFrame.mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset);
*timeIe = sTransmitFrame.mIeInfo->mTimeSyncSeq;
*timeIe = sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeSyncSeq;
*(++timeIe) = (uint8_t)(time & 0xff);
for (uint8_t i = 1; i < sizeof(uint64_t); i++)
+1 -1
View File
@@ -181,12 +181,12 @@ void platformAlarmProcess(otInstance *aInstance)
#endif // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER
}
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
uint64_t otPlatTimeGet(void)
{
return platformAlarmGetNow();
}
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
uint16_t otPlatTimeGetXtalAccuracy(void)
{
return 0;
@@ -29,10 +29,6 @@
#ifndef OPENTHREAD_CORE_SAMR21_CONFIG_CHECK_H_
#define OPENTHREAD_CORE_SAMR21_CONFIG_CHECK_H_
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error "Platform samr21 doesn't support configuration option: OPENTHREAD_CONFIG_ENABLE_TIME_SYNC"
#endif
#if OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT
#error "Platform samr21 doesn't support configuration option: OPENTHREAD_CONFIG_RADIO_915MHZ_OQPSK_SUPPORT"
#endif
+6 -3
View File
@@ -218,11 +218,14 @@ static void handleRx(void)
{
sRxDone = false;
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#error Time sync requires the timestamp of SFD rather than that of rx done!
#else
if (otPlatRadioGetPromiscuous(sInstance))
#endif
{
// Timestamp
sReceiveFrame.mInfo.mRxInfo.mMsec = otPlatAlarmMilliGetNow();
sReceiveFrame.mInfo.mRxInfo.mUsec = 0; // Don't support microsecond timer for now.
// The current driver only supports milliseconds resolution.
sReceiveFrame.mInfo.mRxInfo.mTimestamp = otPlatAlarmMilliGetNow() * 1000;
}
// TODO Set this flag only when the packet is really acknowledged with frame pending set.
+16 -20
View File
@@ -164,10 +164,9 @@ typedef struct otExtAddress otExtAddress;
*/
typedef struct otRadioIeInfo
{
uint8_t mTimeIeOffset; ///< The Time IE offset from the start of PSDU.
uint8_t mTimeSyncSeq; ///< The Time sync sequence.
uint64_t mTimestamp; ///< The time in microseconds when the SFD was received.
int64_t mNetworkTimeOffset; ///< The time offset to the Thread network time.
int64_t mNetworkTimeOffset; ///< The time offset to the Thread network time.
uint8_t mTimeIeOffset; ///< The Time IE offset from the start of PSDU.
uint8_t mTimeSyncSeq; ///< The Time sync sequence.
} otRadioIeInfo;
/**
@@ -175,10 +174,10 @@ typedef struct otRadioIeInfo
*/
typedef struct otRadioFrame
{
uint8_t * mPsdu; ///< The PSDU.
uint16_t mLength; ///< Length of the PSDU.
uint8_t mChannel; ///< Channel used to transmit/receive the frame.
otRadioIeInfo *mIeInfo; ///< The pointer to the Header IE(s) related information.
uint8_t *mPsdu; ///< The PSDU.
uint16_t mLength; ///< Length of the PSDU.
uint8_t mChannel; ///< Channel used to transmit/receive the frame.
/**
* The union of transmit and receive information for a radio frame.
@@ -190,11 +189,12 @@ typedef struct otRadioFrame
*/
struct
{
const uint8_t *mAesKey; ///< The key used for AES-CCM frame security.
otRadioIeInfo *mIeInfo; ///< The pointer to the Header IE(s) related information.
uint8_t mMaxCsmaBackoffs; ///< Maximum number of backoffs attempts before declaring CCA failure.
uint8_t mMaxFrameRetries; ///< Maximum number of retries allowed after a transmission failure.
bool mIsARetx : 1; ///< True if this frame is a retransmission (ignored by radio driver).
bool mCsmaCaEnabled : 1; ///< Set to true to enable CSMA-CA for this packet, false otherwise.
const uint8_t *mAesKey; ///< The key used for AES-CCM frame security.
} mTxInfo;
/**
@@ -203,20 +203,16 @@ typedef struct otRadioFrame
struct
{
/**
* The timestamp when the frame was received (milliseconds).
* Applicable/Required only when raw-link-api feature (`OPENTHREAD_ENABLE_RAW_LINK_API`) is enabled.
* The timestamp when the frame was received in microseconds.
*
* The value SHALL be the time when the SFD was received when TIME_SYNC or CSL is enabled.
* Otherwise, the time when the MAC frame was fully received is also acceptable.
*
*/
uint32_t mMsec;
uint64_t mTimestamp;
/**
* The timestamp when the frame was received (microseconds, the offset to mMsec).
* Applicable/Required only when raw-link-api feature (`OPENTHREAD_ENABLE_RAW_LINK_API`) is enabled.
*
*/
uint16_t mUsec;
int8_t mRssi; ///< Received signal strength indicator in dBm for received frames.
uint8_t mLqi; ///< Link Quality Indicator for received frames.
int8_t mRssi; ///< Received signal strength indicator in dBm for received frames.
uint8_t mLqi; ///< Link Quality Indicator for received frames.
// Flags
bool mAckedWithFramePending : 1; /// This indicates if this frame was acknowledged with frame pending set.
+4 -28
View File
@@ -1659,17 +1659,6 @@ void Mac::HandleReceivedFrame(Frame *aFrame, otError aError)
Get<DataPollSender>().CheckFramePending(*aFrame);
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
if (aFrame->GetVersion() == Frame::kFcfFrameVersion2015)
{
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
ProcessTimeIe(*aFrame);
#endif
}
#endif // OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
if (neighbor != NULL)
{
#if OPENTHREAD_ENABLE_MAC_FILTER
@@ -1994,26 +1983,13 @@ void Mac::LogFrameTxFailure(const Frame &, otError, uint8_t) const
// LCOV_EXCL_STOP
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
void Mac::ProcessTimeIe(Frame &aFrame)
{
TimeIe *timeIe = reinterpret_cast<TimeIe *>(aFrame.GetTimeIe());
VerifyOrExit(timeIe != NULL);
aFrame.SetNetworkTimeOffset(static_cast<int64_t>(timeIe->GetTime()) - static_cast<int64_t>(aFrame.GetTimestamp()));
aFrame.SetTimeSyncSeq(timeIe->GetSequence());
exit:
return;
}
uint8_t Mac::GetTimeIeOffset(Frame &aFrame)
{
uint8_t offset = 0;
uint8_t *base = aFrame.GetPsdu();
uint8_t *cur = NULL;
uint8_t offset = 0;
const uint8_t *base = aFrame.GetPsdu();
const uint8_t *cur = NULL;
cur = aFrame.GetTimeIe();
cur = reinterpret_cast<const uint8_t *>(aFrame.GetTimeIe());
VerifyOrExit(cur != NULL);
cur += sizeof(VendorIeHeader);
+17 -11
View File
@@ -1011,11 +1011,13 @@ exit:
#endif // OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
const uint8_t *Frame::GetTimeIe(void) const
const TimeIe *Frame::GetTimeIe(void) const
{
const TimeIe * timeIe = NULL;
const uint8_t *cur = NULL;
uint8_t oui[kVendorOuiSize] = {kVendorOuiNest & 0xff, (kVendorOuiNest >> 8) & 0xff, (kVendorOuiNest >> 16) & 0xff};
const TimeIe * timeIe = NULL;
const uint8_t *cur = NULL;
uint8_t oui[VendorIeHeader::kVendorOuiSize] = {VendorIeHeader::kVendorOuiNest & 0xff,
(VendorIeHeader::kVendorOuiNest >> 8) & 0xff,
(VendorIeHeader::kVendorOuiNest >> 16) & 0xff};
cur = GetHeaderIe(kHeaderIeVendor);
VerifyOrExit(cur != NULL);
@@ -1023,29 +1025,33 @@ const uint8_t *Frame::GetTimeIe(void) const
cur += sizeof(HeaderIe);
timeIe = reinterpret_cast<const TimeIe *>(cur);
VerifyOrExit(memcmp(oui, timeIe->GetVendorOui(), kVendorOuiSize) == 0, cur = NULL);
VerifyOrExit(timeIe->GetSubType() == kVendorIeTime, cur = NULL);
VerifyOrExit(memcmp(oui, timeIe->GetVendorOui(), VendorIeHeader::kVendorOuiSize) == 0, timeIe = NULL);
VerifyOrExit(timeIe->GetSubType() == VendorIeHeader::kVendorIeTime, timeIe = NULL);
exit:
return cur;
return timeIe;
}
#endif // OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
void Frame::CopyFrom(const Frame &aFromFrame)
{
uint8_t * psduBuffer = mPsdu;
otRadioIeInfo *ieInfoBuffer = mIeInfo;
otRadioIeInfo *ieInfoBuffer = mInfo.mTxInfo.mIeInfo;
memcpy(this, &aFromFrame, sizeof(Frame));
// Set the original buffer pointers back on the frame
// which were overwritten by above `memcpy()`.
mPsdu = psduBuffer;
mIeInfo = ieInfoBuffer;
mPsdu = psduBuffer;
mInfo.mTxInfo.mIeInfo = ieInfoBuffer;
memcpy(mPsdu, aFromFrame.mPsdu, aFromFrame.GetPsduLength());
memcpy(mIeInfo, aFromFrame.mIeInfo, sizeof(otRadioIeInfo));
// mIeInfo may be null when TIME_SYNC is not enabled.
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
memcpy(mInfo.mTxInfo.mIeInfo, aFromFrame.mInfo.mTxInfo.mIeInfo, sizeof(otRadioIeInfo));
#endif
}
uint16_t Frame::GetMtu(void) const
+147 -137
View File
@@ -454,6 +454,118 @@ private:
uint16_t mHeaderIe;
} OT_TOOL_PACKED_END;
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
/**
* This class implements vendor specific Header IE generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class VendorIeHeader
{
public:
enum
{
kVendorOuiNest = 0x18b430,
kVendorOuiSize = 3,
kVendorIeTime = 0x01,
};
/**
* This method returns the Vendor OUI.
*
* @returns the Vendor OUI.
*
*/
const uint8_t *GetVendorOui(void) const { return mVendorOui; }
/**
* This method sets the Vendor OUI.
*
* @param[in] aVendorOui A pointer to the Vendor OUI.
*
*/
void SetVendorOui(const uint8_t *aVendorOui) { memcpy(mVendorOui, aVendorOui, kVendorOuiSize); }
/**
* This method returns the Vendor IE sub-type.
*
* @returns the Vendor IE sub-type.
*
*/
uint8_t GetSubType(void) const { return mSubType; }
/**
* This method sets the Vendor IE sub-type.
*
* @param[in] the Vendor IE sub-type.
*
*/
void SetSubType(uint8_t aSubType) { mSubType = aSubType; }
private:
uint8_t mVendorOui[kVendorOuiSize];
uint8_t mSubType;
} OT_TOOL_PACKED_END;
/**
* This class implements Time Header IE generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class TimeIe : public VendorIeHeader
{
public:
/**
* This method initializes the time IE.
*
*/
void Init(void)
{
uint8_t oui[3] = {VendorIeHeader::kVendorOuiNest & 0xff, (VendorIeHeader::kVendorOuiNest >> 8) & 0xff,
(VendorIeHeader::kVendorOuiNest >> 16) & 0xff};
SetVendorOui(oui);
SetSubType(VendorIeHeader::kVendorIeTime);
}
/**
* This method returns the time sync sequence.
*
* @returns the time sync sequence.
*
*/
uint8_t GetSequence(void) const { return mSequence; }
/**
* This method sets the tine sync sequence.
*
* @param[in] aSequence The time sync sequence.
*
*/
void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
/**
* This method returns the network time.
*
* @returns the network time, in microseconds.
*
*/
uint64_t GetTime(void) const { return ot::Encoding::LittleEndian::HostSwap64(mTime); }
/**
* This method sets the network time.
*
* @param[in] aTime The network time.
*
*/
void SetTime(uint64_t aTime) { mTime = ot::Encoding::LittleEndian::HostSwap64(aTime); }
private:
uint8_t mSequence;
uint64_t mTime;
} OT_TOOL_PACKED_END;
#endif // OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
/**
* This class implements IEEE 802.15.4 MAC frame generation and parsing.
*
@@ -534,9 +646,6 @@ public:
kHeaderIeVendor = 0x00,
kHeaderIeTermination2 = 0x7f,
kVendorOuiNest = 0x18b430,
kVendorOuiSize = 3,
kVendorIeTime = 0x01,
kInfoStringSize = 110, ///< Max chars needed for the info string representation (@sa ToInfoString()).
};
@@ -1148,6 +1257,14 @@ public:
*/
const uint8_t *GetFooter(void) const;
/**
* This method returns the timestamp when the frame was received.
*
* @returns The timestamp when the frame was received, in microseconds.
*
*/
const uint64_t &GetTimestamp(void) const { return mInfo.mRxInfo.mTimestamp; }
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
/**
* This method sets the Time IE offset.
@@ -1155,7 +1272,7 @@ public:
* @param[in] aOffset The Time IE offset, 0 means no Time IE.
*
*/
void SetTimeIeOffset(uint8_t aOffset) { mIeInfo->mTimeIeOffset = aOffset; }
void SetTimeIeOffset(uint8_t aOffset) { mInfo.mTxInfo.mIeInfo->mTimeIeOffset = aOffset; }
/**
* This method sets the offset to network time.
@@ -1163,7 +1280,26 @@ public:
* @param[in] aNetworkTimeOffset The offset to network time.
*
*/
void SetNetworkTimeOffset(int64_t aNetworkTimeOffset) { mIeInfo->mNetworkTimeOffset = aNetworkTimeOffset; }
void SetNetworkTimeOffset(int64_t aNetworkTimeOffset)
{
mInfo.mTxInfo.mIeInfo->mNetworkTimeOffset = aNetworkTimeOffset;
}
/**
* This method returns a pointer to the vendor specific Time IE.
*
* @returns A pointer to the Time IE, NULL if not found.
*
*/
TimeIe *GetTimeIe(void) { return const_cast<TimeIe *>(const_cast<const Frame *>(this)->GetTimeIe()); }
/**
* This method returns a pointer to the vendor specific Time IE.
*
* @returns A pointer to the Time IE, NULL if not found.
*
*/
const TimeIe *GetTimeIe(void) const;
/**
* This method gets the offset to network time.
@@ -1171,7 +1307,10 @@ public:
* @returns The offset to network time.
*
*/
int64_t GetNetworkTimeOffset(void) const { return mIeInfo->mNetworkTimeOffset; }
int64_t ComputeNetworkTimeOffset(void) const
{
return static_cast<int64_t>(GetTimeIe()->GetTime() - GetTimestamp());
}
/**
* This method sets the time sync sequence.
@@ -1179,7 +1318,7 @@ public:
* @param[in] aTimeSyncSeq The time sync sequence.
*
*/
void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { mIeInfo->mTimeSyncSeq = aTimeSyncSeq; }
void SetTimeSyncSeq(uint8_t aTimeSyncSeq) { mInfo.mTxInfo.mIeInfo->mTimeSyncSeq = aTimeSyncSeq; }
/**
* This method gets the time sync sequence.
@@ -1187,31 +1326,7 @@ public:
* @returns The time sync sequence.
*
*/
uint8_t GetTimeSyncSeq(void) const { return mIeInfo->mTimeSyncSeq; }
/**
* This method returns the timestamp when the SFD was received.
*
* @returns The timestamp when the SFD was received, in microseconds.
*
*/
uint64_t GetTimestamp(void) const { return mIeInfo->mTimestamp; }
/**
* This method returns a pointer to the vendor specific Time IE.
*
* @returns A pointer to the Time IE, NULL if not found.
*
*/
uint8_t *GetTimeIe(void) { return const_cast<uint8_t *>(const_cast<const Frame *>(this)->GetTimeIe()); }
/**
* This method returns a pointer to the vendor specific Time IE.
*
* @returns A pointer to the Time IE, NULL if not found.
*
*/
const uint8_t *GetTimeIe(void) const;
uint8_t ReadTimeSyncSeq(void) const { return GetTimeIe()->GetSequence(); }
#endif // OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
#if OPENTHREAD_CONFIG_HEADER_IE_SUPPORT
@@ -1523,111 +1638,6 @@ private:
uint8_t mExtendedPanId[kExtPanIdSize];
} OT_TOOL_PACKED_END;
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
/**
* This class implements vendor specific Header IE generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class VendorIeHeader
{
public:
/**
* This method returns the Vendor OUI.
*
* @returns the Vendor OUI.
*
*/
const uint8_t *GetVendorOui(void) const { return mVendorOui; }
/**
* This method sets the Vendor OUI.
*
* @param[in] aVendorOui A pointer to the Vendor OUI.
*
*/
void SetVendorOui(uint8_t *aVendorOui) { memcpy(mVendorOui, aVendorOui, Frame::kVendorOuiSize); }
/**
* This method returns the Vendor IE sub-type.
*
* @returns the Vendor IE sub-type.
*
*/
uint8_t GetSubType(void) const { return mSubType; }
/**
* This method sets the Vendor IE sub-type.
*
* @param[in] the Vendor IE sub-type.
*
*/
void SetSubType(uint8_t aSubType) { mSubType = aSubType; }
private:
uint8_t mVendorOui[Frame::kVendorOuiSize];
uint8_t mSubType;
} OT_TOOL_PACKED_END;
/**
* This class implements Time Header IE generation and parsing.
*
*/
OT_TOOL_PACKED_BEGIN
class TimeIe : public VendorIeHeader
{
public:
/**
* This method initializes the time IE.
*
*/
void Init(void)
{
uint8_t oui[3] = {Frame::kVendorOuiNest & 0xff, (Frame::kVendorOuiNest >> 8) & 0xff,
(Frame::kVendorOuiNest >> 16) & 0xff};
SetVendorOui(oui);
SetSubType(Frame::kVendorIeTime);
}
/**
* This method returns the time sync sequence.
*
* @returns the time sync sequence.
*
*/
uint8_t GetSequence(void) const { return mSequence; }
/**
* This method sets the tine sync sequence.
*
* @param[in] aSequence The time sync sequence.
*
*/
void SetSequence(uint8_t aSequence) { mSequence = aSequence; }
/**
* This method returns the network time.
*
* @returns the network time, in microseconds.
*
*/
uint64_t GetTime(void) const { return ot::Encoding::LittleEndian::HostSwap64(mTime); }
/**
* This method sets the network time.
*
* @param[in] aTime The network time.
*
*/
void SetTime(uint64_t aTime) { mTime = ot::Encoding::LittleEndian::HostSwap64(aTime); }
private:
uint8_t mSequence;
uint64_t mTime;
} OT_TOOL_PACKED_END;
#endif // OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
/**
* @}
*
+5 -2
View File
@@ -1073,8 +1073,11 @@ void MeshForwarder::HandleReceivedFrame(Mac::Frame &aFrame)
linkInfo.mLqi = aFrame.GetLqi();
linkInfo.mLinkSecurity = aFrame.GetSecurityEnabled();
#if OPENTHREAD_CONFIG_ENABLE_TIME_SYNC
linkInfo.mNetworkTimeOffset = aFrame.GetNetworkTimeOffset();
linkInfo.mTimeSyncSeq = aFrame.GetTimeSyncSeq();
if (aFrame.GetTimeIe() != NULL)
{
linkInfo.mNetworkTimeOffset = aFrame.ComputeNetworkTimeOffset();
linkInfo.mTimeSyncSeq = aFrame.ReadTimeSyncSeq();
}
#endif
payload = aFrame.GetPayload();
+16 -11
View File
@@ -86,11 +86,15 @@ void NcpBase::LinkRawReceiveDone(otRadioFrame *aFrame, otError aError)
SuccessOrExit(mEncoder.WriteUint16(flags)); // Flags
SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
SuccessOrExit(mEncoder.WriteUint8(aFrame->mChannel)); // 802.15.4 channel (Receive channel)
SuccessOrExit(mEncoder.WriteUint8(aFrame->mInfo.mRxInfo.mLqi)); // 802.15.4 LQI
SuccessOrExit(mEncoder.WriteUint32(aFrame->mInfo.mRxInfo.mMsec)); // The timestamp milliseconds
SuccessOrExit(mEncoder.WriteUint16(aFrame->mInfo.mRxInfo.mUsec)); // The timestamp microseconds, offset to mMsec
SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
SuccessOrExit(mEncoder.WriteUint8(aFrame->mChannel)); // 802.15.4 channel (Receive channel)
SuccessOrExit(mEncoder.WriteUint8(aFrame->mInfo.mRxInfo.mLqi)); // 802.15.4 LQI
SuccessOrExit(mEncoder.WriteUint32(
static_cast<uint32_t>(aFrame->mInfo.mRxInfo.mTimestamp / 1000))); // The timestamp milliseconds
SuccessOrExit(
mEncoder.WriteUint16(aFrame->mInfo.mRxInfo.mTimestamp % 1000)); // The timestamp microseconds, offset to mMsec
SuccessOrExit(mEncoder.CloseStruct());
SuccessOrExit(mEncoder.OpenStruct()); // Vendor-data
@@ -133,12 +137,13 @@ void NcpBase::LinkRawTransmitDone(otRadioFrame *aFrame, otRadioFrame *aAckFrame,
SuccessOrExit(mEncoder.WriteInt8(-128)); // Noise Floor (Currently unused)
SuccessOrExit(mEncoder.WriteUint16(0)); // Flags
SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mChannel)); // Receive channel
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mInfo.mRxInfo.mLqi)); // Link Quality Indicator
SuccessOrExit(mEncoder.WriteUint32(aAckFrame->mInfo.mRxInfo.mMsec)); // The timestamp milliseconds
SuccessOrExit(
mEncoder.WriteUint16(aAckFrame->mInfo.mRxInfo.mUsec)); // The timestamp microseconds, offset to mMsec
SuccessOrExit(mEncoder.OpenStruct()); // PHY-data
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mChannel)); // Receive channel
SuccessOrExit(mEncoder.WriteUint8(aAckFrame->mInfo.mRxInfo.mLqi)); // Link Quality Indicator
SuccessOrExit(mEncoder.WriteUint32(
static_cast<uint32_t>(aAckFrame->mInfo.mRxInfo.mTimestamp / 1000))); // The timestamp milliseconds
SuccessOrExit(mEncoder.WriteUint16(aAckFrame->mInfo.mRxInfo.mTimestamp %
1000)); // The timestamp microseconds, offset to mMsec
SuccessOrExit(mEncoder.CloseStruct());
+19 -16
View File
@@ -612,27 +612,29 @@ otError RadioSpinel::ParseRadioFrame(otRadioFrame &aFrame, const uint8_t *aBuffe
otError error = OT_ERROR_NONE;
uint16_t flags = 0;
int8_t noiseFloor = -128;
uint32_t msec = 0;
uint16_t usec = 0;
spinel_size_t size = OT_RADIO_FRAME_MAX_SIZE;
unsigned int receiveError = 0;
spinel_ssize_t unpacked;
// Timestamp is ms + us.
unpacked = spinel_datatype_unpack_in_place(
aBuffer, aLength,
SPINEL_DATATYPE_DATA_WLEN_S // Frame
SPINEL_DATATYPE_INT8_S // RSSI
SPINEL_DATATYPE_INT8_S // Noise Floor
SPINEL_DATATYPE_UINT16_S // Flags
SPINEL_DATATYPE_STRUCT_S( // PHY-data
SPINEL_DATATYPE_UINT8_S // 802.15.4 channel
SPINEL_DATATYPE_UINT8_S // 802.15.4 LQI
SPINEL_DATATYPE_UINT32_S // Timestamp (ms).
SPINEL_DATATYPE_UINT16_S // Timestamp (us).
) SPINEL_DATATYPE_STRUCT_S( // Vendor-data
SPINEL_DATATYPE_UINT_PACKED_S // Receive error
),
aFrame.mPsdu, &size, &aFrame.mInfo.mRxInfo.mRssi, &noiseFloor, &flags, &aFrame.mChannel,
&aFrame.mInfo.mRxInfo.mLqi, &aFrame.mInfo.mRxInfo.mMsec, &aFrame.mInfo.mRxInfo.mUsec, &receiveError);
unpacked =
spinel_datatype_unpack_in_place(aBuffer, aLength,
SPINEL_DATATYPE_DATA_WLEN_S // Frame
SPINEL_DATATYPE_INT8_S // RSSI
SPINEL_DATATYPE_INT8_S // Noise Floor
SPINEL_DATATYPE_UINT16_S // Flags
SPINEL_DATATYPE_STRUCT_S( // PHY-data
SPINEL_DATATYPE_UINT8_S // 802.15.4 channel
SPINEL_DATATYPE_UINT8_S // 802.15.4 LQI
SPINEL_DATATYPE_UINT32_S // Timestamp (ms).
SPINEL_DATATYPE_UINT16_S // Timestamp (us).
) SPINEL_DATATYPE_STRUCT_S( // Vendor-data
SPINEL_DATATYPE_UINT_PACKED_S // Receive error
),
aFrame.mPsdu, &size, &aFrame.mInfo.mRxInfo.mRssi, &noiseFloor, &flags,
&aFrame.mChannel, &aFrame.mInfo.mRxInfo.mLqi, &msec, &usec, &receiveError);
VerifyOrExit(unpacked > 0, error = OT_ERROR_PARSE);
@@ -640,6 +642,7 @@ otError RadioSpinel::ParseRadioFrame(otRadioFrame &aFrame, const uint8_t *aBuffe
{
aFrame.mLength = static_cast<uint8_t>(size);
aFrame.mInfo.mRxInfo.mTimestamp = msec * 1000 + usec;
aFrame.mInfo.mRxInfo.mAckedWithFramePending = ((flags & SPINEL_MD_FLAG_ACKED_FP) != 0);
}
else if (receiveError < OT_NUM_ERRORS)