mirror of
https://github.com/espressif/openthread.git
synced 2026-08-05 18:37:45 +00:00
[posix] add rcp capability diag command to check the Spinel interface speed (#10443)
This commit is contained in:
@@ -1771,6 +1771,12 @@ void RadioSpinel::SetDiagOutputCallback(otPlatDiagOutputCallback aCallback, void
|
||||
mOutputContext = aContext;
|
||||
}
|
||||
|
||||
void RadioSpinel::GetDiagOutputCallback(otPlatDiagOutputCallback &aCallback, void *&aContext)
|
||||
{
|
||||
aCallback = mOutputCallback;
|
||||
aContext = mOutputContext;
|
||||
}
|
||||
|
||||
otError RadioSpinel::PlatDiagProcess(const char *aString)
|
||||
{
|
||||
return Set(SPINEL_PROP_NEST_STREAM_MFG, SPINEL_DATATYPE_UTF8_S, aString);
|
||||
|
||||
@@ -695,6 +695,15 @@ public:
|
||||
*
|
||||
*/
|
||||
void SetDiagOutputCallback(otPlatDiagOutputCallback aCallback, void *aContext);
|
||||
|
||||
/**
|
||||
* Gets the diag output callback.
|
||||
*
|
||||
* @param[out] aCallback A reference to a function that is called on outputting diag messages.
|
||||
* @param[out] aContext A reference to the user context.
|
||||
*
|
||||
*/
|
||||
void GetDiagOutputCallback(otPlatDiagOutputCallback &aCallback, void *&aContext);
|
||||
#endif
|
||||
|
||||
/**
|
||||
|
||||
@@ -8,6 +8,7 @@ This module provides diag commands for checking RCP capabilities.
|
||||
|
||||
- [capflags](#capflags)
|
||||
- [spinel](#spinel)
|
||||
- [spinelspeed](#spinelspeed)
|
||||
- [srcmatchtable](#srcmatchtable)
|
||||
|
||||
## Command Details
|
||||
@@ -114,6 +115,16 @@ PROP_VALUE_SET RADIO_COEX_ENABLE -------------------------- OK
|
||||
Done
|
||||
```
|
||||
|
||||
### spinelspeed
|
||||
|
||||
Check the speed of Spinel interface.
|
||||
|
||||
```bash
|
||||
> diag rcpcaps spinelspeed
|
||||
SpinelSpeed ----------------------------------------------- 34414843 bps
|
||||
Done
|
||||
```
|
||||
|
||||
### srcmatchtable
|
||||
|
||||
Check the source match table size supported by the RCP.
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
|
||||
#include "rcp_caps_diag.hpp"
|
||||
|
||||
#include "lib/utils/math.hpp"
|
||||
|
||||
#if OPENTHREAD_POSIX_CONFIG_RCP_CAPS_DIAG_ENABLE
|
||||
namespace ot {
|
||||
namespace Posix {
|
||||
@@ -465,6 +467,10 @@ otError RcpCapsDiag::DiagProcess(char *aArgs[], uint8_t aArgsLength)
|
||||
{
|
||||
ProcessSpinel();
|
||||
}
|
||||
else if (strcmp(aArgs[1], "spinelspeed") == 0)
|
||||
{
|
||||
ProcessSpinelSpeed();
|
||||
}
|
||||
else
|
||||
{
|
||||
error = OT_ERROR_INVALID_COMMAND;
|
||||
@@ -680,6 +686,87 @@ exit:
|
||||
OutputFormat("ExtendedSrcMatchTableSize", num);
|
||||
}
|
||||
|
||||
void RcpCapsDiag::HandleDiagOutput(const char *aFormat, va_list aArguments, void *aContext)
|
||||
{
|
||||
static_cast<RcpCapsDiag *>(aContext)->HandleDiagOutput(aFormat, aArguments);
|
||||
}
|
||||
|
||||
void RcpCapsDiag::HandleDiagOutput(const char *aFormat, va_list aArguments)
|
||||
{
|
||||
int rval;
|
||||
|
||||
VerifyOrExit(mDiagOutput != nullptr && mDiagOutputLength != 0);
|
||||
rval = vsnprintf(mDiagOutput, mDiagOutputLength, aFormat, aArguments);
|
||||
VerifyOrExit(rval >= 0);
|
||||
|
||||
rval = (rval > mDiagOutputLength) ? mDiagOutputLength : rval;
|
||||
mDiagOutput += rval;
|
||||
mDiagOutputLength -= rval;
|
||||
|
||||
exit:
|
||||
return;
|
||||
}
|
||||
|
||||
void RcpCapsDiag::ProcessSpinelSpeed(void)
|
||||
{
|
||||
static constexpr uint32_t kUsPerSec = 1000000;
|
||||
static constexpr uint8_t kBitsPerByte = 8;
|
||||
static constexpr uint8_t kSpinelHeaderSize = 4;
|
||||
static constexpr uint8_t kZeroTerminatorSize = 1;
|
||||
static constexpr char kEchoCmd[] = "echo ";
|
||||
static constexpr uint8_t kEchoPayloadLength = 200;
|
||||
static constexpr uint8_t kNumTests = 100;
|
||||
|
||||
otError error = OT_ERROR_NONE;
|
||||
char cmd[OPENTHREAD_CONFIG_DIAG_CMD_LINE_BUFFER_SIZE] = {0};
|
||||
char output[OPENTHREAD_CONFIG_DIAG_OUTPUT_BUFFER_SIZE];
|
||||
uint16_t echoPayloadLength;
|
||||
uint64_t startTimestamp;
|
||||
uint64_t endTimestamp;
|
||||
uint64_t sumTime = 0;
|
||||
uint64_t sumLength = 0;
|
||||
uint32_t speed;
|
||||
otPlatDiagOutputCallback callback;
|
||||
void *context;
|
||||
|
||||
mRadioSpinel.GetDiagOutputCallback(callback, context);
|
||||
mRadioSpinel.SetDiagOutputCallback(HandleDiagOutput, this);
|
||||
|
||||
strncpy(cmd, kEchoCmd, sizeof(cmd) - 1);
|
||||
echoPayloadLength = static_cast<uint16_t>(sizeof(cmd) - strlen(cmd) - 1);
|
||||
echoPayloadLength = Lib::Utils::Min<uint16_t>(kEchoPayloadLength, echoPayloadLength);
|
||||
memset(cmd + strlen(cmd), '1', echoPayloadLength);
|
||||
|
||||
for (uint16_t i = 0; i < kNumTests; i++)
|
||||
{
|
||||
output[0] = '\0';
|
||||
mDiagOutput = output;
|
||||
mDiagOutputLength = sizeof(output);
|
||||
startTimestamp = otPlatTimeGet();
|
||||
|
||||
SuccessOrExit(error = mRadioSpinel.PlatDiagProcess(cmd));
|
||||
|
||||
endTimestamp = otPlatTimeGet();
|
||||
sumTime += endTimestamp - startTimestamp;
|
||||
sumLength += kSpinelHeaderSize + strlen(cmd) + kZeroTerminatorSize + kSpinelHeaderSize + strlen(output) +
|
||||
kZeroTerminatorSize;
|
||||
}
|
||||
|
||||
mRadioSpinel.SetDiagOutputCallback(callback, context);
|
||||
|
||||
exit:
|
||||
if (error == OT_ERROR_NONE)
|
||||
{
|
||||
speed = static_cast<uint32_t>((sumLength * kBitsPerByte * kUsPerSec) / sumTime);
|
||||
snprintf(output, sizeof(output), "%lu bps", ToUlong(speed));
|
||||
OutputFormat("SpinelSpeed", output);
|
||||
}
|
||||
else
|
||||
{
|
||||
Output("Failed to test the Spinel speed: %s", otThreadErrorToString(error));
|
||||
}
|
||||
}
|
||||
|
||||
void RcpCapsDiag::OutputFormat(const char *aName, const char *aValue)
|
||||
{
|
||||
static constexpr uint8_t kMaxNameLength = 56;
|
||||
|
||||
@@ -62,6 +62,8 @@ public:
|
||||
: mRadioSpinel(aRadioSpinel)
|
||||
, mOutputCallback(nullptr)
|
||||
, mOutputContext(nullptr)
|
||||
, mDiagOutput(nullptr)
|
||||
, mDiagOutputLength(0)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -111,6 +113,7 @@ private:
|
||||
static constexpr uint16_t kMaxNumChildren = 512;
|
||||
|
||||
void ProcessSpinel(void);
|
||||
void ProcessSpinelSpeed(void);
|
||||
void ProcessCapabilityFlags(void);
|
||||
void ProcessSrcMatchTable(void);
|
||||
void TestSpinelCommands(Category aCategory);
|
||||
@@ -125,6 +128,10 @@ private:
|
||||
bool IsSpinelCapabilitySupported(const uint8_t *aCapsData, spinel_size_t aCapsLength, uint32_t aCapability);
|
||||
void OutputExtendedSrcMatchTableSize(void);
|
||||
void OutputShortSrcMatchTableSize(void);
|
||||
|
||||
static void HandleDiagOutput(const char *aFormat, va_list aArguments, void *aContext);
|
||||
void HandleDiagOutput(const char *aFormat, va_list aArguments);
|
||||
|
||||
void OutputFormat(const char *aName, const char *aValue);
|
||||
void OutputFormat(const char *aName, uint32_t aValue);
|
||||
void OutputResult(const SpinelEntry &aEntry, otError error);
|
||||
@@ -139,6 +146,8 @@ private:
|
||||
Spinel::RadioSpinel &mRadioSpinel;
|
||||
otPlatDiagOutputCallback mOutputCallback;
|
||||
void *mOutputContext;
|
||||
char *mDiagOutput;
|
||||
uint16_t mDiagOutputLength;
|
||||
};
|
||||
|
||||
} // namespace Posix
|
||||
|
||||
Reference in New Issue
Block a user