mirror of
https://github.com/espressif/openthread.git
synced 2026-09-16 22:20:07 +00:00
ncp-uart: Fix for platforms which call otPlatUartSendDone() reentrantly (#306)
This change makes the `NcpUart` class behave more robustly against various sorts of `otPlatUart` API implementations; specifically those that might call `otPlatUartSendDone()` directly from `otPlatUartSend()`. Without this change, all NCP frames after the first few at startup will be squelched.
This commit is contained in:
committed by
Jonathan Hui
parent
9a1a6206d0
commit
5f9f9e2ce2
+29
-15
@@ -298,6 +298,7 @@ static spinel_status_t ResetReasonToSpinelStatus(otPlatResetReason reason)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
NcpBase::NcpBase():
|
||||
mSendDoneTask(&SendDoneTask, this),
|
||||
mUpdateChangedPropsTask(&UpdateChangedProps, this)
|
||||
{
|
||||
mSupportedChannelMask = kPhySupportedChannelMask;
|
||||
@@ -569,27 +570,40 @@ void NcpBase::HandleReceive(const uint8_t *buf, uint16_t bufLength)
|
||||
}
|
||||
}
|
||||
|
||||
void NcpBase::HandleSendDone()
|
||||
void NcpBase::SendDoneTask(void *context)
|
||||
{
|
||||
if (mSendQueue.GetHead() != NULL)
|
||||
{
|
||||
Message &message(*mSendQueue.GetHead());
|
||||
mSendQueue.Dequeue(message);
|
||||
HandleDatagramFromStack(message);
|
||||
}
|
||||
NcpBase *obj = reinterpret_cast<NcpBase *>(context);
|
||||
obj->SendDoneTask();
|
||||
}
|
||||
|
||||
if (mQueuedGetHeader != 0)
|
||||
{
|
||||
HandleCommandPropertyGet(mQueuedGetHeader, mQueuedGetKey);
|
||||
mQueuedGetHeader = 0;
|
||||
}
|
||||
void NcpBase::SendDoneTask(void)
|
||||
{
|
||||
if (!mSending) {
|
||||
if (mSendQueue.GetHead() != NULL)
|
||||
{
|
||||
Message &message(*mSendQueue.GetHead());
|
||||
mSendQueue.Dequeue(message);
|
||||
HandleDatagramFromStack(message);
|
||||
}
|
||||
|
||||
if (!mSending)
|
||||
{
|
||||
UpdateChangedProps();
|
||||
if (mQueuedGetHeader != 0)
|
||||
{
|
||||
HandleCommandPropertyGet(mQueuedGetHeader, mQueuedGetKey);
|
||||
mQueuedGetHeader = 0;
|
||||
}
|
||||
|
||||
if (!mSending)
|
||||
{
|
||||
UpdateChangedProps();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NcpBase::HandleSendDone(void)
|
||||
{
|
||||
mSendDoneTask.Post();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// MARK: Inbound Command Handlers
|
||||
|
||||
@@ -94,6 +94,12 @@ private:
|
||||
|
||||
void UpdateChangedProps(void);
|
||||
|
||||
/**
|
||||
* Trampoline for SendDoneTask().
|
||||
*/
|
||||
static void SendDoneTask(void *context);
|
||||
|
||||
void SendDoneTask(void);
|
||||
|
||||
static void HandleNetifStateChanged(uint32_t flags, void *context);
|
||||
|
||||
@@ -309,6 +315,8 @@ private:
|
||||
|
||||
spinel_prop_key_t mQueuedGetKey;
|
||||
|
||||
Tasklet mSendDoneTask;
|
||||
|
||||
Tasklet mUpdateChangedPropsTask;
|
||||
|
||||
MessageQueue mSendQueue;
|
||||
|
||||
@@ -145,12 +145,17 @@ NcpUart::OutboundFrameSend(void)
|
||||
|
||||
if (errorCode == kThreadError_None)
|
||||
{
|
||||
// We go ahead and set this to `true` here in case
|
||||
// `otPlatUartSend()` ends up directly calling
|
||||
// `otPlatUartSendDone()`.
|
||||
mSending = true;
|
||||
|
||||
errorCode = otPlatUartSend(mSendFrame.GetBuffer(), mSendFrame.GetLength());
|
||||
}
|
||||
|
||||
if (errorCode == kThreadError_None)
|
||||
if (errorCode != kThreadError_None)
|
||||
{
|
||||
mSending = true;
|
||||
mSending = false;
|
||||
}
|
||||
|
||||
return errorCode;
|
||||
|
||||
Reference in New Issue
Block a user