diff --git a/src/ncp/ncp_base.cpp b/src/ncp/ncp_base.cpp index f08438e91..3be20af31 100644 --- a/src/ncp/ncp_base.cpp +++ b/src/ncp/ncp_base.cpp @@ -534,6 +534,7 @@ NcpBase *NcpBase::sNcpInstance = NULL; NcpBase::NcpBase(otInstance *aInstance): mInstance(aInstance), mTxFrameBuffer(mTxBuffer, sizeof(mTxBuffer)), + mHostPowerStateInProgress(false), mLastStatus(SPINEL_STATUS_OK), mSupportedChannelMask(OT_RADIO_SUPPORTED_CHANNELS), mChannelMask(OT_RADIO_SUPPORTED_CHANNELS), @@ -545,7 +546,6 @@ NcpBase::NcpBase(otInstance *aInstance): mThreadChangedFlags(0), mChangedPropsSet(), mHostPowerState(SPINEL_HOST_POWER_STATE_ONLINE), - mHostPowerStateInProgress(false), mHostPowerReplyFrameTag(NcpFrameBuffer::kInvalidTag), mHostPowerStateHeader(0), #if OPENTHREAD_CONFIG_NCP_ENABLE_PEEK_POKE diff --git a/src/ncp/ncp_base.hpp b/src/ncp/ncp_base.hpp index 6983b84a0..ea9342101 100644 --- a/src/ncp/ncp_base.hpp +++ b/src/ncp/ncp_base.hpp @@ -639,6 +639,7 @@ protected: static uint8_t LinkFlagsToFlagByte(bool aRxOnWhenIdle, bool aSecureDataRequests, bool aDeviceType, bool aNetworkData); otInstance *mInstance; NcpFrameBuffer mTxFrameBuffer; + bool mHostPowerStateInProgress; private: enum @@ -669,7 +670,6 @@ private: uint32_t mChangedFlags; bool mShouldSignalEndOfScan; spinel_host_power_state_t mHostPowerState; - bool mHostPowerStateInProgress; NcpFrameBuffer::FrameTag mHostPowerReplyFrameTag; uint8_t mHostPowerStateHeader; diff --git a/src/ncp/ncp_uart.cpp b/src/ncp/ncp_uart.cpp index e75c596bc..bdcd4bf8b 100644 --- a/src/ncp/ncp_uart.cpp +++ b/src/ncp/ncp_uart.cpp @@ -99,6 +99,7 @@ NcpUart::NcpUart(otInstance *aInstance): mUartBuffer(), mState(kStartingFrame), mByte(0), + mUartSendImmediate(false), mUartSendTask(*aInstance, EncodeAndSendToUart, this) { mTxFrameBuffer.SetFrameAddedCallback(HandleFrameAddedToNcpBuffer, this); @@ -136,6 +137,7 @@ void NcpUart::EncodeAndSendToUart(Tasklet &aTasklet) void NcpUart::EncodeAndSendToUart(void) { uint16_t len; + bool prevHostPowerState; while (!mTxFrameBuffer.IsEmpty() || (mState == kFinalizingFrame)) { @@ -164,8 +166,22 @@ void NcpUart::EncodeAndSendToUart(void) SuccessOrExit(mFrameEncoder.Encode(mByte, mUartBuffer)); } + // track the change of mHostPowerStateInProgress by the + // call to OutFrameRemove. + prevHostPowerState = mHostPowerStateInProgress; + mTxFrameBuffer.OutFrameRemove(); + if (prevHostPowerState && !mHostPowerStateInProgress) + { + // If mHostPowerStateInProgress transitioned from true -> false + // in the call to OutFrameRemove, then the frame should be sent + // out the UART without attempting to push any new frames into + // the mUartBuffer. This is necessary to avoid prematurely calling + // otPlatWakeHost. + mUartSendImmediate = true; + } + mState = kFinalizingFrame; // fall through @@ -175,6 +191,13 @@ void NcpUart::EncodeAndSendToUart(void) SuccessOrExit(mFrameEncoder.Finalize(mUartBuffer)); mState = kStartingFrame; + + if (mUartSendImmediate) + { + // clear state and break; + mUartSendImmediate = false; + break; + } } } diff --git a/src/ncp/ncp_uart.hpp b/src/ncp/ncp_uart.hpp index 0bced9ce6..ff061bb59 100644 --- a/src/ncp/ncp_uart.hpp +++ b/src/ncp/ncp_uart.hpp @@ -114,6 +114,7 @@ private: UartTxState mState; uint8_t mByte; uint8_t mRxBuffer[kRxBufferSize]; + bool mUartSendImmediate; Tasklet mUartSendTask; };