Add more flexibility to diagnostic module (#1238)

* Add more flexibility to diagnostic module

- Pass otInstance to otPlatDiagProcess
- Add handler for channel change in diag.c
- Add handler for tx power change in diag.c
- Add handler for frame received in diag.c
- Add handler for alarm fired in diag.c
- Add support for new diag.c handlers in diag_process.cpp

* Add custom diagnostic commands to nrf52840

* Minor fixes
This commit is contained in:
Kamil Sroka
2017-02-04 16:46:12 -08:00
committed by Jonathan Hui
parent 64ddc4b1dd
commit b293954a67
6 changed files with 372 additions and 26 deletions
+28 -5
View File
@@ -35,20 +35,21 @@
#include <openthread.h>
#include <platform/alarm.h>
#include <platform/radio.h>
#include "platform-cc2538.h"
/**
* diagnostics mode flag.
* Diagnostics mode variables.
*
*/
static bool sDiagMode = false;
void otPlatDiagProcess(int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
{
// add more plarform specific diagnostics features here
// Add more plarform specific diagnostics features here.
snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]);
(void)argc;
(void) argc;
(void) aInstance;
}
void otPlatDiagModeSet(bool aMode)
@@ -60,3 +61,25 @@ bool otPlatDiagModeGet()
{
return sDiagMode;
}
void otPlatDiagChannelSet(uint8_t aChannel)
{
(void) aChannel;
}
void otPlatDiagTxPowerSet(int8_t aTxPower)
{
(void) aTxPower;
}
void otPlatDiagRadioReceived(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError)
{
(void) aInstance;
(void) aFrame;
(void) aError;
}
void otPlatDiagAlarmCallback(otInstance *aInstance)
{
(void) aInstance;
}
+258 -5
View File
@@ -28,21 +28,194 @@
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <inttypes.h>
#include <platform/diag.h>
#include <platform/alarm.h>
#include <platform/radio.h>
#include <common/code_utils.hpp>
#include <common/logging.hpp>
struct PlatformDiagCommand
{
const char *mName;
void (*mCommand)(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen);
};
struct PlatformDiagMessage
{
const char mMessageDescriptor[11];
uint8_t mChannel;
int16_t mID;
uint32_t mCnt;
};
/**
* Diagnostics mode flag.
* Diagnostics mode variables.
*
*/
static bool sDiagMode = false;
static bool sListen = false;
static bool sTransmitActive = false;
static uint8_t sChannel = 20;
static int8_t sTxPower = 0;
static uint32_t sTxPeriod = 1;
static int32_t sTxCount = 0;
static int32_t sTxRequestedCount = 1;
static int16_t sID = -1;
static struct PlatformDiagMessage sDiagMessage = {.mMessageDescriptor = "DiagMessage", .mChannel = 0, .mID = 0, .mCnt = 0};
void otPlatDiagProcess(int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
static ThreadError parseLong(char *argv, long *aValue)
{
// Add more plarform specific diagnostics features here.
snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]);
(void)argc;
char *endptr;
*aValue = strtol(argv, &endptr, 0);
return (*endptr == '\0') ? kThreadError_None : kThreadError_Parse;
}
static void appendErrorResult(ThreadError aError, char *aOutput, size_t aOutputMaxLen)
{
if (aError != kThreadError_None)
{
snprintf(aOutput, aOutputMaxLen, "failed\r\nstatus %#x\r\n", aError);
}
}
static void processListen(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
{
(void) aInstance;
ThreadError error = kThreadError_None;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
if (argc == 0)
{
snprintf(aOutput, aOutputMaxLen, "listen: %s\r\n", sListen == true ? "yes" : "no");
}
else
{
long value;
SuccessOrExit(error = parseLong(argv[0], &value));
sListen = (bool)(value);
snprintf(aOutput, aOutputMaxLen, "set listen to %s\r\nstatus 0x%02x\r\n", sListen == true ? "yes" : "no", error);
}
exit:
appendErrorResult(error, aOutput, aOutputMaxLen);
}
static void processID(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
{
(void) aInstance;
ThreadError error = kThreadError_None;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
if (argc == 0)
{
snprintf(aOutput, aOutputMaxLen, "ID: %" PRId16 "\r\n", sID);
}
else
{
long value;
SuccessOrExit(error = parseLong(argv[0], &value));
VerifyOrExit(value >= 0, error = kThreadError_InvalidArgs);
sID = (int16_t)(value);
snprintf(aOutput, aOutputMaxLen, "set ID to %" PRId16 "\r\nstatus 0x%02x\r\n", sID, error);
}
exit:
appendErrorResult(error, aOutput, aOutputMaxLen);
}
static void processTransmit(otInstance *aInstance, int argc, char *argv[], char *aOutput,
size_t aOutputMaxLen)
{
ThreadError error = kThreadError_None;
VerifyOrExit(otPlatDiagModeGet(), error = kThreadError_InvalidState);
if (argc == 0)
{
snprintf(aOutput, aOutputMaxLen, "transmit will send %" PRId32 " diagnostic messages with %" PRIu32
" ms interval\r\nstatus 0x%02x\r\n",
sTxRequestedCount, sTxPeriod, error);
}
else if (strcmp(argv[0], "stop") == 0)
{
otPlatAlarmStop(aInstance);
snprintf(aOutput, aOutputMaxLen, "diagnostic message transmission is stopped\r\nstatus 0x%02x\r\n", error);
sTransmitActive = false;
}
else if (strcmp(argv[0], "start") == 0)
{
otPlatAlarmStop(aInstance);
sTransmitActive = true;
sTxCount = sTxRequestedCount;
uint32_t now = otPlatAlarmGetNow();
otPlatAlarmStartAt(aInstance, now, sTxPeriod);
snprintf(aOutput, aOutputMaxLen, "sending %" PRId32 " diagnostic messages with %" PRIu32
" ms interval\r\nstatus 0x%02x\r\n",
sTxRequestedCount, sTxPeriod, error);
}
else if (strcmp(argv[0], "interval") == 0)
{
long value;
VerifyOrExit(argc == 2, error = kThreadError_InvalidArgs);
SuccessOrExit(error = parseLong(argv[1], &value));
VerifyOrExit(value > 0, error = kThreadError_InvalidArgs);
sTxPeriod = (uint32_t)(value);
snprintf(aOutput, aOutputMaxLen, "set diagnostic messages interval to %" PRIu32 " ms\r\nstatus 0x%02x\r\n", sTxPeriod,
error);
}
else if (strcmp(argv[0], "count") == 0)
{
long value;
VerifyOrExit(argc == 2, error = kThreadError_InvalidArgs);
SuccessOrExit(error = parseLong(argv[1], &value));
VerifyOrExit((value > 0) || (value == -1), error = kThreadError_InvalidArgs);
sTxRequestedCount = (uint32_t)(value);
snprintf(aOutput, aOutputMaxLen, "set diagnostic messages count to %" PRId32 "\r\nstatus 0x%02x\r\n", sTxRequestedCount,
error);
}
exit:
appendErrorResult(error, aOutput, aOutputMaxLen);
}
const struct PlatformDiagCommand sCommands[] =
{
{"listen", &processListen },
{"transmit", &processTransmit },
{"id", &processID }
};
void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
{
uint32_t i;
for (i = 0; i < sizeof(sCommands) / sizeof(sCommands[0]); i++)
{
if (strcmp(argv[0], sCommands[i].mName) == 0)
{
sCommands[i].mCommand(aInstance, argc - 1, argc > 1 ? &argv[1] : NULL, aOutput, aOutputMaxLen);
break;
}
}
if (i == sizeof(sCommands) / sizeof(sCommands[0]))
{
snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]);
}
}
void otPlatDiagModeSet(bool aMode)
@@ -54,3 +227,83 @@ bool otPlatDiagModeGet()
{
return sDiagMode;
}
void otPlatDiagChannelSet(uint8_t aChannel)
{
sChannel = aChannel;
}
void otPlatDiagTxPowerSet(int8_t aTxPower)
{
sTxPower = aTxPower;
}
void otPlatDiagRadioReceived(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError)
{
(void) aInstance;
if (sListen && (aError == kThreadError_None))
{
if (aFrame->mLength == sizeof(struct PlatformDiagMessage))
{
struct PlatformDiagMessage *message = (struct PlatformDiagMessage *)aFrame->mPsdu;
if (strncmp(message->mMessageDescriptor, "DiagMessage", 11) == 0)
{
otPlatLog(kLogLevelDebg, kLogRegionPlatform,
"{\"Frame\":{"
"\"LocalChannel\":%u ,"
"\"RemoteChannel\":%u,"
"\"CNT\":%" PRIu32 ","
"\"LocalID\":%" PRId16 ","
"\"RemoteID\":%" PRId16 ","
"\"RSSI\":%d"
"}}\r\n",
aFrame->mChannel,
message->mChannel,
message->mCnt,
sID,
message->mID,
aFrame->mPower
);
}
}
}
}
void otPlatDiagAlarmCallback(otInstance *aInstance)
{
if (sTransmitActive)
{
if ((sTxCount > 0) || (sTxCount == -1))
{
RadioPacket *sTxPacket = otPlatRadioGetTransmitBuffer(aInstance);
sTxPacket->mLength = sizeof(struct PlatformDiagMessage);
sTxPacket->mChannel = sChannel;
sTxPacket->mPower = sTxPower;
sDiagMessage.mChannel = sTxPacket->mChannel;
sDiagMessage.mID = sID;
memcpy(sTxPacket->mPsdu, &sDiagMessage, sizeof(struct PlatformDiagMessage));
otPlatRadioTransmit(aInstance, sTxPacket);
sDiagMessage.mCnt++;
if (sTxCount != -1)
{
sTxCount--;
}
uint32_t now = otPlatAlarmGetNow();
otPlatAlarmStartAt(aInstance, now, sTxPeriod);
}
else
{
sTransmitActive = false;
otPlatAlarmStop(aInstance);
otPlatLog(kLogLevelDebg, kLogRegionPlatform, "Transmit done");
}
}
}
+28 -4
View File
@@ -37,18 +37,20 @@
#include <openthread.h>
#include <platform/alarm.h>
#include <platform/radio.h>
/**
* diagnostics mode flag.
* Diagnostics mode variables.
*
*/
static bool sDiagMode = false;
void otPlatDiagProcess(int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen)
{
// no more diagnostics features for Posix platform
// Add more plarform specific diagnostics features here.
snprintf(aOutput, aOutputMaxLen, "diag feature '%s' is not supported\r\n", argv[0]);
(void)argc;
(void) argc;
(void) aInstance;
}
void otPlatDiagModeSet(bool aMode)
@@ -60,3 +62,25 @@ bool otPlatDiagModeGet()
{
return sDiagMode;
}
void otPlatDiagChannelSet(uint8_t aChannel)
{
(void) aChannel;
}
void otPlatDiagTxPowerSet(int8_t aTxPower)
{
(void) aTxPower;
}
void otPlatDiagRadioReceived(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError)
{
(void) aInstance;
(void) aFrame;
(void) aError;
}
void otPlatDiagAlarmCallback(otInstance *aInstance)
{
(void) aInstance;
}
+37 -6
View File
@@ -39,6 +39,10 @@
#include <stdint.h>
#include <stddef.h>
#include <platform/radio.h>
#include <openthread-types.h>
#ifdef __cplusplus
extern "C" {
#endif
@@ -57,15 +61,16 @@ extern "C" {
/**
* Process the platform specific diagnostics features.
*
* @param[in] argc The argument counter of diagnostics command line.
* @param[in] argv The argument vector of diagnostics command line.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
* @param[in] aInstance The OpenThread instance for current request.
* @param[in] argc The argument counter of diagnostics command line.
* @param[in] argv The argument vector of diagnostics command line.
* @param[out] aOutput The diagnostics execution result.
* @param[in] aOutputMaxLen The output buffer size.
*/
void otPlatDiagProcess(int argc, char *argv[], char *aOutput, size_t aOutputMaxLen);
void otPlatDiagProcess(otInstance *aInstance, int argc, char *argv[], char *aOutput, size_t aOutputMaxLen);
/**
* Set diagnostics mode.
* Set diagnostics mode.
*/
void otPlatDiagModeSet(bool aMode);
@@ -74,6 +79,32 @@ void otPlatDiagModeSet(bool aMode);
*/
bool otPlatDiagModeGet(void);
/**
* Set diagnostics channel.
*/
void otPlatDiagChannelSet(uint8_t aChannel);
/**
* Set diagnostics tx power.
*/
void otPlatDiagTxPowerSet(int8_t aTxPower);
/**
* Process the platform specific received frame parsing.
*
* @param[in] aInstance The OpenThread instance for current request.
* @param[in] aFrame The received radio frame.
* @param[in] aError The received radio frame status.
*/
void otPlatDiagRadioReceived(otInstance *aInstance, RadioPacket *aFrame, ThreadError aError);
/**
* Process the platform specific alarm callback.
*
* @param[in] aInstance The OpenThread instance for current request.
*/
void otPlatDiagAlarmCallback(otInstance *aInstance);
#ifdef __cplusplus
} // end of extern "C"
#endif
+20 -6
View File
@@ -62,6 +62,7 @@ uint8_t Diag::sTxLen;
uint32_t Diag::sTxPeriod;
uint32_t Diag::sTxPackets;
RadioPacket * Diag::sTxPacket;
bool Diag::sRepeatActive;
otInstance *Diag::sContext;
@@ -73,8 +74,11 @@ void Diag::Init(otInstance *aInstance)
sTxPeriod = 0;
sTxLen = 0;
sTxPackets = 0;
sRepeatActive = false;
memset(&sStats, 0, sizeof(struct DiagStats));
sTxPacket = otPlatRadioGetTransmitBuffer(sContext);
otPlatDiagChannelSet(sChannel);
otPlatDiagTxPowerSet(sTxPower);
}
char *Diag::ProcessCmd(int argc, char *argv[])
@@ -99,7 +103,7 @@ char *Diag::ProcessCmd(int argc, char *argv[])
// more platform specific features will be processed under platform layer
if (i == sizeof(sCommands) / sizeof(sCommands[0]))
{
otPlatDiagProcess(argc, argv, sDiagOutput, sizeof(sDiagOutput));
otPlatDiagProcess(sContext, argc, argv, sDiagOutput, sizeof(sDiagOutput));
}
}
@@ -190,7 +194,6 @@ void Diag::TxPacket()
{
sTxPacket->mPsdu[i] = i;
}
otPlatRadioTransmit(sContext, sTxPacket);
}
@@ -214,6 +217,7 @@ void Diag::ProcessChannel(int argc, char *argv[], char *aOutput, size_t aOutputM
// listen on the set channel immediately
otPlatRadioReceive(sContext, sChannel);
otPlatDiagChannelSet(sChannel);
snprintf(aOutput, aOutputMaxLen, "set channel to %d\r\nstatus 0x%02x\r\n", sChannel, error);
}
@@ -237,6 +241,7 @@ void Diag::ProcessPower(int argc, char *argv[], char *aOutput, size_t aOutputMax
SuccessOrExit(error = ParseLong(argv[0], value));
sTxPower = static_cast<int8_t>(value);
otPlatDiagTxPowerSet(sTxPower);
snprintf(aOutput, aOutputMaxLen, "set tx power to %d dBm\r\nstatus 0x%02x\r\n", sTxPower, error);
}
@@ -276,6 +281,7 @@ void Diag::ProcessRepeat(int argc, char *argv[], char *aOutput, size_t aOutputMa
if (strcmp(argv[0], "stop") == 0)
{
otPlatAlarmStop(sContext);
sRepeatActive = false;
snprintf(aOutput, aOutputMaxLen, "repeated packet transmission is stopped\r\nstatus 0x%02x\r\n", error);
}
else
@@ -291,6 +297,7 @@ void Diag::ProcessRepeat(int argc, char *argv[], char *aOutput, size_t aOutputMa
VerifyOrExit(value <= kMaxPHYPacketSize, error = kThreadError_InvalidArgs);
sTxLen = static_cast<uint8_t>(value);
sRepeatActive = true;
uint32_t now = otPlatAlarmGetNow();
otPlatAlarmStartAt(sContext, now, sTxPeriod);
snprintf(aOutput, aOutputMaxLen, "sending packets of length %#x at the delay of %#x ms\r\nstatus 0x%02x\r\n", static_cast<int>(sTxLen), static_cast<int>(sTxPeriod), error);
@@ -359,16 +366,23 @@ void Diag::DiagReceiveDone(otInstance *aInstance, RadioPacket *aFrame, ThreadErr
sStats.received_packets++;
}
otPlatDiagRadioReceived(aInstance, aFrame, aError);
otPlatRadioReceive(aInstance, sChannel);
}
void Diag::AlarmFired(otInstance *aInstance)
{
uint32_t now = otPlatAlarmGetNow();
if(sRepeatActive)
{
uint32_t now = otPlatAlarmGetNow();
TxPacket();
otPlatAlarmStartAt(aInstance, now, sTxPeriod);
TxPacket();
otPlatAlarmStartAt(aInstance, now, sTxPeriod);
}
else
{
otPlatDiagAlarmCallback(aInstance);
}
}
extern "C" void otPlatDiagAlarmFired(otInstance *aInstance)
+1
View File
@@ -94,6 +94,7 @@ private:
static uint32_t sTxPackets;
static RadioPacket *sTxPacket;
static otInstance *sContext;
static bool sRepeatActive;
};
} // namespace Diagnostics