mirror of
https://github.com/espressif/openthread.git
synced 2026-08-09 12:17:47 +00:00
[ncp] fix logic surrounding the call to otPlatWakeHost (#2208)
Due to the nature of how frames can be processed in ncp_uart.cpp, it is possible for a call to otPlatWakeHost to execute before the SPINEL_PROP_HOST_POWER_STATE response message has been sent to the host. This order is unexpected and not sufficient for proper operation. Instead the call to otPlatWakeHost should only occur after the SPINEL_PROP_HOST_POWER_STATE response message has been sent and only when a new subsequent message has been made ready for delivery over the UART. To solve this, the change below detects when the SPINEL_PROP_HOST_POWER_STATE response message has been completely written to mUartBuffer and immediately calls otPlatUartSend() when this condition is met. With this change the expected order of operations can be maintained.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -114,6 +114,7 @@ private:
|
||||
UartTxState mState;
|
||||
uint8_t mByte;
|
||||
uint8_t mRxBuffer[kRxBufferSize];
|
||||
bool mUartSendImmediate;
|
||||
Tasklet mUartSendTask;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user