mirror of
https://github.com/espressif/openthread.git
synced 2026-08-06 02:37:47 +00:00
[platform] add RCP interface metrics (#7860)
This commit is contained in:
@@ -135,6 +135,8 @@ HdlcInterface::HdlcInterface(SpinelInterface::ReceiveFrameCallback aCallback,
|
||||
, mHdlcDecoder(aFrameBuffer, HandleHdlcFrame, this)
|
||||
, mRadioUrl(nullptr)
|
||||
{
|
||||
memset(&mInterfaceMetrics, 0, sizeof(mInterfaceMetrics));
|
||||
mInterfaceMetrics.mRcpInterfaceType = OT_POSIX_RCP_BUS_UART;
|
||||
}
|
||||
|
||||
void HdlcInterface::OnRcpReset(void)
|
||||
@@ -252,6 +254,19 @@ otError HdlcInterface::Write(const uint8_t *aFrame, uint16_t aLength)
|
||||
|
||||
exit:
|
||||
#endif // OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
|
||||
mInterfaceMetrics.mTransferredFrameCount++;
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
mInterfaceMetrics.mTxFrameCount++;
|
||||
mInterfaceMetrics.mTxFrameByteCount += aLength;
|
||||
mInterfaceMetrics.mTransferredValidFrameCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
mInterfaceMetrics.mTransferredGarbageFrameCount++;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -654,12 +669,18 @@ void HdlcInterface::HandleHdlcFrame(void *aContext, otError aError)
|
||||
|
||||
void HdlcInterface::HandleHdlcFrame(otError aError)
|
||||
{
|
||||
mInterfaceMetrics.mTransferredFrameCount++;
|
||||
|
||||
if (aError == OT_ERROR_NONE)
|
||||
{
|
||||
mInterfaceMetrics.mRxFrameCount++;
|
||||
mInterfaceMetrics.mRxFrameByteCount += mReceiveFrameBuffer.GetLength();
|
||||
mInterfaceMetrics.mTransferredValidFrameCount++;
|
||||
mReceiveFrameCallback(mReceiveFrameContext);
|
||||
}
|
||||
else
|
||||
{
|
||||
mInterfaceMetrics.mTransferredGarbageFrameCount++;
|
||||
mReceiveFrameBuffer.DiscardFrame();
|
||||
otLogWarnPlat("Error decoding hdlc frame: %s", otThreadErrorToString(aError));
|
||||
}
|
||||
|
||||
@@ -169,6 +169,14 @@ public:
|
||||
*/
|
||||
otError ResetConnection(void);
|
||||
|
||||
/**
|
||||
* This method returns the RCP interface metrics.
|
||||
*
|
||||
* @returns The RCP interface metrics.
|
||||
*
|
||||
*/
|
||||
const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void) const { return &mInterfaceMetrics; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* This method instructs `HdlcInterface` to read and decode data from radio over the socket.
|
||||
@@ -258,6 +266,8 @@ private:
|
||||
Hdlc::Decoder mHdlcDecoder;
|
||||
const Url::Url *mRadioUrl;
|
||||
|
||||
otRcpInterfaceMetrics mInterfaceMetrics;
|
||||
|
||||
// Non-copyable, intentionally not implemented.
|
||||
HdlcInterface(const HdlcInterface &);
|
||||
HdlcInterface &operator=(const HdlcInterface &);
|
||||
|
||||
@@ -84,6 +84,22 @@ typedef struct otPlatformConfig
|
||||
///< directly after initialization.
|
||||
} otPlatformConfig;
|
||||
|
||||
/**
|
||||
* This structure represents RCP interface metrics.
|
||||
*
|
||||
*/
|
||||
typedef struct otRcpInterfaceMetrics
|
||||
{
|
||||
uint8_t mRcpInterfaceType; ///< The RCP interface type.
|
||||
uint64_t mTransferredFrameCount; ///< The number of transferred frames.
|
||||
uint64_t mTransferredValidFrameCount; ///< The number of transferred valid frames.
|
||||
uint64_t mTransferredGarbageFrameCount; ///< The number of transferred garbage frames.
|
||||
uint64_t mRxFrameCount; ///< The number of received frames.
|
||||
uint64_t mRxFrameByteCount; ///< The number of received bytes.
|
||||
uint64_t mTxFrameCount; ///< The number of transmitted frames.
|
||||
uint64_t mTxFrameByteCount; ///< The number of transmitted bytes.
|
||||
} otRcpInterfaceMetrics;
|
||||
|
||||
/**
|
||||
* This function performs all platform-specific initialization of OpenThread's drivers and initializes the OpenThread
|
||||
* instance.
|
||||
@@ -194,6 +210,14 @@ const char *otSysGetInfraNetifName(void);
|
||||
*/
|
||||
const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void);
|
||||
|
||||
/**
|
||||
* This method returns the RCP interface metrics.
|
||||
*
|
||||
* @returns The RCP interface metrics.
|
||||
*
|
||||
*/
|
||||
const otRcpInterfaceMetrics *otSysGetRcpInterfaceMetrics(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // end of extern "C"
|
||||
#endif
|
||||
|
||||
@@ -665,3 +665,8 @@ const otRadioSpinelMetrics *otSysGetRadioSpinelMetrics(void)
|
||||
{
|
||||
return sRadioSpinel.GetRadioSpinelMetrics();
|
||||
}
|
||||
|
||||
const otRcpInterfaceMetrics *otSysGetRcpInterfaceMetrics(void)
|
||||
{
|
||||
return sRadioSpinel.GetSpinelInterface().GetRcpInterfaceMetrics();
|
||||
}
|
||||
|
||||
@@ -74,15 +74,8 @@ SpiInterface::SpiInterface(SpinelInterface::ReceiveFrameCallback aCallback,
|
||||
, mResetGpioValueFd(-1)
|
||||
, mIntGpioValueFd(-1)
|
||||
, mSlaveResetCount(0)
|
||||
, mSpiFrameCount(0)
|
||||
, mSpiValidFrameCount(0)
|
||||
, mSpiGarbageFrameCount(0)
|
||||
, mSpiDuplexFrameCount(0)
|
||||
, mSpiUnresponsiveFrameCount(0)
|
||||
, mSpiRxFrameCount(0)
|
||||
, mSpiRxFrameByteCount(0)
|
||||
, mSpiTxFrameCount(0)
|
||||
, mSpiTxFrameByteCount(0)
|
||||
, mSpiTxIsReady(false)
|
||||
, mSpiTxRefusedCount(0)
|
||||
, mSpiTxPayloadSize(0)
|
||||
@@ -94,13 +87,14 @@ SpiInterface::SpiInterface(SpinelInterface::ReceiveFrameCallback aCallback,
|
||||
|
||||
void SpiInterface::OnRcpReset(void)
|
||||
{
|
||||
mSpiValidFrameCount = 0;
|
||||
mSpiTxIsReady = false;
|
||||
mSpiTxRefusedCount = 0;
|
||||
mSpiTxPayloadSize = 0;
|
||||
mDidPrintRateLimitLog = false;
|
||||
mSpiSlaveDataLen = 0;
|
||||
memset(mSpiTxFrameBuffer, 0, sizeof(mSpiTxFrameBuffer));
|
||||
memset(&mInterfaceMetrics, 0, sizeof(mInterfaceMetrics));
|
||||
mInterfaceMetrics.mRcpInterfaceType = OT_POSIX_RCP_BUS_SPI;
|
||||
|
||||
TriggerReset();
|
||||
usleep(static_cast<useconds_t>(mSpiResetDelay) * kUsecPerMsec);
|
||||
@@ -402,7 +396,7 @@ otError SpiInterface::DoSpiTransfer(uint8_t *aSpiRxFrameBuffer, uint32_t aTransf
|
||||
otDumpDebgPlat("SPI-TX", mSpiTxFrameBuffer, static_cast<uint16_t>(transfer[1].len));
|
||||
otDumpDebgPlat("SPI-RX", aSpiRxFrameBuffer, static_cast<uint16_t>(transfer[1].len));
|
||||
|
||||
mSpiFrameCount++;
|
||||
mInterfaceMetrics.mTransferredFrameCount++;
|
||||
}
|
||||
|
||||
return (ret < 0) ? OT_ERROR_FAILED : OT_ERROR_NONE;
|
||||
@@ -421,7 +415,7 @@ otError SpiInterface::PushPullSpi(void)
|
||||
Ncp::SpiFrame txFrame(mSpiTxFrameBuffer);
|
||||
uint16_t skipAlignAllowanceLength;
|
||||
|
||||
if (mSpiValidFrameCount == 0)
|
||||
if (mInterfaceMetrics.mTransferredValidFrameCount == 0)
|
||||
{
|
||||
// Set the reset flag to indicate to our slave that we are coming up from scratch.
|
||||
txFrame.SetHeaderFlagByte(true);
|
||||
@@ -525,7 +519,7 @@ otError SpiInterface::PushPullSpi(void)
|
||||
else
|
||||
{
|
||||
// Header is full of garbage
|
||||
mSpiGarbageFrameCount++;
|
||||
mInterfaceMetrics.mTransferredGarbageFrameCount++;
|
||||
|
||||
otLogWarnPlat("Garbage in header : %02X %02X %02X %02X %02X", spiRxFrame[0], spiRxFrame[1],
|
||||
spiRxFrame[2], spiRxFrame[3], spiRxFrame[4]);
|
||||
@@ -542,7 +536,7 @@ otError SpiInterface::PushPullSpi(void)
|
||||
|
||||
if (!rxFrame.IsValid() || (slaveAcceptLen > kMaxFrameSize) || (mSpiSlaveDataLen > kMaxFrameSize))
|
||||
{
|
||||
mSpiGarbageFrameCount++;
|
||||
mInterfaceMetrics.mTransferredGarbageFrameCount++;
|
||||
mSpiTxRefusedCount++;
|
||||
mSpiSlaveDataLen = 0;
|
||||
|
||||
@@ -554,7 +548,7 @@ otError SpiInterface::PushPullSpi(void)
|
||||
ExitNow();
|
||||
}
|
||||
|
||||
mSpiValidFrameCount++;
|
||||
mInterfaceMetrics.mTransferredValidFrameCount++;
|
||||
|
||||
if (rxFrame.IsResetFlagSet())
|
||||
{
|
||||
@@ -567,9 +561,9 @@ otError SpiInterface::PushPullSpi(void)
|
||||
// Handle received packet, if any.
|
||||
if ((mSpiSlaveDataLen != 0) && (mSpiSlaveDataLen <= txFrame.GetHeaderAcceptLen()))
|
||||
{
|
||||
mSpiRxFrameByteCount += mSpiSlaveDataLen;
|
||||
mInterfaceMetrics.mRxFrameByteCount += mSpiSlaveDataLen;
|
||||
mSpiSlaveDataLen = 0;
|
||||
mSpiRxFrameCount++;
|
||||
mInterfaceMetrics.mRxFrameCount++;
|
||||
successfulExchanges++;
|
||||
|
||||
// Set the skip length to skip align bytes and SPI frame header.
|
||||
@@ -594,8 +588,8 @@ otError SpiInterface::PushPullSpi(void)
|
||||
// that uplayer can pull another packet for us to send.
|
||||
successfulExchanges++;
|
||||
|
||||
mSpiTxFrameCount++;
|
||||
mSpiTxFrameByteCount += mSpiTxPayloadSize;
|
||||
mInterfaceMetrics.mTxFrameCount++;
|
||||
mInterfaceMetrics.mTxFrameByteCount += mSpiTxPayloadSize;
|
||||
|
||||
mSpiTxIsReady = false;
|
||||
mSpiTxPayloadSize = 0;
|
||||
@@ -833,16 +827,16 @@ void SpiInterface::LogError(const char *aString)
|
||||
|
||||
void SpiInterface::LogStats(void)
|
||||
{
|
||||
otLogInfoPlat("INFO: mSlaveResetCount=%" PRIu64, mSlaveResetCount);
|
||||
otLogInfoPlat("INFO: mSpiFrameCount=%" PRIu64, mSpiFrameCount);
|
||||
otLogInfoPlat("INFO: mSpiValidFrameCount=%" PRIu64, mSpiValidFrameCount);
|
||||
otLogInfoPlat("INFO: mSpiDuplexFrameCount=%" PRIu64, mSpiDuplexFrameCount);
|
||||
otLogInfoPlat("INFO: mSpiUnresponsiveFrameCount=%" PRIu64, mSpiUnresponsiveFrameCount);
|
||||
otLogInfoPlat("INFO: mSpiGarbageFrameCount=%" PRIu64, mSpiGarbageFrameCount);
|
||||
otLogInfoPlat("INFO: mSpiRxFrameCount=%" PRIu64, mSpiRxFrameCount);
|
||||
otLogInfoPlat("INFO: mSpiRxFrameByteCount=%" PRIu64, mSpiRxFrameByteCount);
|
||||
otLogInfoPlat("INFO: mSpiTxFrameCount=%" PRIu64, mSpiTxFrameCount);
|
||||
otLogInfoPlat("INFO: mSpiTxFrameByteCount=%" PRIu64, mSpiTxFrameByteCount);
|
||||
otLogInfoPlat("INFO: SlaveResetCount=%" PRIu64, mSlaveResetCount);
|
||||
otLogInfoPlat("INFO: SpiDuplexFrameCount=%" PRIu64, mSpiDuplexFrameCount);
|
||||
otLogInfoPlat("INFO: SpiUnresponsiveFrameCount=%" PRIu64, mSpiUnresponsiveFrameCount);
|
||||
otLogInfoPlat("INFO: TransferredFrameCount=%" PRIu64, mInterfaceMetrics.mTransferredFrameCount);
|
||||
otLogInfoPlat("INFO: TransferredValidFrameCount=%" PRIu64, mInterfaceMetrics.mTransferredValidFrameCount);
|
||||
otLogInfoPlat("INFO: TransferredGarbageFrameCount=%" PRIu64, mInterfaceMetrics.mTransferredGarbageFrameCount);
|
||||
otLogInfoPlat("INFO: RxFrameCount=%" PRIu64, mInterfaceMetrics.mRxFrameCount);
|
||||
otLogInfoPlat("INFO: RxFrameByteCount=%" PRIu64, mInterfaceMetrics.mRxFrameByteCount);
|
||||
otLogInfoPlat("INFO: TxFrameCount=%" PRIu64, mInterfaceMetrics.mTxFrameCount);
|
||||
otLogInfoPlat("INFO: TxFrameByteCount=%" PRIu64, mInterfaceMetrics.mTxFrameByteCount);
|
||||
}
|
||||
} // namespace Posix
|
||||
} // namespace ot
|
||||
|
||||
@@ -159,6 +159,14 @@ public:
|
||||
*/
|
||||
otError ResetConnection(void) { return OT_ERROR_NONE; }
|
||||
|
||||
/**
|
||||
* This method returns the RCP interface metrics.
|
||||
*
|
||||
* @returns The RCP interface metrics.
|
||||
*
|
||||
*/
|
||||
const otRcpInterfaceMetrics *GetRcpInterfaceMetrics(void) const { return &mInterfaceMetrics; }
|
||||
|
||||
private:
|
||||
int SetupGpioHandle(int aFd, uint8_t aLine, uint32_t aHandleFlags, const char *aLabel);
|
||||
int SetupGpioEvent(int aFd, uint8_t aLine, uint32_t aHandleFlags, uint32_t aEventFlags, const char *aLabel);
|
||||
@@ -228,15 +236,8 @@ private:
|
||||
uint32_t mSpiSpeedHz;
|
||||
|
||||
uint64_t mSlaveResetCount;
|
||||
uint64_t mSpiFrameCount;
|
||||
uint64_t mSpiValidFrameCount;
|
||||
uint64_t mSpiGarbageFrameCount;
|
||||
uint64_t mSpiDuplexFrameCount;
|
||||
uint64_t mSpiUnresponsiveFrameCount;
|
||||
uint64_t mSpiRxFrameCount;
|
||||
uint64_t mSpiRxFrameByteCount;
|
||||
uint64_t mSpiTxFrameCount;
|
||||
uint64_t mSpiTxFrameByteCount;
|
||||
|
||||
bool mSpiTxIsReady;
|
||||
uint16_t mSpiTxRefusedCount;
|
||||
@@ -248,6 +249,8 @@ private:
|
||||
|
||||
bool mDidRxFrame;
|
||||
|
||||
otRcpInterfaceMetrics mInterfaceMetrics;
|
||||
|
||||
// Non-copyable, intentionally not implemented.
|
||||
SpiInterface(const SpiInterface &);
|
||||
SpiInterface &operator=(const SpiInterface &);
|
||||
|
||||
Reference in New Issue
Block a user