diff --git a/examples/platforms/nrf528xx/nrf52840/openthread-core-nrf52840-config.h b/examples/platforms/nrf528xx/nrf52840/openthread-core-nrf52840-config.h index 23c10ac95..3150c1637 100644 --- a/examples/platforms/nrf528xx/nrf52840/openthread-core-nrf52840-config.h +++ b/examples/platforms/nrf528xx/nrf52840/openthread-core-nrf52840-config.h @@ -285,7 +285,18 @@ * */ #ifndef OPENTHREAD_CONFIG_CSL_SAMPLE_WINDOW -#define OPENTHREAD_CONFIG_CSL_SAMPLE_WINDOW 30 +#define OPENTHREAD_CONFIG_CSL_SAMPLE_WINDOW 5 +#endif + +/** + * @def OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD + * + * For some reasons, CSL receivers wake up a little later than expected. This variable specifies how much time that + * CSL receiver would wake up earlier than the expected sample window. The time is in unit of 10 symbols. + * + */ +#ifndef OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD +#define OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD 3 #endif /* diff --git a/examples/platforms/nrf528xx/src/radio.c b/examples/platforms/nrf528xx/src/radio.c index 2fda984c8..490ae79a1 100644 --- a/examples/platforms/nrf528xx/src/radio.c +++ b/examples/platforms/nrf528xx/src/radio.c @@ -452,19 +452,34 @@ otError otPlatRadioReceive(otInstance *aInstance, uint8_t aChannel) otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) { - bool result = true; + bool result = true; + otError error = OT_ERROR_NONE; aFrame->mPsdu[-1] = aFrame->mLength; nrf_802154_channel_set(aFrame->mChannel); - if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled) +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + if (aFrame->mInfo.mTxInfo.mTxDelay != 0) { - nrf_802154_transmit_csma_ca_raw(&aFrame->mPsdu[-1]); + if (!nrf_802154_transmit_raw_at(&aFrame->mPsdu[-1], aFrame->mInfo.mTxInfo.mCsmaCaEnabled, + aFrame->mInfo.mTxInfo.mTxDelayBaseTime, aFrame->mInfo.mTxInfo.mTxDelay, + aFrame->mChannel)) + { + error = OT_ERROR_INVALID_STATE; + } } else +#endif { - result = nrf_802154_transmit_raw(&aFrame->mPsdu[-1], false); + if (aFrame->mInfo.mTxInfo.mCsmaCaEnabled) + { + nrf_802154_transmit_csma_ca_raw(&aFrame->mPsdu[-1]); + } + else + { + result = nrf_802154_transmit_raw(&aFrame->mPsdu[-1], false); + } } clearPendingEvents(); @@ -475,7 +490,7 @@ otError otPlatRadioTransmit(otInstance *aInstance, otRadioFrame *aFrame) setPendingEvent(kPendingEventChannelAccessFailure); } - return OT_ERROR_NONE; + return error; } otRadioFrame *otPlatRadioGetTransmitBuffer(otInstance *aInstance) @@ -504,7 +519,7 @@ otRadioCaps otPlatRadioGetCaps(otInstance *aInstance) return (otRadioCaps)(OT_RADIO_CAPS_ENERGY_SCAN | OT_RADIO_CAPS_ACK_TIMEOUT | OT_RADIO_CAPS_CSMA_BACKOFF | #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 - OT_RADIO_CAPS_TRANSMIT_SEC | + OT_RADIO_CAPS_TRANSMIT_SEC | OT_RADIO_CAPS_TRANSMIT_TIMING | #endif OT_RADIO_CAPS_SLEEP_TO_TX); } @@ -997,9 +1012,9 @@ static uint16_t getCslPhase() { uint32_t curTime = otPlatAlarmMicroGetNow(); uint32_t cslPeriodInUs = sCslPeriod * OT_US_PER_TEN_SYMBOLS; - uint32_t diff = ((sCslSampleTime % cslPeriodInUs) - (curTime % cslPeriodInUs) + cslPeriodInUs) % cslPeriodInUs; + uint32_t diff = (cslPeriodInUs - (curTime % cslPeriodInUs) + (sCslSampleTime % cslPeriodInUs)) % cslPeriodInUs; - return (uint16_t)(diff / OT_US_PER_TEN_SYMBOLS); + return (uint16_t)(diff / OT_US_PER_TEN_SYMBOLS + 1); } #endif @@ -1096,6 +1111,13 @@ void nrf_802154_tx_started(const uint8_t *aFrame) bool processSecurity = false; assert(aFrame == sTransmitPsdu); +#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE + if (sCslPeriod > 0) + { + otMacFrameSetCslIe(&sTransmitFrame, (uint16_t)sCslPeriod, getCslPhase()); + } +#endif + // Update IE and secure transmit frame #if OPENTHREAD_CONFIG_TIME_SYNC_ENABLE if (sTransmitFrame.mInfo.mTxInfo.mIeInfo->mTimeIeOffset != 0) @@ -1116,13 +1138,6 @@ void nrf_802154_tx_started(const uint8_t *aFrame) } #endif // OPENTHREAD_CONFIG_TIME_SYNC_ENABLE -#if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - if (sCslPeriod > 0) - { - otMacFrameSetCslIe(&sTransmitFrame, (uint16_t)sCslPeriod, getCslPhase()); - } -#endif - #if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 otEXPECT(otMacFrameIsSecurityEnabled(&sTransmitFrame) && otMacFrameIsKeyIdMode1(&sTransmitFrame) && !sTransmitFrame.mInfo.mTxInfo.mIsSecurityProcessed); diff --git a/include/openthread/instance.h b/include/openthread/instance.h index 73546c8cc..6d7c87a53 100644 --- a/include/openthread/instance.h +++ b/include/openthread/instance.h @@ -53,7 +53,7 @@ extern "C" { * @note This number versions both OpenThread platform and user APIs. * */ -#define OPENTHREAD_API_VERSION (37) +#define OPENTHREAD_API_VERSION (38) /** * @addtogroup api-instance diff --git a/include/openthread/platform/radio.h b/include/openthread/platform/radio.h index 9d41b1b4c..806fdf4d3 100644 --- a/include/openthread/platform/radio.h +++ b/include/openthread/platform/radio.h @@ -228,8 +228,8 @@ typedef struct otRadioFrame { const otMacKey *mAesKey; ///< The key used for AES-CCM frame security. otRadioIeInfo * mIeInfo; ///< The pointer to the Header IE(s) related information. - uint16_t mPeriod; ///< The transmit time period. - uint16_t mPhase; ///< The transmit time phase. + uint32_t mTxDelay; ///< The delay time for this transmission (based on `mTxDelayBaseTime`). + uint32_t mTxDelayBaseTime; ///< The base time for the transmission delay. 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). diff --git a/script/check-size b/script/check-size index 6d3b46448..941b0effe 100755 --- a/script/check-size +++ b/script/check-size @@ -136,7 +136,7 @@ size_nrf52840_version() "BACKBONE_ROUTER=1" "DUA=1" "MLR=1" - # "CSL_RECEIVER=1" not supported on nrf52840 yet + "CSL_RECEIVER=1" ) fi diff --git a/src/core/config/mac.h b/src/core/config/mac.h index 0aeb921b3..643286a44 100644 --- a/src/core/config/mac.h +++ b/src/core/config/mac.h @@ -395,4 +395,15 @@ #define OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE 0 #endif +/** + * @def OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD + * + * For some reasons, CSL receivers wake up a little later than expected. This variable specifies how much time that + * CSL receiver would wake up earlier than the expected sample window. The time is in unit of 10 symbols. + * + */ +#ifndef OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD +#define OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD 1 +#endif + #endif // CONFIG_MAC_H_ diff --git a/src/core/mac/mac.cpp b/src/core/mac/mac.cpp index 0e630592c..64df219fd 100644 --- a/src/core/mac/mac.cpp +++ b/src/core/mac/mac.cpp @@ -1086,8 +1086,10 @@ void Mac::BeginTransmit(void) sendFrame.SetIsARetransmission(false); sendFrame.SetIsSecurityProcessed(false); #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - sendFrame.SetTxPeriod(0); + sendFrame.SetTxDelay(0); + sendFrame.SetTxDelayBaseTime(0); #endif + sendFrame.SetCsmaCaEnabled(true); // Set to true by default, only set to `false` for CSL transmission switch (mOperation) { @@ -2348,10 +2350,10 @@ void Mac::ProcessCsl(const RxFrame &aFrame, const Address &aSrcAddr) child->SetCslPeriod(csl->GetPeriod()); // Use ceiling to ensure the the time diff will be within kUsPerTenSymbols - child->SetCslPhase(((aFrame.GetTimestamp() + kUsPerTenSymbols - 1) / kUsPerTenSymbols + csl->GetPhase()) % - csl->GetPeriod()); + child->SetCslPhase(csl->GetPhase()); child->SetCslSynchronized(true); child->SetCslLastHeard(TimerMilli::GetNow()); + child->SetLastRxTimestamp(aFrame.GetTimestamp()); otLogDebgMac("Timestamp=%u Sequence=%u CslPeriod=%hu CslPhase=%hu TransmitPhase=%hu", static_cast(aFrame.GetTimestamp()), aFrame.GetSequence(), csl->GetPeriod(), csl->GetPhase(), child->GetCslPhase()); diff --git a/src/core/mac/mac_frame.hpp b/src/core/mac/mac_frame.hpp index 8bae5affa..1063be592 100644 --- a/src/core/mac/mac_frame.hpp +++ b/src/core/mac/mac_frame.hpp @@ -1310,9 +1310,22 @@ public: */ otError GenerateEnhAck(const RxFrame &aFrame, bool aIsFramePending, const uint8_t *aIeData, uint8_t aIeLength); -#if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - void SetTxPhase(uint16_t aPhase) { mInfo.mTxInfo.mPhase = aPhase; } - void SetTxPeriod(uint16_t aPeriod) { mInfo.mTxInfo.mPeriod = aPeriod; } +#if OPENTHREAD_CONFIG_THREAD_VERSION >= OT_THREAD_VERSION_1_2 + /** + * Set TX delay field for the frame. + * + * @param[in] aTxDelay The delay time for the TX frame. + * + */ + void SetTxDelay(uint32_t aTxDelay) { mInfo.mTxInfo.mTxDelay = aTxDelay; } + + /** + * Set TX delay base time field for the frame. + * + * @param[in] aTxDelayBaseTime The delay base time for the TX frame. + * + */ + void SetTxDelayBaseTime(uint32_t aTxDelayBaseTime) { mInfo.mTxInfo.mTxDelayBaseTime = aTxDelayBaseTime; } #endif }; diff --git a/src/core/mac/sub_mac.cpp b/src/core/mac/sub_mac.cpp index 4dedb14a9..0bdf01c9c 100644 --- a/src/core/mac/sub_mac.cpp +++ b/src/core/mac/sub_mac.cpp @@ -44,6 +44,7 @@ #include "common/locator-getters.hpp" #include "common/logging.hpp" #include "common/random.hpp" +#include "common/time.hpp" namespace ot { namespace Mac { @@ -349,25 +350,19 @@ void SubMac::StartCsmaBackoff(void) uint32_t backoffExponent = kMinBE + mTransmitRetries + mCsmaBackoffs; #if OPENTHREAD_CONFIG_MAC_CSL_TRANSMITTER_ENABLE - if (mTransmitFrame.mInfo.mTxInfo.mPeriod != 0) + if (mTransmitFrame.mInfo.mTxInfo.mTxDelay != 0) { SetState(kStateCslTransmit); if (ShouldHandleTransmitTargetTime()) { - uint32_t phaseNow = - (otPlatRadioGetNow(&GetInstance()) / kUsPerTenSymbols) % mTransmitFrame.mInfo.mTxInfo.mPeriod; - uint32_t phaseDesired = mTransmitFrame.mInfo.mTxInfo.mPhase; - - if (phaseNow < phaseDesired) + if (otPlatRadioGetNow(&GetInstance()) < + mTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime + mTransmitFrame.mInfo.mTxInfo.mTxDelay) { - mTimer.Start((phaseDesired - phaseNow) * kUsPerTenSymbols); + mTimer.StartAt(Time(mTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime), + mTransmitFrame.mInfo.mTxInfo.mTxDelay); } - else if (phaseNow > phaseDesired) - { - mTimer.Start((phaseDesired + mTransmitFrame.mInfo.mTxInfo.mPeriod - phaseNow) * kUsPerTenSymbols); - } - else + else // Transmit without delay { BeginTransmit(); } @@ -423,8 +418,6 @@ void SubMac::BeginTransmit(void) VerifyOrExit(mState == kStateCsmaBackoff); #endif - mTransmitFrame.SetCsmaCaEnabled(mTransmitFrame.mInfo.mTxInfo.mPeriod == 0); - if ((mRadioCaps & OT_RADIO_CAPS_SLEEP_TO_TX) == 0) { error = Get().Receive(mTransmitFrame.GetChannel()); @@ -439,6 +432,13 @@ void SubMac::BeginTransmit(void) } error = Get().Transmit(mTransmitFrame); + if (error == OT_ERROR_INVALID_STATE && mTransmitFrame.mInfo.mTxInfo.mTxDelay > 0) + { + // Platform `transmit_at` fails and we send the frame directly. + mTransmitFrame.mInfo.mTxInfo.mTxDelay = 0; + mTransmitFrame.mInfo.mTxInfo.mTxDelayBaseTime = 0; + error = Get().Transmit(mTransmitFrame); + } OT_ASSERT(error == OT_ERROR_NONE); exit: @@ -997,7 +997,7 @@ void SubMac::HandleCslTimer(void) case kCslSample: mCslState = kCslSleep; // kUsPerTenSymbols: computing CSL Phase using floor division. - mCslTimer.StartAt(mCslSampleTime, mCslPeriod * kUsPerTenSymbols - kUsPerTenSymbols); + mCslTimer.StartAt(mCslSampleTime, (mCslPeriod - kCslReceiveTimeAhead) * kUsPerTenSymbols); if (mState == kStateCslSample) { #if !OPENTHREAD_CONFIG_MAC_CSL_DEBUG_ENABLE diff --git a/src/core/mac/sub_mac.hpp b/src/core/mac/sub_mac.hpp index a50e23a03..f3c641e93 100644 --- a/src/core/mac/sub_mac.hpp +++ b/src/core/mac/sub_mac.hpp @@ -539,12 +539,13 @@ private: }; #if OPENTHREAD_CONFIG_MAC_CSL_RECEIVER_ENABLE - /** - * The SSED sample window in units of 10 symbols. - * - */ enum : uint32_t{ - kCslSampleWindow = OPENTHREAD_CONFIG_CSL_SAMPLE_WINDOW * kUsPerTenSymbols, + kCslSampleWindow = + OPENTHREAD_CONFIG_CSL_SAMPLE_WINDOW * kUsPerTenSymbols, ///< The SSED sample window in units of 10 symbols. + kCslReceiveTimeAhead = + OPENTHREAD_CONFIG_CSL_RECEIVE_TIME_AHEAD, ///< CSL receivers would wake up `kCslReceiveTimeAhead` earlier + ///< than expected sample window. The time is in unit of 10 + ///< symbols. }; /** diff --git a/src/core/thread/csl_tx_scheduler.cpp b/src/core/thread/csl_tx_scheduler.cpp index 273932571..6516f064f 100644 --- a/src/core/thread/csl_tx_scheduler.cpp +++ b/src/core/thread/csl_tx_scheduler.cpp @@ -128,6 +128,7 @@ void CslTxScheduler::RescheduleCslTx(void) for (Child &child : Get().Iterate(Child::kInStateAnyExceptInvalid)) { uint32_t delay; + uint32_t cslTxDelay; if (!child.IsCslSynchronized() || child.GetIndirectMessageCount() == 0 || child.GetCslTxAttempts() >= kMaxCslTriggeredTxAttempts) @@ -135,7 +136,8 @@ void CslTxScheduler::RescheduleCslTx(void) continue; } - delay = GetNextCslTransmissionDelay(child, radioNow); + delay = GetNextCslTransmissionDelay(child, radioNow, cslTxDelay); + if (delay < minDelayTime) { minDelayTime = delay; @@ -151,28 +153,25 @@ void CslTxScheduler::RescheduleCslTx(void) mCslTxChild = bestChild; } -uint32_t CslTxScheduler::GetNextCslTransmissionDelay(const Child &aChild, uint64_t aRadioNow) const +uint32_t CslTxScheduler::GetNextCslTransmissionDelay(const Child &aChild, + uint64_t aRadioNow, + uint32_t & aDelayFromLastRx) const { - uint32_t delay; - uint16_t period_offset = (aRadioNow / kUsPerTenSymbols) % aChild.GetCslPeriod(); + uint32_t periodInUs = aChild.GetCslPeriod() * kUsPerTenSymbols; + uint64_t firstTxWindow = aChild.GetLastRxTimestamp() + aChild.GetCslPhase() * kUsPerTenSymbols; + uint64_t nextTxWindow = aRadioNow - (aRadioNow % periodInUs) + (firstTxWindow % periodInUs); - if (aChild.GetCslPhase() > period_offset + mCslFrameRequestAhead) - { - delay = static_cast(aChild.GetCslPhase() - period_offset - mCslFrameRequestAhead) * kUsPerTenSymbols; - } - else - { - delay = static_cast(aChild.GetCslPeriod() + aChild.GetCslPhase() - period_offset - - mCslFrameRequestAhead) * - kUsPerTenSymbols; - } + while (aRadioNow + mCslFrameRequestAhead >= nextTxWindow) nextTxWindow += periodInUs; - return delay; + aDelayFromLastRx = static_cast(nextTxWindow - aChild.GetLastRxTimestamp()); + + return static_cast(nextTxWindow - aRadioNow); } otError CslTxScheduler::HandleFrameRequest(Mac::TxFrame &aFrame) { - otError error = OT_ERROR_NONE; + otError error = OT_ERROR_NONE; + uint32_t txDelay; VerifyOrExit(mCslTxChild != nullptr, error = OT_ERROR_ABORT); @@ -202,8 +201,12 @@ otError CslTxScheduler::HandleFrameRequest(Mac::TxFrame &aFrame) aFrame.SetChannel(mCslTxChild->GetCslChannel() == 0 ? Get().GetPanChannel() : mCslTxChild->GetCslChannel()); - aFrame.SetTxPhase(mCslTxChild->GetCslPhase()); - aFrame.SetTxPeriod(mCslTxChild->GetCslPeriod()); + + GetNextCslTransmissionDelay(*mCslTxChild, otPlatRadioGetNow(&GetInstance()), txDelay); + aFrame.SetTxDelay(txDelay); + aFrame.SetTxDelayBaseTime( + static_cast(mCslTxChild->GetLastRxTimestamp())); // Only LSB part of the time is required. + aFrame.SetCsmaCaEnabled(false); exit: return error; diff --git a/src/core/thread/csl_tx_scheduler.hpp b/src/core/thread/csl_tx_scheduler.hpp index be48b4cae..584018d98 100644 --- a/src/core/thread/csl_tx_scheduler.hpp +++ b/src/core/thread/csl_tx_scheduler.hpp @@ -101,6 +101,9 @@ public: TimeMilli GetCslLastHeard(void) const { return mCslLastHeard; } void SetCslLastHeard(TimeMilli aCslLastHeard) { mCslLastHeard = aCslLastHeard; } + uint64_t GetLastRxTimestamp(void) const { return mLastRxTimstamp; } + void SetLastRxTimestamp(uint64_t aLastRxTimestamp) { mLastRxTimstamp = aLastRxTimestamp; } + private: uint8_t mCslTxAttempts : 7; ///< Number of CSL triggered tx attempts. bool mCslSynchronized : 1; ///< Indicates whether or not the child is CSL synchronized. @@ -109,6 +112,7 @@ public: uint16_t mCslPeriod; ///< CSL sampled listening period in units of 10 symbols (160 microseconds). uint16_t mCslPhase; ///< The time when the next CSL sample will start. TimeMilli mCslLastHeard; ///< Time when last frame containing CSL IE was heard. + uint64_t mLastRxTimstamp; ///< Time when last frame containing CSL IE was received, in microseconds. static_assert(kMaxCslTriggeredTxAttempts < (1 << 7), "mCslTxAttempts cannot fit max!"); }; @@ -190,7 +194,7 @@ private: void InitFrameRequestAhead(void); void RescheduleCslTx(void); - uint32_t GetNextCslTransmissionDelay(const Child &aChild, uint64_t aRadioNow) const; + uint32_t GetNextCslTransmissionDelay(const Child &aChild, uint64_t aRadioNow, uint32_t &aDelayFromLastRx) const; // Callbacks from `Mac` otError HandleFrameRequest(Mac::TxFrame &aFrame); diff --git a/src/lib/spinel/radio_spinel_impl.hpp b/src/lib/spinel/radio_spinel_impl.hpp index 3fe28e18d..e0fd31aaf 100644 --- a/src/lib/spinel/radio_spinel_impl.hpp +++ b/src/lib/spinel/radio_spinel_impl.hpp @@ -1585,13 +1585,13 @@ otError RadioSpinel::Transmit(otRadioFrame &a SPINEL_DATATYPE_BOOL_S // CsmaCaEnabled SPINEL_DATATYPE_BOOL_S // IsARetx SPINEL_DATATYPE_BOOL_S // SkipAes - SPINEL_DATATYPE_UINT16_S // Period - SPINEL_DATATYPE_UINT16_S, // Phase + SPINEL_DATATYPE_UINT32_S // TxDelay + SPINEL_DATATYPE_UINT32_S, // TxDelayBaseTime mTransmitFrame->mPsdu, mTransmitFrame->mLength, mTransmitFrame->mChannel, mTransmitFrame->mInfo.mTxInfo.mMaxCsmaBackoffs, mTransmitFrame->mInfo.mTxInfo.mMaxFrameRetries, mTransmitFrame->mInfo.mTxInfo.mCsmaCaEnabled, mTransmitFrame->mInfo.mTxInfo.mIsARetx, - mTransmitFrame->mInfo.mTxInfo.mIsSecurityProcessed, mTransmitFrame->mInfo.mTxInfo.mPeriod, - mTransmitFrame->mInfo.mTxInfo.mPhase); + mTransmitFrame->mInfo.mTxInfo.mIsSecurityProcessed, mTransmitFrame->mInfo.mTxInfo.mTxDelay, + mTransmitFrame->mInfo.mTxInfo.mTxDelayBaseTime); if (error == OT_ERROR_NONE) { diff --git a/src/ncp/ncp_base_radio.cpp b/src/ncp/ncp_base_radio.cpp index 25a349ec8..6c00fd513 100644 --- a/src/ncp/ncp_base_radio.cpp +++ b/src/ncp/ncp_base_radio.cpp @@ -398,8 +398,8 @@ otError NcpBase::DecodeStreamRawTxRequest(otRadioFrame &aFrame) aFrame.mInfo.mTxInfo.mCsmaCaEnabled = true; aFrame.mInfo.mTxInfo.mIsARetx = false; aFrame.mInfo.mTxInfo.mIsSecurityProcessed = false; - aFrame.mInfo.mTxInfo.mPeriod = 0; - aFrame.mInfo.mTxInfo.mPhase = 0; + aFrame.mInfo.mTxInfo.mTxDelay = 0; + aFrame.mInfo.mTxInfo.mTxDelayBaseTime = 0; // All the next parameters are optional. Note that even if the // decoder fails to parse any of optional parameters we still want to @@ -411,8 +411,8 @@ otError NcpBase::DecodeStreamRawTxRequest(otRadioFrame &aFrame) SuccessOrExit(mDecoder.ReadBool(csmaEnable)); SuccessOrExit(mDecoder.ReadBool(isARetx)); SuccessOrExit(mDecoder.ReadBool(isSecurityProcessed)); - SuccessOrExit(mDecoder.ReadUint16(aFrame.mInfo.mTxInfo.mPeriod)); - SuccessOrExit(mDecoder.ReadUint16(aFrame.mInfo.mTxInfo.mPhase)); + SuccessOrExit(mDecoder.ReadUint32(aFrame.mInfo.mTxInfo.mTxDelay)); + SuccessOrExit(mDecoder.ReadUint32(aFrame.mInfo.mTxInfo.mTxDelayBaseTime)); aFrame.mInfo.mTxInfo.mCsmaCaEnabled = csmaEnable; aFrame.mInfo.mTxInfo.mIsARetx = isARetx; aFrame.mInfo.mTxInfo.mIsSecurityProcessed = isSecurityProcessed;