From d041699ad36d00c7713f37db30597b6249abd2d3 Mon Sep 17 00:00:00 2001 From: Yakun Xu Date: Tue, 30 Jul 2019 13:52:37 +0800 Subject: [PATCH] [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. --- .../openthread-core-cc1352-config-check.h | 4 - examples/platforms/cc1352/radio.c | 13 +- .../openthread-core-cc2538-config-check.h | 4 - examples/platforms/cc2538/radio.c | 10 +- .../openthread-core-cc2650-config-check.h | 4 - examples/platforms/cc2650/radio.c | 8 +- .../openthread-core-cc2652-config-check.h | 4 - examples/platforms/cc2652/radio.c | 8 +- .../openthread-core-kw41z-config-check.h | 4 - examples/platforms/kw41z/radio.c | 9 +- examples/platforms/nrf52811/radio.c | 27 +- examples/platforms/nrf52840/radio.c | 29 +- examples/platforms/posix/alarm.c | 2 +- examples/platforms/posix/radio.c | 27 +- examples/platforms/posix/sim/alarm-sim.c | 2 +- .../openthread-core-samr21-config-check.h | 4 - examples/platforms/samr21/radio.c | 9 +- include/openthread/platform/radio.h | 36 +-- src/core/mac/mac.cpp | 32 +- src/core/mac/mac_frame.cpp | 28 +- src/core/mac/mac_frame.hpp | 284 +++++++++--------- src/core/thread/mesh_forwarder.cpp | 7 +- src/ncp/ncp_base_radio.cpp | 27 +- src/posix/platform/radio_spinel.cpp | 35 ++- 24 files changed, 300 insertions(+), 317 deletions(-) diff --git a/examples/platforms/cc1352/openthread-core-cc1352-config-check.h b/examples/platforms/cc1352/openthread-core-cc1352-config-check.h index eac283004..73fca4dae 100644 --- a/examples/platforms/cc1352/openthread-core-cc1352-config-check.h +++ b/examples/platforms/cc1352/openthread-core-cc1352-config-check.h @@ -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 diff --git a/examples/platforms/cc1352/radio.c b/examples/platforms/cc1352/radio.c index 6b4d8965d..305125b0e 100644 --- a/examples/platforms/cc1352/radio.c +++ b/examples/platforms/cc1352/radio.c @@ -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]); diff --git a/examples/platforms/cc2538/openthread-core-cc2538-config-check.h b/examples/platforms/cc2538/openthread-core-cc2538-config-check.h index c1d45924d..93788b121 100644 --- a/examples/platforms/cc2538/openthread-core-cc2538-config-check.h +++ b/examples/platforms/cc2538/openthread-core-cc2538-config-check.h @@ -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 diff --git a/examples/platforms/cc2538/radio.c b/examples/platforms/cc2538/radio.c index 62367ee0e..5da1e63d4 100644 --- a/examples/platforms/cc2538/radio.c +++ b/examples/platforms/cc2538/radio.c @@ -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 diff --git a/examples/platforms/cc2650/openthread-core-cc2650-config-check.h b/examples/platforms/cc2650/openthread-core-cc2650-config-check.h index 1aa48b355..bf7393a6d 100644 --- a/examples/platforms/cc2650/openthread-core-cc2650-config-check.h +++ b/examples/platforms/cc2650/openthread-core-cc2650-config-check.h @@ -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 diff --git a/examples/platforms/cc2650/radio.c b/examples/platforms/cc2650/radio.c index 43e411d2e..de2fa1e9a 100644 --- a/examples/platforms/cc2650/radio.c +++ b/examples/platforms/cc2650/radio.c @@ -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; diff --git a/examples/platforms/cc2652/openthread-core-cc2652-config-check.h b/examples/platforms/cc2652/openthread-core-cc2652-config-check.h index 662d1ee14..347af7779 100644 --- a/examples/platforms/cc2652/openthread-core-cc2652-config-check.h +++ b/examples/platforms/cc2652/openthread-core-cc2652-config-check.h @@ -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 diff --git a/examples/platforms/cc2652/radio.c b/examples/platforms/cc2652/radio.c index 08aabefa0..dab3d19e8 100644 --- a/examples/platforms/cc2652/radio.c +++ b/examples/platforms/cc2652/radio.c @@ -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; diff --git a/examples/platforms/kw41z/openthread-core-kw41z-config-check.h b/examples/platforms/kw41z/openthread-core-kw41z-config-check.h index 237b2fb3c..1f7540c70 100644 --- a/examples/platforms/kw41z/openthread-core-kw41z-config-check.h +++ b/examples/platforms/kw41z/openthread-core-kw41z-config-check.h @@ -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 diff --git a/examples/platforms/kw41z/radio.c b/examples/platforms/kw41z/radio.c index 9a5d6f7bc..6d539ef8f 100644 --- a/examples/platforms/kw41z/radio.c +++ b/examples/platforms/kw41z/radio.c @@ -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; diff --git a/examples/platforms/nrf52811/radio.c b/examples/platforms/nrf52811/radio.c index a0ba790e9..01c47b70f 100644 --- a/examples/platforms/nrf52811/radio.c +++ b/examples/platforms/nrf52811/radio.c @@ -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++) diff --git a/examples/platforms/nrf52840/radio.c b/examples/platforms/nrf52840/radio.c index 518cf79a0..0f3d5f0f2 100644 --- a/examples/platforms/nrf52840/radio.c +++ b/examples/platforms/nrf52840/radio.c @@ -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++) diff --git a/examples/platforms/posix/alarm.c b/examples/platforms/posix/alarm.c index 28b1565b6..0a5f2a349 100644 --- a/examples/platforms/posix/alarm.c +++ b/examples/platforms/posix/alarm.c @@ -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; diff --git a/examples/platforms/posix/radio.c b/examples/platforms/posix/radio.c index b42755826..11e63e8db 100644 --- a/examples/platforms/posix/radio.c +++ b/examples/platforms/posix/radio.c @@ -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++) diff --git a/examples/platforms/posix/sim/alarm-sim.c b/examples/platforms/posix/sim/alarm-sim.c index fe309d01e..cbe179afa 100644 --- a/examples/platforms/posix/sim/alarm-sim.c +++ b/examples/platforms/posix/sim/alarm-sim.c @@ -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; diff --git a/examples/platforms/samr21/openthread-core-samr21-config-check.h b/examples/platforms/samr21/openthread-core-samr21-config-check.h index 372a5f734..3b991e014 100644 --- a/examples/platforms/samr21/openthread-core-samr21-config-check.h +++ b/examples/platforms/samr21/openthread-core-samr21-config-check.h @@ -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 diff --git a/examples/platforms/samr21/radio.c b/examples/platforms/samr21/radio.c index 621b26301..dc09f27f6 100644 --- a/examples/platforms/samr21/radio.c +++ b/examples/platforms/samr21/radio.c @@ -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. diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index b6a1902ec..618781892 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -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. diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 3fc56f0b3..bff64ff8b 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -1659,17 +1659,6 @@ void Mac::HandleReceivedFrame(Frame *aFrame, otError aError) Get().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(aFrame.GetTimeIe()); - - VerifyOrExit(timeIe != NULL); - - aFrame.SetNetworkTimeOffset(static_cast(timeIe->GetTime()) - static_cast(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(aFrame.GetTimeIe()); VerifyOrExit(cur != NULL); cur += sizeof(VendorIeHeader); diff --git a/src/core/mac/mac_frame.cpp b/src/core/mac/mac_frame.cpp index 1553cc5d6..98d79d9a1 100644 --- a/src/core/mac/mac_frame.cpp +++ b/src/core/mac/mac_frame.cpp @@ -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(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 diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp index d40e88b7e..8f9a6ca81 100644 --- a/src/core/mac/mac_frame.hpp +++ b/src/core/mac/mac_frame.hpp @@ -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(const_cast(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(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(const_cast(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 - /** * @} * diff --git a/src/core/thread/mesh_forwarder.cpp b/src/core/thread/mesh_forwarder.cpp index 83cfc58b1..efb65ccc4 100644 --- a/src/core/thread/mesh_forwarder.cpp +++ b/src/core/thread/mesh_forwarder.cpp @@ -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(); diff --git a/src/ncp/ncp_base_radio.cpp b/src/ncp/ncp_base_radio.cpp index 46b5d4b1e..e58f1d5f9 100644 --- a/src/ncp/ncp_base_radio.cpp +++ b/src/ncp/ncp_base_radio.cpp @@ -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(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(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()); diff --git a/src/posix/platform/radio_spinel.cpp b/src/posix/platform/radio_spinel.cpp index 79fb6cd02..b69b30f69 100644 --- a/src/posix/platform/radio_spinel.cpp +++ b/src/posix/platform/radio_spinel.cpp @@ -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(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)