Skip to content

Commit

Permalink
[diag] add diag receive command to show received specified number of …
Browse files Browse the repository at this point in the history
…frames (openthread#11039)

The `diag frame` command can set the frame to be sent. But developers
has no command to check if the received frame is the same as the sent
frame. This commit adds the command `diag receive [async] <number>
[lpr]` to show the detailed info of specified number of received
frames.
  • Loading branch information
zhanglongxia authored Dec 13, 2024
1 parent 93ef72a commit 971f05f
Show file tree
Hide file tree
Showing 4 changed files with 183 additions and 7 deletions.
12 changes: 11 additions & 1 deletion src/cli/cli.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,17 @@ void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments, void
static_cast<Interpreter *>(aContext)->HandleDiagOutput(aFormat, aArguments);
}

void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments) { OutputFormatV(aFormat, aArguments); }
void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments)
{
if (strcmp(aFormat, "OT_ERROR_NONE") == 0)
{
OutputResult(OT_ERROR_NONE);
}
else
{
OutputFormatV(aFormat, aArguments);
}
}
#endif

template <> otError Interpreter::Process<Cmd("version")>(Arg aArgs[])
Expand Down
20 changes: 20 additions & 0 deletions src/core/diags/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,26 @@ set radio from sleep to receive on channel 11
status 0x00
```

### diag radio receive \[async\] \<number\> \[lpr\]

Set the radio to receive mode and receive a specified number of frames.

- async: Use the non-blocking mode.
- number: The number of frames expected to be received.
- l: Show Lqi.
- p: Show Psdu.
- r: Show Rssi.

```bash
> diag radio receive 5 lpr
0, rssi:-49, lqi:119, len:10, psdu:000102030405060771e
1, rssi:-51, lqi:112, len:10, psdu:000102030405060771e
2, rssi:-42, lqi:120, len:10, psdu:000102030405060771e
3, rssi:-54, lqi:111, len:10, psdu:000102030405060771e
4, rssi:-56, lqi:108, len:10, psdu:000102030405060771e
Done
```

### diag radio state

Return the state of the radio.
Expand Down
132 changes: 126 additions & 6 deletions src/core/diags/factory_diags.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -587,6 +587,50 @@ void Diags::TransmitPacket(void)
IgnoreError(Get<Radio>().Transmit(*static_cast<Mac::TxFrame *>(mTxPacket)));
}

Error Diags::ParseReceiveConfigFormat(const char *aFormat, ReceiveConfig &aConfig)
{
Error error = kErrorNone;

VerifyOrExit(aFormat != nullptr, error = kErrorInvalidArgs);

for (const char *arg = aFormat; *arg != '\0'; arg++)
{
switch (*arg)
{
case 'r':
aConfig.mShowRssi = true;
break;

case 'l':
aConfig.mShowLqi = true;
break;

case 'p':
aConfig.mShowPsdu = true;
break;

default:
ExitNow(error = OT_ERROR_INVALID_ARGS);
}
}

exit:
return error;
}

Error Diags::RadioReceive(void)
{
Error error;

SuccessOrExit(error = Get<Radio>().Receive(mChannel));
SuccessOrExit(error = Get<Radio>().SetTransmitPower(mTxPower));
otPlatDiagChannelSet(mChannel);
otPlatDiagTxPowerSet(mTxPower);

exit:
return error;
}

Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[])
{
Error error = kErrorInvalidArgs;
Expand All @@ -601,12 +645,44 @@ Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[])
}
else if (StringMatch(aArgs[0], "receive"))
{
SuccessOrExit(error = Get<Radio>().Receive(mChannel));
SuccessOrExit(error = Get<Radio>().SetTransmitPower(mTxPower));
otPlatDiagChannelSet(mChannel);
otPlatDiagTxPowerSet(mTxPower);
ReceiveConfig receiveConfig;

aArgs++;
aArgsLength--;

if (aArgsLength == 0)
{
SuccessOrExit(error = RadioReceive());
Output("set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", mChannel, error);
ExitNow();
}

Output("set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", mChannel, error);
if (StringMatch(aArgs[0], "async"))
{
aArgs++;
aArgsLength--;
receiveConfig.mIsAsyncCommand = true;
}

VerifyOrExit(aArgsLength > 0);
SuccessOrExit(error = Utils::CmdLineParser::ParseAsUint16(aArgs[0], receiveConfig.mNumFrames));
aArgs++;
aArgsLength--;

if (aArgsLength > 0)
{
SuccessOrExit(error = ParseReceiveConfigFormat(aArgs[0], receiveConfig));
}

SuccessOrExit(error = RadioReceive());

receiveConfig.mIsEnabled = true;
mReceiveConfig = receiveConfig;

if (!mReceiveConfig.mIsAsyncCommand)
{
error = kErrorPending;
}
}
else if (StringMatch(aArgs[0], "state"))
{
Expand Down Expand Up @@ -668,10 +744,54 @@ void Diags::AlarmFired(void)
}
}

void Diags::OutputReceivedFrame(const otRadioFrame *aFrame)
{
VerifyOrExit(mReceiveConfig.mIsEnabled && (aFrame != nullptr));

Output("%u", mReceiveConfig.mReceiveCount++);

if (mReceiveConfig.mShowRssi)
{
Output(", rssi:%d", aFrame->mInfo.mRxInfo.mRssi);
}

if (mReceiveConfig.mShowLqi)
{
Output(", lqi:%u", aFrame->mInfo.mRxInfo.mLqi);
}

if (mReceiveConfig.mShowPsdu)
{
static constexpr uint16_t kBufSize = 255;
char buf[kBufSize];
StringWriter writer(buf, sizeof(buf));

writer.AppendHexBytes(aFrame->mPsdu, aFrame->mLength);
Output(", len:%u, psdu:%s", aFrame->mLength, buf);
}

Output("\r\n");

if (mReceiveConfig.mReceiveCount >= mReceiveConfig.mNumFrames)
{
mReceiveConfig.mIsEnabled = false;

if (!mReceiveConfig.mIsAsyncCommand)
{
Output("OT_ERROR_NONE");
}
}

exit:
return;
}

void Diags::ReceiveDone(otRadioFrame *aFrame, Error aError)
{
if (aError == kErrorNone)
{
OutputReceivedFrame(aFrame);

// for sensitivity test, only record the rssi and lqi for the first and last packet
if (mStats.mReceivedPackets == 0)
{
Expand Down Expand Up @@ -910,7 +1030,7 @@ Error Diags::ProcessGpio(uint8_t aArgsLength, char *aArgs[])

void Diags::AppendErrorResult(Error aError)
{
if (aError != kErrorNone)
if ((aError != kErrorNone) && (aError != kErrorPending))
{
Output("failed\r\nstatus %#x\r\n", aError);
}
Expand Down
26 changes: 26 additions & 0 deletions src/core/diags/factory_diags.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,28 @@ class Diags : public InstanceLocator, private NonCopyable
RawPowerSetting mRawPowerSetting;
};

struct ReceiveConfig
{
ReceiveConfig(void)
: mIsEnabled(false)
, mIsAsyncCommand(false)
, mShowRssi(true)
, mShowLqi(true)
, mShowPsdu(false)
, mReceiveCount(0)
, mNumFrames(0)
{
}

bool mIsEnabled : 1;
bool mIsAsyncCommand : 1;
bool mShowRssi : 1;
bool mShowLqi : 1;
bool mShowPsdu : 1;
uint16_t mReceiveCount;
uint16_t mNumFrames;
};

Error ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[]);
Error ProcessChannel(uint8_t aArgsLength, char *aArgs[]);
Error ProcessFrame(uint8_t aArgsLength, char *aArgs[]);
Expand All @@ -198,6 +220,9 @@ class Diags : public InstanceLocator, private NonCopyable

Error GetRawPowerSetting(RawPowerSetting &aRawPowerSetting);
Error GetPowerSettings(uint8_t aChannel, PowerSettings &aPowerSettings);
Error ParseReceiveConfigFormat(const char *aFormat, ReceiveConfig &aConfig);
Error RadioReceive(void);
void OutputReceivedFrame(const otRadioFrame *aFrame);

void TransmitPacket(void);
void Output(const char *aFormat, ...);
Expand All @@ -223,6 +248,7 @@ class Diags : public InstanceLocator, private NonCopyable
bool mDiagSendOn : 1;
#endif

ReceiveConfig mReceiveConfig;
otDiagOutputCallback mOutputCallback;
void *mOutputContext;
};
Expand Down

0 comments on commit 971f05f

Please sign in to comment.