[ncp-spi] improve callback implementation, change code style format (#2734)

This commit makes the following changes in `NcpSpi` class:

- It adds a new class `SpiFrame` which provides helper methods to
  parse and update the header fields in the header of an SPI  frame.
- It simplifies/enhances the `SpiTransactionComplete()` callback
  implementation by combining the parsing of input/output frame
  headers with the rx/tx frame processing.
- It adds a check for correct pattern bits in a received frame
  flag byte (frames with incorrect pattern bits are ignored).
- Code format is changed to follow the "pretty" style.
- Fixes a rare issue with a possible incorrect accept length on
  the first SPI transaction after NCP reset.
This commit is contained in:
Abtin Keshavarzian
2018-06-11 08:59:25 -07:00
committed by Jonathan Hui
parent 2f9bd174d0
commit 90b160ccfa
2 changed files with 273 additions and 163 deletions
+119 -135
View File
@@ -33,8 +33,8 @@
#include "ncp_spi.hpp"
#include <openthread/ncp.h>
#include <openthread/platform/spi-slave.h>
#include <openthread/platform/misc.h>
#include <openthread/platform/spi-slave.h>
#include "openthread-core-config.h"
#include "common/code_utils.hpp"
@@ -43,11 +43,6 @@
#include "common/new.hpp"
#include "net/ip6.hpp"
#define SPI_RESET_FLAG 0x80
#define SPI_CRC_FLAG 0x40
#define SPI_PATTERN_VALUE 0x02
#define SPI_PATTERN_MASK 0x03
#if OPENTHREAD_ENABLE_NCP_SPI
namespace ot {
@@ -59,10 +54,10 @@ static otDEFINE_ALIGNED_VAR(sNcpRaw, sizeof(NcpSpi), uint64_t);
extern "C" void otNcpInit(otInstance *aInstance)
{
NcpSpi *ncpSpi = NULL;
NcpSpi * ncpSpi = NULL;
Instance *instance = static_cast<Instance *>(aInstance);
ncpSpi = new(&sNcpRaw) NcpSpi(instance);
ncpSpi = new (&sNcpRaw) NcpSpi(instance);
if (ncpSpi == NULL || ncpSpi != NcpBase::GetNcpInstance())
{
@@ -72,169 +67,154 @@ extern "C" void otNcpInit(otInstance *aInstance)
#endif // OPENTHREAD_ENABLE_SPINEL_VENDOR_SUPPORT == 0
static void spi_header_set_flag_byte(uint8_t *header, uint8_t value)
NcpSpi::NcpSpi(Instance *aInstance)
: NcpBase(aInstance)
, mTxState(kTxStateIdle)
, mHandlingRxFrame(false)
, mResetFlag(true)
, mPrepareTxFrameTask(*aInstance, &NcpSpi::PrepareTxFrame, this)
, mSendFrameLength(0)
{
header[0] = value;
}
SpiFrame sendFrame(mSendFrame);
SpiFrame emptyFullAccept(mEmptySendFrameFullAccept);
SpiFrame emptyZeroAccept(mEmptySendFrameZeroAccept);
static void spi_header_set_accept_len(uint8_t *header, uint16_t len)
{
header[1] = ((len >> 0) & 0xff);
header[2] = ((len >> 8) & 0xff);
}
sendFrame.SetHeaderFlagByte(/* aResetFlag */ true);
sendFrame.SetHeaderAcceptLen(0);
sendFrame.SetHeaderDataLen(0);
static void spi_header_set_data_len(uint8_t *header, uint16_t len)
{
header[3] = ((len >> 0) & 0xff);
header[4] = ((len >> 8) & 0xff);
}
emptyFullAccept.SetHeaderFlagByte(/* aResetFlag */ true);
emptyFullAccept.SetHeaderAcceptLen(kSpiBufferSize - kSpiHeaderSize);
emptyFullAccept.SetHeaderDataLen(0);
static uint8_t spi_header_get_flag_byte(const uint8_t *header)
{
return header[0];
}
static uint16_t spi_header_get_accept_len(const uint8_t *header)
{
return ( header[1] + static_cast<uint16_t>(header[2] << 8) );
}
static uint16_t spi_header_get_data_len(const uint8_t *header)
{
return ( header[3] + static_cast<uint16_t>(header[4] << 8) );
}
NcpSpi::NcpSpi(Instance *aInstance) :
NcpBase(aInstance),
mTxState(kTxStateIdle),
mHandlingRxFrame(false),
mResetFlag(true),
mPrepareTxFrameTask(*aInstance, &NcpSpi::PrepareTxFrame, this),
mSendFrameLen(0)
{
memset(mSendFrame, 0, kSpiHeaderLength);
memset(mEmptySendFrameZeroAccept, 0, kSpiHeaderLength);
memset(mEmptySendFrameFullAccept, 0, kSpiHeaderLength);
emptyZeroAccept.SetHeaderFlagByte(/* aResetFlag */ true);
emptyZeroAccept.SetHeaderAcceptLen(0);
emptyZeroAccept.SetHeaderDataLen(0);
mTxFrameBuffer.SetFrameAddedCallback(HandleFrameAddedToTxBuffer, this);
spi_header_set_flag_byte(mSendFrame, SPI_RESET_FLAG | SPI_PATTERN_VALUE);
spi_header_set_flag_byte(mEmptySendFrameZeroAccept, SPI_RESET_FLAG | SPI_PATTERN_VALUE);
spi_header_set_flag_byte(mEmptySendFrameFullAccept, SPI_RESET_FLAG | SPI_PATTERN_VALUE);
spi_header_set_accept_len(mSendFrame, sizeof(mReceiveFrame) - kSpiHeaderLength);
spi_header_set_accept_len(mEmptySendFrameFullAccept, sizeof(mReceiveFrame) - kSpiHeaderLength);
spi_header_set_accept_len(mEmptySendFrameZeroAccept, 0);
otPlatSpiSlaveEnable(&NcpSpi::SpiTransactionComplete, &NcpSpi::SpiTransactionProcess, this);
// We signal an interrupt on this first transaction to
// make sure that the host processor knows that our
// reset flag was set.
otPlatSpiSlavePrepareTransaction(mEmptySendFrameZeroAccept, kSpiHeaderLength, mEmptyReceiveFrame, kSpiHeaderLength,
true);
otPlatSpiSlavePrepareTransaction(mEmptySendFrameZeroAccept, kSpiHeaderSize, mEmptyReceiveFrame, kSpiHeaderSize,
/* aRequestTras */ true);
}
bool NcpSpi::SpiTransactionComplete(void *aContext, uint8_t *aOutputBuf, uint16_t aOutputBufLen, uint8_t *aInputBuf,
uint16_t aInputBufLen, uint16_t aTransactionLength)
bool NcpSpi::SpiTransactionComplete(void * aContext,
uint8_t *aOutputBuf,
uint16_t aOutputLen,
uint8_t *aInputBuf,
uint16_t aInputLen,
uint16_t aTransLen)
{
return static_cast<NcpSpi *>(aContext)->SpiTransactionComplete(aOutputBuf, aOutputBufLen, aInputBuf, aInputBufLen,
aTransactionLength);
NcpSpi *ncp = reinterpret_cast<NcpSpi *>(aContext);
return ncp->SpiTransactionComplete(aOutputBuf, aOutputLen, aInputBuf, aInputLen, aTransLen);
}
bool NcpSpi::SpiTransactionComplete(uint8_t *aOutputBuf, uint16_t aOutputBufLen, uint8_t *aInputBuf,
uint16_t aInputBufLen, uint16_t aTransactionLength)
bool NcpSpi::SpiTransactionComplete(uint8_t *aOutputBuf,
uint16_t aOutputLen,
uint8_t *aInputBuf,
uint16_t aInputLen,
uint16_t aTransLen)
{
// This may be executed from an interrupt context.
// Must return as quickly as possible.
// This can be executed from an interrupt context, therefore we cannot
// use any of OpenThread APIs here. If further processing is needed,
// returned value `shouldProcess` is set to `true` to indicate to
// platform SPI slave driver to invoke `SpiTransactionProcess()` callback
// which unlike this callback must be called from the same OS context
// that OpenThread APIs/callbacks are executed.
uint16_t rx_data_len = 0;
uint16_t rx_accept_len = 0;
uint16_t tx_data_len = 0;
uint16_t tx_accept_len = 0;
bool shouldProcess = false;
uint16_t transDataLen;
bool shouldProcess = false;
SpiFrame outputFrame(aOutputBuf);
SpiFrame inputFrame(aInputBuf);
SpiFrame sendFrame(mSendFrame);
// TODO: Check `PATTERN` bits of `HDR` and ignore frame if not set.
// Holding off on implementing this so as to not cause immediate
// compatibility problems, even though it is required by the spec.
VerifyOrExit((aTransLen >= kSpiHeaderSize) && (aInputLen >= kSpiHeaderSize) && (aOutputLen >= kSpiHeaderSize));
VerifyOrExit(inputFrame.IsValid() && outputFrame.IsValid());
if (aTransactionLength >= kSpiHeaderLength)
transDataLen = aTransLen - kSpiHeaderSize;
if (!mHandlingRxFrame)
{
if (aOutputBufLen >= kSpiHeaderLength)
{
rx_accept_len = spi_header_get_accept_len(aOutputBuf);
tx_data_len = spi_header_get_data_len(aOutputBuf);
(void)spi_header_get_flag_byte(aOutputBuf);
}
uint16_t rxDataLen = inputFrame.GetHeaderDataLen();
if (aInputBufLen >= kSpiHeaderLength)
{
rx_data_len = spi_header_get_data_len(aInputBuf);
tx_accept_len = spi_header_get_accept_len(aInputBuf);
}
// A new frame is successfully received if input frame
// indicates that there is data and the "data len" is not
// larger than than the "accept len" we provided in the
// exchanged output frame.
if (!mHandlingRxFrame &&
(rx_data_len > 0) &&
(rx_data_len <= aTransactionLength - kSpiHeaderLength) &&
(rx_data_len <= rx_accept_len))
if ((rxDataLen > 0) && (rxDataLen <= transDataLen) && (rxDataLen <= outputFrame.GetHeaderAcceptLen()))
{
mHandlingRxFrame = true;
shouldProcess = true;
shouldProcess = true;
}
}
if ((mTxState == kTxStateSending) &&
(tx_data_len > 0) &&
(tx_data_len <= aTransactionLength - kSpiHeaderLength) &&
(tx_data_len <= tx_accept_len))
if (mTxState == kTxStateSending)
{
uint16_t txDataLen = outputFrame.GetHeaderDataLen();
// Frame transmission is successful if master indicates
// in the input frame that it could accept the frame
// length that was exchanged, i.e., the "data len" in
// the output frame is smaller than or equal to "accept
// len" in the received input frame from master.
if ((txDataLen > 0) && (txDataLen <= transDataLen) && (txDataLen <= inputFrame.GetHeaderAcceptLen()))
{
mTxState = kTxStateHandlingSendDone;
mTxState = kTxStateHandlingSendDone;
shouldProcess = true;
}
}
if (mResetFlag && (aTransactionLength > 0) && (aOutputBufLen > 0))
exit:
// Determine the input and output frames to prepare a new transaction.
if (mResetFlag && (aTransLen > 0) && (aOutputLen > 0))
{
// Clear the reset flag.
mResetFlag = false;
spi_header_set_flag_byte(mSendFrame, SPI_PATTERN_VALUE);
spi_header_set_flag_byte(mEmptySendFrameZeroAccept, SPI_PATTERN_VALUE);
spi_header_set_flag_byte(mEmptySendFrameFullAccept, SPI_PATTERN_VALUE);
sendFrame.SetHeaderFlagByte(/*aResetFlag */ false);
SpiFrame(mEmptySendFrameFullAccept).SetHeaderFlagByte(/*aResetFlag */ false);
SpiFrame(mEmptySendFrameZeroAccept).SetHeaderFlagByte(/*aResetFlag */ false);
}
if (mTxState == kTxStateSending)
{
aOutputBuf = mSendFrame;
aOutputBufLen = mSendFrameLen;
aOutputLen = mSendFrameLength;
}
else
{
aOutputBuf = (mHandlingRxFrame) ? mEmptySendFrameZeroAccept : mEmptySendFrameFullAccept;
aOutputBufLen = kSpiHeaderLength;
aOutputBuf = mHandlingRxFrame ? mEmptySendFrameZeroAccept : mEmptySendFrameFullAccept;
aOutputLen = kSpiHeaderSize;
}
if (mHandlingRxFrame)
{
aInputBuf = mEmptyReceiveFrame;
aInputBufLen = kSpiHeaderLength;
spi_header_set_accept_len(mSendFrame, 0);
aInputLen = kSpiHeaderSize;
}
else
{
aInputBuf = mReceiveFrame;
aInputBufLen = sizeof(mReceiveFrame);
spi_header_set_accept_len(mSendFrame, sizeof(mReceiveFrame) - kSpiHeaderLength);
aInputLen = kSpiBufferSize;
}
otPlatSpiSlavePrepareTransaction(aOutputBuf, aOutputBufLen, aInputBuf, aInputBufLen,
(mTxState == kTxStateSending));
sendFrame.SetHeaderAcceptLen(aInputLen - kSpiHeaderSize);
otPlatSpiSlavePrepareTransaction(aOutputBuf, aOutputLen, aInputBuf, aInputLen, (mTxState == kTxStateSending));
return shouldProcess;
}
void NcpSpi::SpiTransactionProcess(void *aContext)
{
static_cast<NcpSpi *>(aContext)->SpiTransactionProcess();
reinterpret_cast<NcpSpi *>(aContext)->SpiTransactionProcess();
}
void NcpSpi::SpiTransactionProcess(void)
@@ -250,8 +230,10 @@ void NcpSpi::SpiTransactionProcess(void)
}
}
void NcpSpi::HandleFrameAddedToTxBuffer(void *aContext, NcpFrameBuffer::FrameTag aTag,
NcpFrameBuffer::Priority aPriority, NcpFrameBuffer *aNcpFrameBuffer)
void NcpSpi::HandleFrameAddedToTxBuffer(void * aContext,
NcpFrameBuffer::FrameTag aTag,
NcpFrameBuffer::Priority aPriority,
NcpFrameBuffer * aNcpFrameBuffer)
{
OT_UNUSED_VARIABLE(aNcpFrameBuffer);
OT_UNUSED_VARIABLE(aTag);
@@ -260,11 +242,12 @@ void NcpSpi::HandleFrameAddedToTxBuffer(void *aContext, NcpFrameBuffer::FrameTag
static_cast<NcpSpi *>(aContext)->mPrepareTxFrameTask.Post();
}
otError NcpSpi::PrepareNextSpiSendFrame(void)
void NcpSpi::PrepareNextSpiSendFrame(void)
{
otError errorCode = OT_ERROR_NONE;
otError error = OT_ERROR_NONE;
uint16_t frameLength;
uint16_t readLength;
SpiFrame sendFrame(mSendFrame);
VerifyOrExit(!mTxFrameBuffer.IsEmpty());
@@ -273,38 +256,36 @@ otError NcpSpi::PrepareNextSpiSendFrame(void)
otPlatWakeHost();
}
SuccessOrExit(errorCode = mTxFrameBuffer.OutFrameBegin());
SuccessOrExit(error = mTxFrameBuffer.OutFrameBegin());
frameLength = mTxFrameBuffer.OutFrameGetLength();
assert(frameLength <= sizeof(mSendFrame) - kSpiHeaderLength);
spi_header_set_data_len(mSendFrame, frameLength);
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, mSendFrame + kSpiHeaderLength);
readLength = mTxFrameBuffer.OutFrameRead(frameLength, sendFrame.GetData());
assert(readLength == frameLength);
mSendFrameLen = frameLength + kSpiHeaderLength;
sendFrame.SetHeaderDataLen(frameLength);
mSendFrameLength = frameLength + kSpiHeaderSize;
mTxState = kTxStateSending;
// Prepare new transaction by using `mSendFrame` as the output
// buffer while keeping the input buffer unchanged.
// frame while keeping the input frame unchanged.
errorCode = otPlatSpiSlavePrepareTransaction(mSendFrame, mSendFrameLen, NULL, 0, true);
error = otPlatSpiSlavePrepareTransaction(mSendFrame, mSendFrameLength, NULL, 0, /* aRequestTrans */ true);
if (errorCode == OT_ERROR_BUSY)
if (error == OT_ERROR_BUSY)
{
// Being busy is OK. We will get the transaction
// set up properly when the current transaction
// is completed.
errorCode = OT_ERROR_NONE;
// Being busy is OK. We will get the transaction set up
// properly when the current transaction is completed.
error = OT_ERROR_NONE;
}
if (errorCode != OT_ERROR_NONE)
if (error != OT_ERROR_NONE)
{
mTxState = kTxStateIdle;
mPrepareTxFrameTask.Post();
@@ -314,7 +295,7 @@ otError NcpSpi::PrepareNextSpiSendFrame(void)
mTxFrameBuffer.OutFrameRemove();
exit:
return errorCode;
return;
}
void NcpSpi::PrepareTxFrame(Tasklet &aTasklet)
@@ -347,8 +328,11 @@ void NcpSpi::PrepareTxFrame(void)
void NcpSpi::HandleRxFrame(void)
{
SpiFrame recvFrame(mReceiveFrame);
SpiFrame sendFrame(mSendFrame);
// Pass the received frame to base class to process.
HandleReceive(mReceiveFrame + kSpiHeaderLength, spi_header_get_data_len(mReceiveFrame));
HandleReceive(recvFrame.GetData(), recvFrame.GetHeaderDataLen());
// The order of operations below is important. We should clear
// the `mHandlingRxFrame` before checking `mTxState` and possibly
@@ -371,10 +355,10 @@ void NcpSpi::HandleRxFrame(void)
if (mTxState != kTxStateSending)
{
spi_header_set_accept_len(mSendFrame, sizeof(mReceiveFrame) - kSpiHeaderLength);
sendFrame.SetHeaderAcceptLen(kSpiBufferSize - kSpiHeaderSize);
otPlatSpiSlavePrepareTransaction(mEmptySendFrameFullAccept, kSpiHeaderLength, mReceiveFrame,
sizeof(mReceiveFrame), false);
otPlatSpiSlavePrepareTransaction(mEmptySendFrameFullAccept, kSpiHeaderSize, mReceiveFrame, kSpiBufferSize,
/* aRequestTrans */ false);
// No need to check the error status. Getting `OT_ERROR_BUSY`
// is OK as everything will be set up properly from callback when
@@ -382,7 +366,7 @@ void NcpSpi::HandleRxFrame(void)
}
}
} // namespace Ncp
} // namespace ot
} // namespace Ncp
} // namespace ot
#endif // OPENTHREAD_ENABLE_NCP_SPI
+154 -28
View File
@@ -40,6 +40,121 @@
namespace ot {
namespace Ncp {
/**
* This class defines a SPI frame.
*
*/
class SpiFrame
{
public:
enum
{
kHeaderSize = 5, ///< SPI header size (in bytes).
};
/**
* This constructor initializes an `SpiFrame` instance.
*
* @param[in] aBuffer Pointer to buffer containing the frame.
*
*/
SpiFrame(uint8_t *aBuffer) : mBuffer(aBuffer) { }
/**
* This method gets a pointer to data portion in the SPI frame skipping the header.
*
* @returns A pointer to data in the SPI frame.
*
*/
uint8_t *GetData(void) { return mBuffer + kHeaderSize; }
/**
* This method indicates whether or not the frame is valid.
*
* In a valid frame the flag byte should contain the pattern bits.
*
* @returns TRUE if the frame is valid, FALSE otherwise.
*
*/
bool IsValid(void) const
{
return ((mBuffer[kIndexFlagByte] & kFlagPatternMask) == kFlagPattern);
}
/**
* This method sets the "flag byte" field in the SPI frame header.
*
* @param[in] aResetFalg The status of reset flag (TRUE to set the flag, FALSE to clear flag).
*
*/
void SetHeaderFlagByte(bool aResetFlag)
{
mBuffer[kIndexFlagByte] = kFlagPattern | (aResetFlag ? kFlagReset : 0);
}
/**
* This method sets the "accept len" field in the SPI frame header.
*
* "accept len" specifies number of bytes the sender of the SPI frame can receive.
*
* @param[in] aAcceptLen The accept length in bytes.
*
*/
void SetHeaderAcceptLen(uint16_t aAcceptLen)
{
Encoding::LittleEndian::WriteUint16(aAcceptLen, mBuffer + kIndexAcceptLen);
}
/**
* This method gets the "accept len" field in the SPI frame header.
*
* @returns The accept length in bytes.
*
*/
uint16_t GetHeaderAcceptLen(void) const
{
return Encoding::LittleEndian::ReadUint16(mBuffer + kIndexAcceptLen);
}
/**
* This method sets the "data len" field in the SPI frame header.
*
* "Data len" specifies number of data bytes in the transmitted SPI frame.
*
* @param[in] aDataLen The data length in bytes.
*
*/
void SetHeaderDataLen(uint16_t aDataLen)
{
Encoding::LittleEndian::WriteUint16(aDataLen, mBuffer + kIndexDataLen);
}
/**
* This method gets the "data len" field in the SPI frame header.
*
* @returns The data length in bytes.
*
*/
uint16_t GetHeaderDataLen(void) const
{
return Encoding::LittleEndian::ReadUint16(mBuffer + kIndexDataLen);
}
private:
enum
{
kIndexFlagByte = 0, // flag byte (uint8_t).
kIndexAcceptLen = 1, // accept len (uint16_t little-endian encoding).
kIndexDataLen = 3, // data len (uint16_t little-endian encoding).
kFlagReset = (1 << 7), // Flag byte RESET bit.
kFlagPattern = 0x02, // Flag byte PATTERN bits.
kFlagPatternMask = 0x03, // Flag byte PATTERN mask.
};
uint8_t *mBuffer;
};
class NcpSpi : public NcpBase
{
public:
@@ -58,55 +173,66 @@ private:
* SPI tx and rx buffer size (should fit a max length frame + SPI header).
*
*/
kSpiBufferSize = OPENTHREAD_CONFIG_NCP_SPI_BUFFER_SIZE,
kSpiBufferSize = OPENTHREAD_CONFIG_NCP_SPI_BUFFER_SIZE,
/**
* Size of SPI header in bytes.
* Size of the SPI header (in bytes).
*
*/
kSpiHeaderLength = 5,
kSpiHeaderSize = SpiFrame::kHeaderSize,
};
enum TxState
{
kTxStateIdle, // No frame to send.
kTxStateSending, // A frame is ready to be sent.
kTxStateHandlingSendDone // The frame was sent successfully, waiting to prepare the next one (if any).
kTxStateIdle, // No frame to send.
kTxStateSending, // A frame is ready to be sent.
kTxStateHandlingSendDone // The frame was sent successfully, waiting to prepare the next one (if any).
};
static bool SpiTransactionComplete(void *aContext, uint8_t *aOutputBuf, uint16_t aOutputBufLen, uint8_t *aInputBuf,
uint16_t aInputBufLen, uint16_t aTransactionLength);
bool SpiTransactionComplete(uint8_t *aOutputBuf, uint16_t aOutputBufLen, uint8_t *aInputBuf, uint16_t aInputBufLen,
uint16_t aTransactionLength);
typedef uint8_t LargeFrameBuffer[kSpiBufferSize];
typedef uint8_t EmptyFrameBuffer[kSpiHeaderSize];
static bool SpiTransactionComplete(void * aContext,
uint8_t *aOutputBuf,
uint16_t aOutputLen,
uint8_t *aInputBuf,
uint16_t aInputLen,
uint16_t aTransLen);
bool SpiTransactionComplete(uint8_t *aOutputBuf,
uint16_t aOutputLen,
uint8_t *aInputBuf,
uint16_t aInputLen,
uint16_t aTransLen);
static void SpiTransactionProcess(void *aContext);
void SpiTransactionProcess(void);
void SpiTransactionProcess(void);
static void HandleFrameAddedToTxBuffer(void *aContext, NcpFrameBuffer::FrameTag aFrameTag,
NcpFrameBuffer::Priority aPriority, NcpFrameBuffer *aNcpFrameBuffer);
static void HandleFrameAddedToTxBuffer(void * aContext,
NcpFrameBuffer::FrameTag aFrameTag,
NcpFrameBuffer::Priority aPriority,
NcpFrameBuffer * aNcpFrameBuffer);
static void PrepareTxFrame(Tasklet &aTasklet);
void PrepareTxFrame(void);
void HandleRxFrame(void);
otError PrepareNextSpiSendFrame(void);
void PrepareTxFrame(void);
void HandleRxFrame(void);
void PrepareNextSpiSendFrame(void);
volatile TxState mTxState;
volatile bool mHandlingRxFrame;
volatile bool mResetFlag;
volatile bool mHandlingRxFrame;
volatile bool mResetFlag;
Tasklet mPrepareTxFrameTask;
uint16_t mSendFrameLen;
uint8_t mSendFrame[kSpiBufferSize];
uint8_t mReceiveFrame[kSpiBufferSize];
uint16_t mSendFrameLength;
LargeFrameBuffer mSendFrame;
EmptyFrameBuffer mEmptySendFrameFullAccept;
EmptyFrameBuffer mEmptySendFrameZeroAccept;
uint8_t mEmptySendFrameZeroAccept[kSpiHeaderLength];
uint8_t mEmptySendFrameFullAccept[kSpiHeaderLength];
uint8_t mEmptyReceiveFrame[kSpiHeaderLength];
LargeFrameBuffer mReceiveFrame;
EmptyFrameBuffer mEmptyReceiveFrame;
};
} // namespace Ncp
} // namespace ot
} // namespace Ncp
} // namespace ot
#endif // NCP_SPI_HPP_
#endif // NCP_SPI_HPP_