示例#1
0
void NcpSpi::PrepareNextSpiSendFrame(void)
{
    otError  error = OT_ERROR_NONE;
    uint16_t frameLength;
    uint16_t readLength;
    SpiFrame sendFrame(mSendFrame);

    VerifyOrExit(!mTxFrameBuffer.IsEmpty());

    if (ShouldWakeHost())
    {
        otPlatWakeHost();
    }

    SuccessOrExit(error = mTxFrameBuffer.OutFrameBegin());

    frameLength = mTxFrameBuffer.OutFrameGetLength();
    assert(frameLength <= kSpiBufferSize - kSpiHeaderSize);

    // The "accept length" in `mSendFrame` is already updated based
    // on current state of receive. It is changed either from the
    // `SpiTransactionComplete()` callback or from `HandleRxFrame()`.

    readLength = mTxFrameBuffer.OutFrameRead(frameLength, sendFrame.GetData());
    assert(readLength == frameLength);

    sendFrame.SetHeaderDataLen(frameLength);
    mSendFrameLength = frameLength + kSpiHeaderSize;

    mTxState = kTxStateSending;

    // Prepare new transaction by using `mSendFrame` as the output
    // frame while keeping the input frame unchanged.

    error = otPlatSpiSlavePrepareTransaction(mSendFrame, mSendFrameLength, NULL, 0, /* aRequestTrans */ true);

    if (error == OT_ERROR_BUSY)
    {
        // Being busy is OK. We will get the transaction set up
        // properly when the current transaction is completed.
        error = OT_ERROR_NONE;
    }

    if (error != OT_ERROR_NONE)
    {
        mTxState = kTxStateIdle;
        mPrepareTxFrameTask.Post();
        ExitNow();
    }

    mTxFrameBuffer.OutFrameRemove();

exit:
    return;
}
示例#2
0
// This method encodes a frame from the tx frame buffer (mTxFrameBuffer) into the uart buffer and sends it over uart.
// If the uart buffer gets full, it sends the current encoded portion. This method remembers current state, so on
// sub-sequent calls, it restarts encoding the bytes from where it left of in the frame .
void NcpUart::EncodeAndSendToUart(void)
{
    uint16_t len;
    bool prevHostPowerState;
#if OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER
    NcpFrameBufferEncrypterReader &txFrameBuffer = mTxFrameBufferEncrypterReader;
#else
    NcpFrameBuffer &txFrameBuffer = mTxFrameBuffer;
#endif // OPENTHREAD_ENABLE_NCP_SPINEL_ENCRYPTER

    while (!txFrameBuffer.IsEmpty() || (mState == kFinalizingFrame))
    {
        switch (mState)
        {
        case kStartingFrame:

            if (super_t::ShouldWakeHost())
            {
                otPlatWakeHost();
            }

            VerifyOrExit(super_t::ShouldDeferHostSend() == false);
            SuccessOrExit(mFrameEncoder.Init(mUartBuffer));

            txFrameBuffer.OutFrameBegin();

            mState = kEncodingFrame;

            while (!txFrameBuffer.OutFrameHasEnded())
            {
                mByte = txFrameBuffer.OutFrameReadByte();

        case kEncodingFrame:

                SuccessOrExit(mFrameEncoder.Encode(mByte, mUartBuffer));
            }

            // track the change of mHostPowerStateInProgress by the
            // call to OutFrameRemove.
            prevHostPowerState = mHostPowerStateInProgress;

            txFrameBuffer.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

        case kFinalizingFrame:

            SuccessOrExit(mFrameEncoder.Finalize(mUartBuffer));

            mState = kStartingFrame;

            if (mUartSendImmediate)
            {
                // clear state and break;
                mUartSendImmediate = false;
                break;
            }
        }
    }

exit:
    len = mUartBuffer.GetLength();

    if (len > 0)
    {
        if (otPlatUartSend(mUartBuffer.GetBuffer(), len) != OT_ERROR_NONE)
        {
            assert(false);
        }
    }
}