Skip to content

Commit 971f05f

Browse files
authored
[diag] add diag receive command to show received specified number of 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.
1 parent 93ef72a commit 971f05f

File tree

4 files changed

+183
-7
lines changed

4 files changed

+183
-7
lines changed

src/cli/cli.cpp

+11-1
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,17 @@ void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments, void
199199
static_cast<Interpreter *>(aContext)->HandleDiagOutput(aFormat, aArguments);
200200
}
201201

202-
void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments) { OutputFormatV(aFormat, aArguments); }
202+
void Interpreter::HandleDiagOutput(const char *aFormat, va_list aArguments)
203+
{
204+
if (strcmp(aFormat, "OT_ERROR_NONE") == 0)
205+
{
206+
OutputResult(OT_ERROR_NONE);
207+
}
208+
else
209+
{
210+
OutputFormatV(aFormat, aArguments);
211+
}
212+
}
203213
#endif
204214

205215
template <> otError Interpreter::Process<Cmd("version")>(Arg aArgs[])

src/core/diags/README.md

+20
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,26 @@ set radio from sleep to receive on channel 11
218218
status 0x00
219219
```
220220

221+
### diag radio receive \[async\] \<number\> \[lpr\]
222+
223+
Set the radio to receive mode and receive a specified number of frames.
224+
225+
- async: Use the non-blocking mode.
226+
- number: The number of frames expected to be received.
227+
- l: Show Lqi.
228+
- p: Show Psdu.
229+
- r: Show Rssi.
230+
231+
```bash
232+
> diag radio receive 5 lpr
233+
0, rssi:-49, lqi:119, len:10, psdu:000102030405060771e
234+
1, rssi:-51, lqi:112, len:10, psdu:000102030405060771e
235+
2, rssi:-42, lqi:120, len:10, psdu:000102030405060771e
236+
3, rssi:-54, lqi:111, len:10, psdu:000102030405060771e
237+
4, rssi:-56, lqi:108, len:10, psdu:000102030405060771e
238+
Done
239+
```
240+
221241
### diag radio state
222242

223243
Return the state of the radio.

src/core/diags/factory_diags.cpp

+126-6
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,50 @@ void Diags::TransmitPacket(void)
587587
IgnoreError(Get<Radio>().Transmit(*static_cast<Mac::TxFrame *>(mTxPacket)));
588588
}
589589

590+
Error Diags::ParseReceiveConfigFormat(const char *aFormat, ReceiveConfig &aConfig)
591+
{
592+
Error error = kErrorNone;
593+
594+
VerifyOrExit(aFormat != nullptr, error = kErrorInvalidArgs);
595+
596+
for (const char *arg = aFormat; *arg != '\0'; arg++)
597+
{
598+
switch (*arg)
599+
{
600+
case 'r':
601+
aConfig.mShowRssi = true;
602+
break;
603+
604+
case 'l':
605+
aConfig.mShowLqi = true;
606+
break;
607+
608+
case 'p':
609+
aConfig.mShowPsdu = true;
610+
break;
611+
612+
default:
613+
ExitNow(error = OT_ERROR_INVALID_ARGS);
614+
}
615+
}
616+
617+
exit:
618+
return error;
619+
}
620+
621+
Error Diags::RadioReceive(void)
622+
{
623+
Error error;
624+
625+
SuccessOrExit(error = Get<Radio>().Receive(mChannel));
626+
SuccessOrExit(error = Get<Radio>().SetTransmitPower(mTxPower));
627+
otPlatDiagChannelSet(mChannel);
628+
otPlatDiagTxPowerSet(mTxPower);
629+
630+
exit:
631+
return error;
632+
}
633+
590634
Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[])
591635
{
592636
Error error = kErrorInvalidArgs;
@@ -601,12 +645,44 @@ Error Diags::ProcessRadio(uint8_t aArgsLength, char *aArgs[])
601645
}
602646
else if (StringMatch(aArgs[0], "receive"))
603647
{
604-
SuccessOrExit(error = Get<Radio>().Receive(mChannel));
605-
SuccessOrExit(error = Get<Radio>().SetTransmitPower(mTxPower));
606-
otPlatDiagChannelSet(mChannel);
607-
otPlatDiagTxPowerSet(mTxPower);
648+
ReceiveConfig receiveConfig;
649+
650+
aArgs++;
651+
aArgsLength--;
652+
653+
if (aArgsLength == 0)
654+
{
655+
SuccessOrExit(error = RadioReceive());
656+
Output("set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", mChannel, error);
657+
ExitNow();
658+
}
608659

609-
Output("set radio from sleep to receive on channel %d\r\nstatus 0x%02x\r\n", mChannel, error);
660+
if (StringMatch(aArgs[0], "async"))
661+
{
662+
aArgs++;
663+
aArgsLength--;
664+
receiveConfig.mIsAsyncCommand = true;
665+
}
666+
667+
VerifyOrExit(aArgsLength > 0);
668+
SuccessOrExit(error = Utils::CmdLineParser::ParseAsUint16(aArgs[0], receiveConfig.mNumFrames));
669+
aArgs++;
670+
aArgsLength--;
671+
672+
if (aArgsLength > 0)
673+
{
674+
SuccessOrExit(error = ParseReceiveConfigFormat(aArgs[0], receiveConfig));
675+
}
676+
677+
SuccessOrExit(error = RadioReceive());
678+
679+
receiveConfig.mIsEnabled = true;
680+
mReceiveConfig = receiveConfig;
681+
682+
if (!mReceiveConfig.mIsAsyncCommand)
683+
{
684+
error = kErrorPending;
685+
}
610686
}
611687
else if (StringMatch(aArgs[0], "state"))
612688
{
@@ -668,10 +744,54 @@ void Diags::AlarmFired(void)
668744
}
669745
}
670746

747+
void Diags::OutputReceivedFrame(const otRadioFrame *aFrame)
748+
{
749+
VerifyOrExit(mReceiveConfig.mIsEnabled && (aFrame != nullptr));
750+
751+
Output("%u", mReceiveConfig.mReceiveCount++);
752+
753+
if (mReceiveConfig.mShowRssi)
754+
{
755+
Output(", rssi:%d", aFrame->mInfo.mRxInfo.mRssi);
756+
}
757+
758+
if (mReceiveConfig.mShowLqi)
759+
{
760+
Output(", lqi:%u", aFrame->mInfo.mRxInfo.mLqi);
761+
}
762+
763+
if (mReceiveConfig.mShowPsdu)
764+
{
765+
static constexpr uint16_t kBufSize = 255;
766+
char buf[kBufSize];
767+
StringWriter writer(buf, sizeof(buf));
768+
769+
writer.AppendHexBytes(aFrame->mPsdu, aFrame->mLength);
770+
Output(", len:%u, psdu:%s", aFrame->mLength, buf);
771+
}
772+
773+
Output("\r\n");
774+
775+
if (mReceiveConfig.mReceiveCount >= mReceiveConfig.mNumFrames)
776+
{
777+
mReceiveConfig.mIsEnabled = false;
778+
779+
if (!mReceiveConfig.mIsAsyncCommand)
780+
{
781+
Output("OT_ERROR_NONE");
782+
}
783+
}
784+
785+
exit:
786+
return;
787+
}
788+
671789
void Diags::ReceiveDone(otRadioFrame *aFrame, Error aError)
672790
{
673791
if (aError == kErrorNone)
674792
{
793+
OutputReceivedFrame(aFrame);
794+
675795
// for sensitivity test, only record the rssi and lqi for the first and last packet
676796
if (mStats.mReceivedPackets == 0)
677797
{
@@ -910,7 +1030,7 @@ Error Diags::ProcessGpio(uint8_t aArgsLength, char *aArgs[])
9101030

9111031
void Diags::AppendErrorResult(Error aError)
9121032
{
913-
if (aError != kErrorNone)
1033+
if ((aError != kErrorNone) && (aError != kErrorPending))
9141034
{
9151035
Output("failed\r\nstatus %#x\r\n", aError);
9161036
}

src/core/diags/factory_diags.hpp

+26
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,28 @@ class Diags : public InstanceLocator, private NonCopyable
177177
RawPowerSetting mRawPowerSetting;
178178
};
179179

180+
struct ReceiveConfig
181+
{
182+
ReceiveConfig(void)
183+
: mIsEnabled(false)
184+
, mIsAsyncCommand(false)
185+
, mShowRssi(true)
186+
, mShowLqi(true)
187+
, mShowPsdu(false)
188+
, mReceiveCount(0)
189+
, mNumFrames(0)
190+
{
191+
}
192+
193+
bool mIsEnabled : 1;
194+
bool mIsAsyncCommand : 1;
195+
bool mShowRssi : 1;
196+
bool mShowLqi : 1;
197+
bool mShowPsdu : 1;
198+
uint16_t mReceiveCount;
199+
uint16_t mNumFrames;
200+
};
201+
180202
Error ParseCmd(char *aString, uint8_t &aArgsLength, char *aArgs[]);
181203
Error ProcessChannel(uint8_t aArgsLength, char *aArgs[]);
182204
Error ProcessFrame(uint8_t aArgsLength, char *aArgs[]);
@@ -198,6 +220,9 @@ class Diags : public InstanceLocator, private NonCopyable
198220

199221
Error GetRawPowerSetting(RawPowerSetting &aRawPowerSetting);
200222
Error GetPowerSettings(uint8_t aChannel, PowerSettings &aPowerSettings);
223+
Error ParseReceiveConfigFormat(const char *aFormat, ReceiveConfig &aConfig);
224+
Error RadioReceive(void);
225+
void OutputReceivedFrame(const otRadioFrame *aFrame);
201226

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

251+
ReceiveConfig mReceiveConfig;
226252
otDiagOutputCallback mOutputCallback;
227253
void *mOutputContext;
228254
};

0 commit comments

Comments
 (0)