[posix] add radio url (#4935)

Radio url provides a unified interface for users to specify the radio
peripheral device and arguments to the OpenThread core stack.
This commit is contained in:
Jiacheng Guo
2020-05-29 17:34:29 -07:00
committed by GitHub
parent b0b2591bc0
commit 115616c6bf
20 changed files with 497 additions and 220 deletions
+1
View File
@@ -281,6 +281,7 @@ LOCAL_SRC_FILES := \
src/posix/platform/misc.cpp \ src/posix/platform/misc.cpp \
src/posix/platform/netif.cpp \ src/posix/platform/netif.cpp \
src/posix/platform/radio.cpp \ src/posix/platform/radio.cpp \
src/posix/platform/radio_url.cpp \
src/posix/platform/settings.cpp \ src/posix/platform/settings.cpp \
src/posix/platform/spi_interface.cpp \ src/posix/platform/spi_interface.cpp \
src/posix/platform/system.cpp \ src/posix/platform/system.cpp \
+5 -4
View File
@@ -93,12 +93,12 @@ EOF
echo "Step 2. Start retrieving dataset from Radio..." echo "Step 2. Start retrieving dataset from Radio..."
RADIO_NCP_PATH="$(pwd)/$(ls output/*linux*/bin/ot-ncp-ftd)" RADIO_NCP_PATH="$(pwd)/$(ls output/*linux*/bin/ot-ncp-ftd)"
"$(pwd)/$(ls output/posix/*linux*/bin/ot-ncp)" -n --radio-version --ncp-dataset -- "${RADIO_NCP_PATH}" 1 "$(pwd)/$(ls output/posix/*linux*/bin/ot-ncp)" -n --radio-version "spinel+hdlc+forkpty://${RADIO_NCP_PATH}?arg=1&ncp-dataset=1"
echo "Step 3. Start posix app and check whether PAN dataset is the same..." echo "Step 3. Start posix app and check whether PAN dataset is the same..."
RADIO_RCP_PATH="$(pwd)/$(ls output/*linux*/bin/ot-rcp)" RADIO_RCP_PATH="$(pwd)/$(ls output/*linux*/bin/ot-rcp)"
OT_CLI_CMD="$(pwd)/$(ls output/posix/*linux*/bin/ot-cli) ${RADIO_RCP_PATH} 1" OT_CLI_CMD="$(pwd)/$(ls output/posix/*linux*/bin/ot-cli) spinel+hdlc+forkpty://${RADIO_RCP_PATH}?arg=1"
expect <<EOF expect <<EOF
spawn ${OT_CLI_CMD} spawn ${OT_CLI_CMD}
@@ -126,8 +126,9 @@ expect eof
EOF EOF
echo "Step 4. Start posix app and check whether it can get radio firmware version..." echo "Step 4. Start posix app and check whether it can get radio firmware version..."
RADIO_VERSION="$("$(pwd)/$(ls output/posix/*linux*/bin/ot-cli)" -n --radio-version --ncp-dataset -- "${RADIO_RCP_PATH}" 1)" || true RADIO_VERSION="$("$(pwd)/$(ls output/posix/*linux*/bin/ot-cli)" -n --radio-version "spinel+hdlc+forkpty://${RADIO_RCP_PATH}?arg=1&ncp-dataset=1")" || true
test -n "${RADIO_VERSION}" echo "${RADIO_VERSION}"
test -n "{RADIO_VERSION}"
} }
main() main()
+5 -7
View File
@@ -81,12 +81,10 @@ check()
# Cover setting a valid network interface name. # Cover setting a valid network interface name.
readonly VALID_NETIF_NAME="wan$(date +%H%M%S)" readonly VALID_NETIF_NAME="wan$(date +%H%M%S)"
local options=( RADIO_URL="spinel+hdlc+uart://${CORE_PTY}?max-power-table=11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26"
'--max-power-table=11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26'
)
if [[ ${DAEMON} == 1 ]]; then if [[ ${DAEMON} == 1 ]]; then
sudo "$(pwd)/$(ls output/posix/*linux*/bin/ot-daemon)" "${options[@]}" -I "${VALID_NETIF_NAME}" "${CORE_PTY}" & sudo "$(pwd)/$(ls output/posix/*linux*/bin/ot-daemon)" -I "${VALID_NETIF_NAME}" "${RADIO_URL}" &
sleep 1 sleep 1
OT_CLI_CMD="$(pwd)/$(ls output/posix/*linux*/bin/ot-ctl)" OT_CLI_CMD="$(pwd)/$(ls output/posix/*linux*/bin/ot-ctl)"
sudo "${OT_CLI_CMD}" panid 0xface | grep 'Done' || die 'failed to set panid with ot-ctl' sudo "${OT_CLI_CMD}" panid 0xface | grep 'Done' || die 'failed to set panid with ot-ctl'
@@ -96,14 +94,14 @@ check()
sudo "${OT_CLI_CMD}" factoryreset sudo "${OT_CLI_CMD}" factoryreset
else else
OT_CLI="$(pwd)/$(ls output/posix/*linux*/bin/ot-cli)" OT_CLI="$(pwd)/$(ls output/posix/*linux*/bin/ot-cli)"
sudo "${OT_CLI}" -I "${VALID_NETIF_NAME}" -n "${CORE_PTY}" sudo "${OT_CLI}" -I "${VALID_NETIF_NAME}" -n "${RADIO_URL}"
# Cover setting a too long(max is 15 characters) network interface name. # Cover setting a too long(max is 15 characters) network interface name.
# Expect exit code to be 2(OT_EXIT_INVALID_ARGUMENTS). # Expect exit code to be 2(OT_EXIT_INVALID_ARGUMENTS).
readonly INVALID_NETIF_NAME="wan0123456789123" readonly INVALID_NETIF_NAME="wan0123456789123"
sudo "${OT_CLI}" -I "${INVALID_NETIF_NAME}" -n "${CORE_PTY}" || test $? = 2 sudo "${OT_CLI}" -I "${INVALID_NETIF_NAME}" -n "${RADIO_URL}" || test $? = 2
OT_CLI_CMD="$(pwd)/$(ls output/posix/*linux*/bin/ot-cli) ${CORE_PTY}" OT_CLI_CMD="$(pwd)/$(ls output/posix/*linux*/bin/ot-cli) ${RADIO_URL}"
fi fi
sudo expect <<EOF | tee "${OT_OUTPUT}" & sudo expect <<EOF | tee "${OT_OUTPUT}" &
+6 -115
View File
@@ -75,6 +75,7 @@
#error "Unknown posix app type!" #error "Unknown posix app type!"
#endif #endif
#include <common/code_utils.hpp> #include <common/code_utils.hpp>
#include <common/logging.hpp>
#include <lib/platform/exit_code.h> #include <lib/platform/exit_code.h>
#include <openthread/openthread-system.h> #include <openthread/openthread-system.h>
@@ -102,88 +103,31 @@ void __gcov_flush();
enum enum
{ {
ARG_PRINT_RADIO_VERSION = 1001, ARG_PRINT_RADIO_VERSION = 1001,
ARG_NO_RADIO_RESET = 1002,
ARG_RESTORE_NCP_DATASET = 1003,
ARG_SPI_GPIO_INT_DEV = 1011,
ARG_SPI_GPIO_INT_LINE = 1012,
ARG_SPI_GPIO_RESET_DEV = 1013,
ARG_SPI_GPIO_RESET_LINE = 1014,
ARG_SPI_MODE = 1015,
ARG_SPI_SPEED = 1016,
ARG_SPI_CS_DELAY = 1017,
ARG_SPI_RESET_DELAY = 1018,
ARG_SPI_ALIGN_ALLOWANCE = 1019,
ARG_SPI_SMALL_PACKET = 1020,
ARG_MAX_POWER_TABLE = 1021,
}; };
static const struct option kOptions[] = {{"debug-level", required_argument, NULL, 'd'}, static const struct option kOptions[] = {{"debug-level", required_argument, NULL, 'd'},
{"dry-run", no_argument, NULL, 'n'}, {"dry-run", no_argument, NULL, 'n'},
{"help", no_argument, NULL, 'h'}, {"help", no_argument, NULL, 'h'},
{"interface-name", required_argument, NULL, 'I'}, {"interface-name", required_argument, NULL, 'I'},
{"no-reset", no_argument, NULL, ARG_NO_RADIO_RESET},
{"radio-version", no_argument, NULL, ARG_PRINT_RADIO_VERSION}, {"radio-version", no_argument, NULL, ARG_PRINT_RADIO_VERSION},
{"ncp-dataset", no_argument, NULL, ARG_RESTORE_NCP_DATASET},
{"time-speed", required_argument, NULL, 's'}, {"time-speed", required_argument, NULL, 's'},
{"verbose", no_argument, NULL, 'v'}, {"verbose", no_argument, NULL, 'v'},
#if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
{"max-power-table", required_argument, NULL, ARG_MAX_POWER_TABLE},
#endif
#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_SPI
{"gpio-int-dev", required_argument, NULL, ARG_SPI_GPIO_INT_DEV},
{"gpio-int-line", required_argument, NULL, ARG_SPI_GPIO_INT_LINE},
{"gpio-reset-dev", required_argument, NULL, ARG_SPI_GPIO_RESET_DEV},
{"gpio-reset-line", required_argument, NULL, ARG_SPI_GPIO_RESET_LINE},
{"spi-mode", required_argument, NULL, ARG_SPI_MODE},
{"spi-speed", required_argument, NULL, ARG_SPI_SPEED},
{"spi-cs-delay", required_argument, NULL, ARG_SPI_CS_DELAY},
{"spi-reset-delay", required_argument, NULL, ARG_SPI_RESET_DELAY},
{"spi-align-allowance", required_argument, NULL, ARG_SPI_ALIGN_ALLOWANCE},
{"spi-small-packet", required_argument, NULL, ARG_SPI_SMALL_PACKET},
#endif // OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_SPI
{0, 0, 0, 0}}; {0, 0, 0, 0}};
static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode) static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode)
{ {
fprintf(aStream, fprintf(aStream,
"Syntax:\n" "Syntax:\n"
" %s [Options] NodeId|Device|Command [DeviceConfig|CommandArgs]\n" " %s [Options] RadioURL\n"
"Options:\n" "Options:\n"
" -d --debug-level Debug level of logging.\n" " -d --debug-level Debug level of logging.\n"
" -h --help Display this usage information.\n" " -h --help Display this usage information.\n"
" -I --interface-name name Thread network interface name.\n" " -I --interface-name name Thread network interface name.\n"
" -n --dry-run Just verify if arguments is valid and radio spinel is compatible.\n" " -n --dry-run Just verify if arguments is valid and radio spinel is compatible.\n"
" --no-reset Do not send Spinel reset command to RCP on initialization.\n"
" --radio-version Print radio firmware version.\n" " --radio-version Print radio firmware version.\n"
" --ncp-dataset Retrieve and save NCP dataset to file.\n"
" -s --time-speed factor Time speed up factor.\n" " -s --time-speed factor Time speed up factor.\n"
" -v --verbose Also log to stderr.\n", " -v --verbose Also log to stderr.\n",
aProgramName); aProgramName);
#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_SPI
fprintf(aStream,
" --gpio-int-dev[=gpio-device-path]\n"
" Specify a path to the Linux sysfs-exported GPIO device for the\n"
" `I̅N̅T̅` pin. If not specified, `SPI` interface will fall back to\n"
" polling, which is inefficient.\n"
" --gpio-int-line[=line-offset]\n"
" The offset index of `I̅N̅T̅` pin for the associated GPIO device.\n"
" If not specified, `SPI` interface will fall back to polling,\n"
" which is inefficient.\n"
" --gpio-reset-dev[=gpio-device-path]\n"
" Specify a path to the Linux sysfs-exported GPIO device for the\n"
" `R̅E̅S̅` pin.\n"
" --gpio-reset-line[=line-offset]"
" The offset index of `R̅E̅S̅` pin for the associated GPIO device.\n"
" --spi-mode[=mode] Specify the SPI mode to use (0-3).\n"
" --spi-speed[=hertz] Specify the SPI speed in hertz.\n"
" --spi-cs-delay[=usec] Specify the delay after C̅S̅ assertion, in µsec.\n"
" --spi-reset-delay[=ms] Specify the delay after R̅E̅S̅E̅T̅ assertion, in milliseconds.\n"
" --spi-align-allowance[=n] Specify the maximum number of 0xFF bytes to clip from start of\n"
" MISO frame. Max value is 16.\n"
" --spi-small-packet=[n] Specify the smallest packet we can receive in a single transaction.\n"
" (larger packets will require two transactions). Default value is 32.\n");
#endif
#if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE #if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
fprintf(aStream, fprintf(aStream,
" --max-power-table Max power for channels in ascending order separated by commas,\n" " --max-power-table Max power for channels in ascending order separated by commas,\n"
@@ -191,6 +135,7 @@ static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode)
" the last value will be applied to all remaining channels.\n" " the last value will be applied to all remaining channels.\n"
" Special value 0x7f disables a channel.\n"); " Special value 0x7f disables a channel.\n");
#endif #endif
fprintf(aStream, "%s", otSysGetRadioUrlHelpString());
exit(aExitCode); exit(aExitCode);
} }
@@ -198,15 +143,8 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig)
{ {
memset(aConfig, 0, sizeof(*aConfig)); memset(aConfig, 0, sizeof(*aConfig));
aConfig->mPlatformConfig.mSpeedUpFactor = 1; aConfig->mPlatformConfig.mSpeedUpFactor = 1;
aConfig->mPlatformConfig.mResetRadio = true; aConfig->mLogLevel = OT_LOG_LEVEL_CRIT;
aConfig->mPlatformConfig.mSpiSpeed = OT_PLATFORM_CONFIG_SPI_DEFAULT_SPEED_HZ;
aConfig->mPlatformConfig.mSpiCsDelay = OT_PLATFORM_CONFIG_SPI_DEFAULT_CS_DELAY_US;
aConfig->mPlatformConfig.mSpiResetDelay = OT_PLATFORM_CONFIG_SPI_DEFAULT_RESET_DELAY_MS;
aConfig->mPlatformConfig.mSpiAlignAllowance = OT_PLATFORM_CONFIG_SPI_DEFAULT_ALIGN_ALLOWANCE;
aConfig->mPlatformConfig.mSpiSmallPacketSize = OT_PLATFORM_CONFIG_SPI_DEFAULT_SMALL_PACKET_SIZE;
aConfig->mPlatformConfig.mSpiMode = OT_PLATFORM_CONFIG_SPI_DEFAULT_MODE;
aConfig->mLogLevel = OT_LOG_LEVEL_CRIT;
optind = 1; optind = 1;
@@ -253,47 +191,6 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig)
case ARG_PRINT_RADIO_VERSION: case ARG_PRINT_RADIO_VERSION:
aConfig->mPrintRadioVersion = true; aConfig->mPrintRadioVersion = true;
break; break;
case ARG_NO_RADIO_RESET:
aConfig->mPlatformConfig.mResetRadio = false;
break;
case ARG_RESTORE_NCP_DATASET:
aConfig->mPlatformConfig.mRestoreDatasetFromNcp = true;
break;
case ARG_SPI_GPIO_INT_DEV:
aConfig->mPlatformConfig.mSpiGpioIntDevice = optarg;
break;
case ARG_SPI_GPIO_INT_LINE:
aConfig->mPlatformConfig.mSpiGpioIntLine = (uint8_t)atoi(optarg);
break;
case ARG_SPI_GPIO_RESET_DEV:
aConfig->mPlatformConfig.mSpiGpioResetDevice = optarg;
break;
case ARG_SPI_GPIO_RESET_LINE:
aConfig->mPlatformConfig.mSpiGpioResetLine = (uint8_t)atoi(optarg);
break;
case ARG_SPI_MODE:
aConfig->mPlatformConfig.mSpiMode = (uint8_t)atoi(optarg);
break;
case ARG_SPI_SPEED:
aConfig->mPlatformConfig.mSpiSpeed = (uint32_t)atoi(optarg);
break;
case ARG_SPI_CS_DELAY:
aConfig->mPlatformConfig.mSpiCsDelay = (uint16_t)atoi(optarg);
break;
case ARG_SPI_RESET_DELAY:
aConfig->mPlatformConfig.mSpiResetDelay = (uint32_t)atoi(optarg);
break;
case ARG_SPI_ALIGN_ALLOWANCE:
aConfig->mPlatformConfig.mSpiAlignAllowance = (uint8_t)atoi(optarg);
break;
case ARG_SPI_SMALL_PACKET:
aConfig->mPlatformConfig.mSpiSmallPacketSize = (uint8_t)atoi(optarg);
break;
#if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
case ARG_MAX_POWER_TABLE:
aConfig->mPlatformConfig.mMaxPowerTable = optarg;
break;
#endif
case '?': case '?':
PrintUsage(aArgVector[0], stderr, OT_EXIT_INVALID_ARGUMENTS); PrintUsage(aArgVector[0], stderr, OT_EXIT_INVALID_ARGUMENTS);
break; break;
@@ -307,13 +204,7 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig)
{ {
PrintUsage(aArgVector[0], stderr, OT_EXIT_INVALID_ARGUMENTS); PrintUsage(aArgVector[0], stderr, OT_EXIT_INVALID_ARGUMENTS);
} }
aConfig->mPlatformConfig.mRadioUrl = aArgVector[optind];
aConfig->mPlatformConfig.mRadioFile = aArgVector[optind];
if (optind + 1 < aArgCount)
{
aConfig->mPlatformConfig.mRadioConfig = aArgVector[optind + 1];
}
} }
static otInstance *InitInstance(int aArgCount, char *aArgVector[]) static otInstance *InitInstance(int aArgCount, char *aArgVector[])
+1
View File
@@ -67,6 +67,7 @@ add_library(openthread-posix
misc.cpp misc.cpp
netif.cpp netif.cpp
radio.cpp radio.cpp
radio_url.cpp
settings.cpp settings.cpp
spi_interface.cpp spi_interface.cpp
system.cpp system.cpp
+17 -1
View File
@@ -50,6 +50,7 @@ libopenthread_posix_a_SOURCES = \
misc.cpp \ misc.cpp \
netif.cpp \ netif.cpp \
radio.cpp \ radio.cpp \
radio_url.cpp \
settings.cpp \ settings.cpp \
spi_interface.cpp \ spi_interface.cpp \
system.cpp \ system.cpp \
@@ -62,6 +63,7 @@ noinst_HEADERS = \
hdlc_interface.hpp \ hdlc_interface.hpp \
openthread-posix-config.h \ openthread-posix-config.h \
platform-posix.h \ platform-posix.h \
radio_url.hpp \
$(NULL) $(NULL)
openthread_HEADERS = \ openthread_HEADERS = \
@@ -75,7 +77,7 @@ if OPENTHREAD_BUILD_COVERAGE
CLEANFILES = $(wildcard *.gcda *.gcno) CLEANFILES = $(wildcard *.gcda *.gcno)
endif # OPENTHREAD_BUILD_COVERAGE endif # OPENTHREAD_BUILD_COVERAGE
check_PROGRAMS = test-settings check_PROGRAMS = test-settings test-radio-url
test_settings_CPPFLAGS = \ test_settings_CPPFLAGS = \
-I$(top_srcdir)/include \ -I$(top_srcdir)/include \
@@ -90,8 +92,22 @@ test_settings_SOURCES = \
settings.cpp \ settings.cpp \
$(NULL) $(NULL)
test_radio_url_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/src \
-I$(top_srcdir)/src/core \
-I$(top_srcdir)/src/posix/platform/include \
-DOPENTHREAD_CONFIG_LOG_PLATFORM=0 \
-DSELF_TEST \
$(NULL)
test_radio_url_SOURCES = \
radio_url.cpp \
$(NULL)
TESTS = \ TESTS = \
test-settings \ test-settings \
test-radio-url \
$(NULL) $(NULL)
include $(abs_top_nlbuild_autotools_dir)/automake/post.am include $(abs_top_nlbuild_autotools_dir)/automake/post.am
+35 -39
View File
@@ -138,30 +138,30 @@ HdlcInterface::HdlcInterface(SpinelInterface::ReceiveFrameCallback aCallback,
{ {
} }
otError HdlcInterface::Init(const otPlatformConfig &aPlatformConfig) otError HdlcInterface::Init(Arguments &aArguments)
{ {
otError error = OT_ERROR_NONE; otError error = OT_ERROR_NONE;
struct stat st; struct stat st;
VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY); VerifyOrExit(mSockFd == -1, error = OT_ERROR_ALREADY);
VerifyOrDie(stat(aPlatformConfig.mRadioFile, &st) == 0, OT_EXIT_INVALID_ARGUMENTS); VerifyOrDie(stat(aArguments.GetPath(), &st) == 0, OT_EXIT_INVALID_ARGUMENTS);
if (S_ISCHR(st.st_mode)) if (S_ISCHR(st.st_mode))
{ {
mSockFd = OpenFile(aPlatformConfig.mRadioFile, aPlatformConfig.mRadioConfig); mSockFd = OpenFile(aArguments.GetPath(), aArguments);
VerifyOrExit(mSockFd != -1, error = OT_ERROR_INVALID_ARGS); VerifyOrExit(mSockFd != -1, error = OT_ERROR_INVALID_ARGS);
} }
#if OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE #if OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
else if (S_ISREG(st.st_mode)) else if (S_ISREG(st.st_mode))
{ {
mSockFd = ForkPty(aPlatformConfig.mRadioFile, aPlatformConfig.mRadioConfig); mSockFd = ForkPty(aArguments.GetPath(), aArguments.GetValue("arg"));
VerifyOrExit(mSockFd != -1, error = OT_ERROR_INVALID_ARGS); VerifyOrExit(mSockFd != -1, error = OT_ERROR_INVALID_ARGS);
} }
#endif // OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE #endif // OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
else else
{ {
otLogCritPlat("Radio file '%s' not supported", aPlatformConfig.mRadioFile); otLogCritPlat("Radio file '%s' not supported", aArguments.GetPath());
ExitNow(error = OT_ERROR_INVALID_ARGS); ExitNow(error = OT_ERROR_INVALID_ARGS);
} }
@@ -407,10 +407,12 @@ exit:
return error; return error;
} }
int HdlcInterface::OpenFile(const char *aFile, const char *aConfig) int HdlcInterface::OpenFile(const char *aFile, Arguments &aArguments)
{ {
int fd = -1; int fd = -1;
int rval = 0; int rval = 0;
const char *parity = aArguments.GetValue("uart-parity");
uint32_t baudrate = 115200;
fd = open(aFile, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC); fd = open(aFile, O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC);
if (fd == -1) if (fd == -1)
@@ -423,10 +425,8 @@ int HdlcInterface::OpenFile(const char *aFile, const char *aConfig)
{ {
struct termios tios; struct termios tios;
unsigned int speed = 115200; unsigned int speed = 115200;
int cstopb = 1; int stopBit = 1;
char parity = 'N';
char flow = 'N';
VerifyOrExit((rval = tcgetattr(fd, &tios)) == 0, OT_NOOP); VerifyOrExit((rval = tcgetattr(fd, &tios)) == 0, OT_NOOP);
@@ -434,29 +434,29 @@ int HdlcInterface::OpenFile(const char *aFile, const char *aConfig)
tios.c_cflag = CS8 | HUPCL | CREAD | CLOCAL; tios.c_cflag = CS8 | HUPCL | CREAD | CLOCAL;
// example: 115200N1H if (parity)
if (aConfig != NULL)
{ {
sscanf(aConfig, "%u%c%d%c", &speed, &parity, &cstopb, &flow); if (strncmp(parity, "odd", 3) == 0)
{
tios.c_cflag |= PARENB;
tios.c_cflag |= PARODD;
}
else if (strncmp(parity, "even", 4) == 0)
{
tios.c_cflag |= PARENB;
}
else
{
DieNow(OT_EXIT_INVALID_ARGUMENTS);
}
} }
switch (parity) if (aArguments.GetValue("uart-stop"))
{ {
case 'N': stopBit = atoi(aArguments.GetValue("uart-stop"));
break;
case 'E':
tios.c_cflag |= PARENB;
break;
case 'O':
tios.c_cflag |= (PARENB | PARODD);
break;
default:
// not supported
DieNow(OT_EXIT_INVALID_ARGUMENTS);
break;
} }
switch (cstopb) switch (stopBit)
{ {
case 1: case 1:
tios.c_cflag &= static_cast<unsigned long>(~CSTOPB); tios.c_cflag &= static_cast<unsigned long>(~CSTOPB);
@@ -469,7 +469,11 @@ int HdlcInterface::OpenFile(const char *aFile, const char *aConfig)
break; break;
} }
switch (speed) if (aArguments.GetValue("baudrate"))
{
baudrate = static_cast<uint32_t>(atoi(aArguments.GetValue("baudrate")));
}
switch (baudrate)
{ {
case 9600: case 9600:
speed = B9600; speed = B9600;
@@ -556,17 +560,9 @@ int HdlcInterface::OpenFile(const char *aFile, const char *aConfig)
break; break;
} }
switch (flow) if (aArguments.GetValue("uart-flow-control") != NULL)
{ {
case 'N':
break;
case 'H':
tios.c_cflag |= CRTSCTS; tios.c_cflag |= CRTSCTS;
break;
default:
// not supported
DieNow(OT_EXIT_INVALID_ARGUMENTS);
break;
} }
VerifyOrExit((rval = cfsetspeed(&tios, static_cast<speed_t>(speed))) == 0, perror("cfsetspeed")); VerifyOrExit((rval = cfsetspeed(&tios, static_cast<speed_t>(speed))) == 0, perror("cfsetspeed"));
+3 -3
View File
@@ -74,14 +74,14 @@ public:
* *
* @note This method should be called before reading and sending spinel frames to the interface. * @note This method should be called before reading and sending spinel frames to the interface.
* *
* @param[in] aPlatformConfig Platform configuration structure. * @param[in] aArguments Arguments parsed from radio url.
* *
* @retval OT_ERROR_NONE The interface is initialized successfully * @retval OT_ERROR_NONE The interface is initialized successfully
* @retval OT_ERROR_ALREADY The interface is already initialized. * @retval OT_ERROR_ALREADY The interface is already initialized.
* @retval OT_ERROR_INVALID_ARGS The UART device or executable cannot be found or failed to open/run. * @retval OT_ERROR_INVALID_ARGS The UART device or executable cannot be found or failed to open/run.
* *
*/ */
otError Init(const otPlatformConfig &aPlatformConfig); otError Init(Arguments &aArguments);
/** /**
* This method deinitializes the interface to the RCP. * This method deinitializes the interface to the RCP.
@@ -198,7 +198,7 @@ private:
static void HandleHdlcFrame(void *aContext, otError aError); static void HandleHdlcFrame(void *aContext, otError aError);
void HandleHdlcFrame(otError aError); void HandleHdlcFrame(otError aError);
static int OpenFile(const char *aFile, const char *aConfig); static int OpenFile(const char *aFile, Arguments &aArguments);
#if OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE #if OPENTHREAD_POSIX_CONFIG_RCP_PTY_ENABLE
static int ForkPty(const char *aCommand, const char *aArguments); static int ForkPty(const char *aCommand, const char *aArguments);
#endif #endif
@@ -38,6 +38,7 @@
#include <setjmp.h> #include <setjmp.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h>
#include <sys/select.h> #include <sys/select.h>
#include <openthread/error.h> #include <openthread/error.h>
@@ -69,25 +70,9 @@ enum
*/ */
typedef struct otPlatformConfig typedef struct otPlatformConfig
{ {
uint64_t mNodeId; ///< Unique node ID. uint32_t mSpeedUpFactor; ///< Speed up factor.
uint32_t mSpeedUpFactor; ///< Speed up factor. const char *mInterfaceName; ///< Thread network interface name.
const char *mInterfaceName; ///< Thread network interface name. const char *mRadioUrl; ///< Radio url.
const char *mRadioFile; ///< Radio file path.
const char *mRadioConfig; ///< Radio configurations.
const char *mMaxPowerTable; ///< Radio max transmit power table.
bool mResetRadio; ///< Whether to reset RCP when initializing.
bool mRestoreDatasetFromNcp; ///< Whether to retrieve dataset from NCP and save to file.
char * mSpiGpioIntDevice; ///< Path to the Linux GPIO character device for the `I̅N̅T̅` pin.
char * mSpiGpioResetDevice; ///< Path to the Linux GPIO character device for the `R̅E̅S̅E̅T̅` pin.
uint8_t mSpiGpioIntLine; ///< Line index of the `I̅N̅T̅` pin for the associated GPIO character device.
uint8_t mSpiGpioResetLine; ///< Line index of the `R̅E̅S̅E̅T̅` pin for the associated GPIO character device.
uint8_t mSpiMode; ///< SPI mode to use (0-3).
uint32_t mSpiSpeed; ///< SPI speed in hertz.
uint32_t mSpiResetDelay; ///< The delay after R̅E̅S̅E̅T̅ assertion, in miliseconds.
uint16_t mSpiCsDelay; ///< The delay after SPI C̅S̅ assertion, in µsec.
uint8_t mSpiAlignAllowance; ///< Maximum number of 0xFF bytes to clip from start of MISO frame.
uint8_t mSpiSmallPacketSize; ///< Smallest SPI packet size we can receive in a single transaction.
} otPlatformConfig; } otPlatformConfig;
/** /**
@@ -156,6 +141,14 @@ int otSysMainloopPoll(otSysMainloopContext *aMainloop);
*/ */
void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop); void otSysMainloopProcess(otInstance *aInstance, const otSysMainloopContext *aMainloop);
/**
* This method returns the radio url help string.
*
* @returns the radio url help string.
*
*/
const char *otSysGetRadioUrlHelpString(void);
#ifdef __cplusplus #ifdef __cplusplus
} // end of extern "C" } // end of extern "C"
#endif #endif
+2 -1
View File
@@ -50,6 +50,7 @@
#include "common/logging.hpp" #include "common/logging.hpp"
#include "radio_url.hpp"
#include "lib/platform/exit_code.h" #include "lib/platform/exit_code.h"
/** /**
@@ -162,7 +163,7 @@ void platformAlarmAdvanceNow(uint64_t aDelta);
* @param[in] aPlatformConfig Platform configuration structure. * @param[in] aPlatformConfig Platform configuration structure.
* *
*/ */
void platformRadioInit(const otPlatformConfig *aPlatformConfig); void platformRadioInit(otPosixRadioArguments *aArguments);
/** /**
* This function shuts down the radio service used by OpenThread. * This function shuts down the radio service used by OpenThread.
+12 -8
View File
@@ -94,18 +94,22 @@ void otPlatRadioSetPromiscuous(otInstance *aInstance, bool aEnable)
SuccessOrDie(sRadioSpinel.SetPromiscuous(aEnable)); SuccessOrDie(sRadioSpinel.SetPromiscuous(aEnable));
} }
void platformRadioInit(const otPlatformConfig *aPlatformConfig) void platformRadioInit(otPosixRadioArguments *aArguments)
{ {
ot::Posix::Arguments *args = reinterpret_cast<ot::Posix::Arguments *>(aArguments);
bool resetRadio = (args->GetValue("no-reset") == NULL);
bool restoreDataset = (args->GetValue("ncp-dataset") != NULL);
#if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE #if OPENTHREAD_POSIX_CONFIG_MAX_POWER_TABLE_ENABLE
uint8_t channel = ot::Radio::kChannelMin; uint8_t channel = ot::Radio::kChannelMin;
int8_t power = ot::Posix::MaxPowerTable::kPowerDefault; int8_t power = ot::Posix::MaxPowerTable::kPowerDefault;
const char *maxPowerTable = args->GetValue("max-power-table");
if (aPlatformConfig->mMaxPowerTable != NULL) if (maxPowerTable != NULL)
{ {
const char *str = NULL; const char *str = NULL;
for (str = strtok(const_cast<char *>(aPlatformConfig->mMaxPowerTable), ","); for (str = strtok(const_cast<char *>(maxPowerTable), ","); str != NULL && channel <= ot::Radio::kChannelMax;
str != NULL && channel <= ot::Radio::kChannelMax; str = strtok(NULL, ",")) str = strtok(NULL, ","))
{ {
power = static_cast<int8_t>(strtol(str, NULL, 0)); power = static_cast<int8_t>(strtol(str, NULL, 0));
sMaxPowerTable.SetTransmitPower(channel++, power); sMaxPowerTable.SetTransmitPower(channel++, power);
@@ -122,8 +126,8 @@ void platformRadioInit(const otPlatformConfig *aPlatformConfig)
} }
#endif #endif
SuccessOrDie(sRadioSpinel.GetSpinelInterface().Init(*aPlatformConfig)); SuccessOrDie(sRadioSpinel.GetSpinelInterface().Init(*args));
sRadioSpinel.Init(aPlatformConfig->mResetRadio, aPlatformConfig->mRestoreDatasetFromNcp); sRadioSpinel.Init(resetRadio, restoreDataset);
} }
void platformRadioDeinit(void) void platformRadioDeinit(void)
+224
View File
@@ -0,0 +1,224 @@
/*
* Copyright (c) 2020, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#include "posix/platform/radio_url.hpp"
#include <stdio.h>
#include <string.h>
#include <openthread/openthread-system.h>
#include "core/common/code_utils.hpp"
#include "posix/platform/platform-posix.h"
const char *otSysGetRadioUrlHelpString(void)
{
#if OPENTHREAD_POSIX_CONFIG_RCP_BUS == OT_POSIX_RCP_BUS_SPI
#define RADIO_URL_HELP_BUS \
"Radio URL:\n" \
"spinel+spi://${PATH_TO_SPI_DEVICE}?${arguments}\n" \
"arguments:\n" \
" gpio-int-device[=gpio-device-path]\n" \
" Specify a path to the Linux sysfs-exported GPIO device for the\n" \
" `I̅N̅T̅` pin. If not specified, `SPI` interface will fall back to\n" \
" polling, which is inefficient.\n" \
" gpio-int-line[=line-offset]\n" \
" The offset index of `I̅N̅T̅` pin for the associated GPIO device.\n" \
" If not specified, `SPI` interface will fall back to polling,\n" \
" which is inefficient.\n" \
" gpio-reset-dev[=gpio-device-path]\n" \
" Specify a path to the Linux sysfs-exported GPIO device for the\n" \
" `R̅E̅S̅` pin.\n" \
" gpio-reset-line[=line-offset]" \
" The offset index of `R̅E̅S̅` pin for the associated GPIO device.\n" \
" spi-mode[=mode] Specify the SPI mode to use (0-3).\n" \
" spi-speed[=hertz] Specify the SPI speed in hertz.\n" \
" spi-cs-delay[=usec] Specify the delay after C̅S̅ assertion, in µsec.\n" \
" spi-reset-delay[=ms] Specify the delay after R̅E̅S̅E̅T̅ assertion, in milliseconds.\n" \
" spi-align-allowance[=n] Specify the maximum number of 0xFF bytes to clip from start of\n" \
" MISO frame. Max value is 16.\n" \
" spi-small-packet=[n] Specify the smallest packet we can receive in a single transaction.\n" \
" (larger packets will require two transactions). Default value is 32.\n"
#else
#define RADIO_URL_HELP_BUS \
"Radio URL:\n" \
"spinel+hdlc+uart://${PATH_TO_UART_DEVICE}?${arguments} for real uart device\n" \
"spinel+hdlc+fortpty://${PATH_TO_UART_DEVICE}?${arguments} for forking a pty subprocess.\n" \
"arguments:\n" \
" uart-parity[=even|odd] Uart parity config, optional.\n" \
" uart-stop[=number-of-bits] Uart stop bit, default is 1.\n" \
" baudrate[=baudrate] Uart baud rate, default is 115200.\n" \
" arg[=argument string] Command line arguments for subprocess, can be repeated.\n"
#endif
return RADIO_URL_HELP_BUS " no-reset Skip resetting the radio device.\n"
" ncp-dataset Retrieve dataset from ncp.\n"
" max-power-table Max power table for each channel, splitted by comma.\n";
}
namespace ot {
namespace Posix {
Arguments::Arguments(const char *aUrl)
{
char *url = &mUrl[0];
mPath = NULL;
mStart = NULL;
mEnd = NULL;
VerifyOrExit(aUrl != NULL, OT_NOOP);
VerifyOrExit(strnlen(aUrl, sizeof(mUrl)) < sizeof(mUrl), OT_NOOP);
strncpy(mUrl, aUrl, sizeof(mUrl) - 1);
url = strstr(url, "://");
VerifyOrExit(url != NULL, OT_NOOP);
url += sizeof("://") - 1;
mPath = url;
mStart = strstr(url, "?");
if (mStart != NULL)
{
mStart[0] = '\0';
mStart++;
mEnd = mStart + strlen(mStart);
for (char *cur = strtok(mStart, "&"); cur != NULL; cur = strtok(NULL, "&"))
;
}
else
{
mEnd = url + strlen(url);
mStart = mEnd;
}
exit:
return;
}
const char *Arguments::GetValue(const char *aName, const char *aLastValue)
{
const char * rval = NULL;
const size_t len = strlen(aName);
char * start = (aLastValue == NULL ? mStart : (const_cast<char *>(aLastValue) + strlen(aLastValue) + 1));
while (start < mEnd)
{
char *last = NULL;
if (!strncmp(aName, start, len))
{
if (start[len] == '=')
{
ExitNow(rval = &start[len + 1]);
}
else if (start[len] == '&' || start[len] == '\0')
{
ExitNow(rval = "");
}
}
last = start;
start = last + strlen(last) + 1;
}
exit:
return rval;
}
} // namespace Posix
} // namespace ot
#ifndef SELF_TEST
#define SELF_TEST 0
#endif
#if SELF_TEST
#include <assert.h>
void TestSimple()
{
char url[] = "spinel:///dev/ttyUSB0?baudrate=115200";
ot::Posix::Arguments args(url);
assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
assert(!strcmp(args.GetValue("baudrate"), "115200"));
printf("PASS %s\r\n", __func__);
}
void TestSimpleNoArguments()
{
char url[] = "spinel:///dev/ttyUSB0";
ot::Posix::Arguments args(url);
assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
printf("PASS %s\r\n", __func__);
}
void TestMultipleProtocols()
{
char url[] = "spinel+spi:///dev/ttyUSB0?baudrate=115200";
ot::Posix::Arguments args(url);
assert(!strcmp(args.GetPath(), "/dev/ttyUSB0"));
assert(!strcmp(args.GetValue("baudrate"), "115200"));
printf("PASS %s\r\n", __func__);
}
void TestMultipleProtocolsAndDuplicateParameters()
{
char url[] = "spinel+exec:///path/to/ot-rcp?arg=1&arg=arg2&arg=3";
ot::Posix::Arguments args(url);
const char * arg = NULL;
assert(!strcmp(args.GetPath(), "/path/to/ot-rcp"));
arg = args.GetValue("arg");
assert(!strcmp(arg, "1"));
arg = args.GetValue("arg", arg);
assert(!strcmp(arg, "arg2"));
arg = args.GetValue("arg", arg);
assert(!strcmp(arg, "3"));
printf("PASS %s\r\n", __func__);
}
int main()
{
TestSimple();
TestSimpleNoArguments();
TestMultipleProtocols();
TestMultipleProtocolsAndDuplicateParameters();
return 0;
}
#endif // SELF_TEST
+85
View File
@@ -0,0 +1,85 @@
/*
* Copyright (c) 2020, The OpenThread Authors.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the copyright holder nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef POSIX_PLATFORM_RADIO_URL_HPP_
#define POSIX_PLATFORM_RADIO_URL_HPP_
#include <stdio.h>
#include <stdlib.h>
#include <openthread/openthread-system.h>
extern "C" {
typedef struct otPosixRadioArguments
{
const char *mPath; ///< The path to the executable or device
} otPosixRadioArguments;
}
namespace ot {
namespace Posix {
class Arguments : public otPosixRadioArguments
{
public:
Arguments(const char *aUrl);
/**
* This method gets the path in url
*
* @returns The path in url.
*
*/
const char *GetPath(void) const { return mPath; }
/**
* This method returns the url agument value.
*
* @param[in] aName Argument name.
* @param[in] aLastValue The last iterated argument value, NULL for first value.
*
* @returns The argument value.
*
*/
const char *GetValue(const char *aName, const char *aLastValue = NULL);
private:
enum
{
kRadioUrlMaxSize = 512,
};
char mUrl[kRadioUrlMaxSize];
char *mStart;
char *mEnd;
};
} // namespace Posix
} // namespace ot
#endif // POSIX_PLATFORM_RADIO_URL_HPP_
+69 -10
View File
@@ -91,32 +91,91 @@ SpiInterface::SpiInterface(SpinelInterface::ReceiveFrameCallback aCallback,
{ {
} }
otError SpiInterface::Init(const otPlatformConfig &aPlatformConfig) otError SpiInterface::Init(Arguments &aArguments)
{ {
VerifyOrDie(aPlatformConfig.mSpiAlignAllowance <= kSpiAlignAllowanceMax, OT_EXIT_FAILURE); const char *spiGpioIntDevice;
const char *spiGpioResetDevice;
uint8_t spiGpioIntLine = 0;
uint8_t spiGpioResetLine = 0;
uint8_t spiMode = OT_PLATFORM_CONFIG_SPI_DEFAULT_MODE;
uint32_t spiSpeed = SPI_IOC_WR_MAX_SPEED_HZ;
uint32_t spiResetDelay = OT_PLATFORM_CONFIG_SPI_DEFAULT_RESET_DELAY_MS;
uint16_t spiCsDelay = OT_PLATFORM_CONFIG_SPI_DEFAULT_CS_DELAY_US;
uint8_t spiAlignAllowance = OT_PLATFORM_CONFIG_SPI_DEFAULT_ALIGN_ALLOWANCE;
uint8_t spiSmallPacketSize = OT_PLATFORM_CONFIG_SPI_DEFAULT_SMALL_PACKET_SIZE;
mSpiCsDelayUs = aPlatformConfig.mSpiCsDelay; spiGpioIntDevice = aArguments.GetValue("gpio-int-device");
mSpiSmallPacketSize = aPlatformConfig.mSpiSmallPacketSize; spiGpioResetDevice = aArguments.GetValue("gpio-reset-device");
mSpiAlignAllowance = aPlatformConfig.mSpiAlignAllowance; if (!spiGpioIntDevice || !spiGpioResetDevice)
{
DieNow(OT_EXIT_INVALID_ARGUMENTS);
}
if (aPlatformConfig.mSpiGpioIntDevice != NULL) if (aArguments.GetValue("gpio-int-line"))
{
spiGpioIntLine = static_cast<uint8_t>(atoi(aArguments.GetValue("gpio-int-line")));
}
else
{
DieNow(OT_EXIT_INVALID_ARGUMENTS);
}
if (aArguments.GetValue("gpio-reset-line"))
{
spiGpioResetLine = static_cast<uint8_t>(atoi(aArguments.GetValue("gpio-reset-line")));
}
else
{
DieNow(OT_EXIT_INVALID_ARGUMENTS);
}
if (aArguments.GetValue("spi-mode"))
{
spiMode = static_cast<uint8_t>(atoi(aArguments.GetValue("spi-mode")));
}
if (aArguments.GetValue("spi-speed"))
{
spiSpeed = static_cast<uint32_t>(atoi(aArguments.GetValue("spi-speed")));
}
if (aArguments.GetValue("spi-reset-delay"))
{
spiResetDelay = static_cast<uint32_t>(atoi(aArguments.GetValue("spi-reset-delay")));
}
if (aArguments.GetValue("spi-cs-delay"))
{
spiCsDelay = static_cast<uint16_t>(atoi(aArguments.GetValue("spi-cs-delay")));
}
if (aArguments.GetValue("spi-align-allowance"))
{
spiAlignAllowance = static_cast<uint8_t>(atoi(aArguments.GetValue("spi-align-allowance")));
}
if (aArguments.GetValue("spi-small-packet"))
{
spiSmallPacketSize = static_cast<uint8_t>(atoi(aArguments.GetValue("spi-small-packet")));
}
VerifyOrDie(spiAlignAllowance <= kSpiAlignAllowanceMax, OT_EXIT_FAILURE);
mSpiCsDelayUs = spiCsDelay;
mSpiSmallPacketSize = spiSmallPacketSize;
mSpiAlignAllowance = spiAlignAllowance;
if (spiGpioIntDevice != NULL)
{ {
// If the interrupt pin is not set, SPI interface will use polling mode. // If the interrupt pin is not set, SPI interface will use polling mode.
InitIntPin(aPlatformConfig.mSpiGpioIntDevice, aPlatformConfig.mSpiGpioIntLine); InitIntPin(spiGpioIntDevice, spiGpioIntLine);
} }
else else
{ {
otLogNotePlat("SPI interface enters polling mode."); otLogNotePlat("SPI interface enters polling mode.");
} }
InitResetPin(aPlatformConfig.mSpiGpioResetDevice, aPlatformConfig.mSpiGpioResetLine); InitResetPin(spiGpioResetDevice, spiGpioResetLine);
InitSpiDev(aPlatformConfig.mRadioFile, aPlatformConfig.mSpiMode, aPlatformConfig.mSpiSpeed); InitSpiDev(aArguments.GetPath(), spiMode, spiSpeed);
// Reset RCP chip. // Reset RCP chip.
TrigerReset(); TrigerReset();
// Waiting for the RCP chip starts up. // Waiting for the RCP chip starts up.
usleep(static_cast<useconds_t>(aPlatformConfig.mSpiResetDelay) * kUsecPerMsec); usleep(static_cast<useconds_t>(spiResetDelay) * kUsecPerMsec);
return OT_ERROR_NONE; return OT_ERROR_NONE;
} }
+2 -2
View File
@@ -79,14 +79,14 @@ public:
* *
* @note This method should be called before reading and sending spinel frames to the interface. * @note This method should be called before reading and sending spinel frames to the interface.
* *
* @param[in] aPlatformConfig Platform configuration structure. * @param[in] aArguments Arguments parsed from radio url.
* *
* @retval OT_ERROR_NONE The interface is initialized successfully. * @retval OT_ERROR_NONE The interface is initialized successfully.
* @retval OT_ERROR_ALREADY The interface is already initialized. * @retval OT_ERROR_ALREADY The interface is already initialized.
* @retval OT_ERROR_INVALID_ARGS The UART device or executable cannot be found or failed to open/run. * @retval OT_ERROR_INVALID_ARGS The UART device or executable cannot be found or failed to open/run.
* *
*/ */
otError Init(const otPlatformConfig &aPlatformConfig); otError Init(Arguments &aArguments);
/** /**
* This method deinitializes the interface to the RCP. * This method deinitializes the interface to the RCP.
+6 -3
View File
@@ -49,13 +49,16 @@ uint64_t gNodeId = 0;
otInstance *otSysInit(otPlatformConfig *aPlatformConfig) otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
{ {
otInstance *instance = NULL; otInstance * instance = NULL;
ot::Posix::Arguments args(aPlatformConfig->mRadioUrl);
#if OPENTHREAD_POSIX_VIRTUAL_TIME #if OPENTHREAD_POSIX_VIRTUAL_TIME
virtualTimeInit(static_cast<uint16_t>(atoi(aPlatformConfig->mRadioConfig))); virtualTimeInit(static_cast<uint16_t>(atoi(args.GetValue("arg"))));
#endif #endif
VerifyOrDie(args.GetPath() != NULL, OT_EXIT_INVALID_ARGUMENTS);
platformAlarmInit(aPlatformConfig->mSpeedUpFactor); platformAlarmInit(aPlatformConfig->mSpeedUpFactor);
platformRadioInit(aPlatformConfig); platformRadioInit(&args);
platformRandomInit(); platformRandomInit();
instance = otInstanceInitSingle(); instance = otInstanceInitSingle();
+1 -1
View File
@@ -27,7 +27,7 @@
# POSSIBILITY OF SUCH DAMAGE. # POSSIBILITY OF SUCH DAMAGE.
# #
spawn $env(OT_COMMAND) $env(RCP_COMMAND) 1 spawn $env(OT_COMMAND) "spinel+hdlc+uart://$env(RCP_COMMAND)?arg=1"
set timeout 1 set timeout 1
expect_after { expect_after {
timeout { exit 1 } timeout { exit 1 }
@@ -28,7 +28,7 @@
# #
# allows 11-25 and forbidden 26 # allows 11-25 and forbidden 26
spawn $env(OT_COMMAND) --max-power-table 11,12,13,14,15,16,17,18,19,20,21,22,23,24,-1,0x7f $env(RCP_COMMAND) 1 spawn $env(OT_COMMAND) "spinel+hdlc+uart://$env(RCP_COMMAND)?max-power-table=11,12,13,14,15,16,17,18,19,20,21,22,23,24,-1,0x7f&arg=1"
set timeout 1 set timeout 1
expect_after { expect_after {
timeout { exit 1 } timeout { exit 1 }
@@ -42,7 +42,7 @@ expect "Done"
send "\x04" send "\x04"
expect eof expect eof
# allows all channels by default # allows all channels by default
spawn $env(OT_COMMAND) $env(RCP_COMMAND) 1 spawn $env(OT_COMMAND) "spinel+hdlc+uart://$env(RCP_COMMAND)?arg=1"
set timeout 1 set timeout 1
expect_after { expect_after {
timeout { exit 1 } timeout { exit 1 }
+8 -4
View File
@@ -108,7 +108,8 @@ class Node:
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode) cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
if 'RADIO_DEVICE' in os.environ: if 'RADIO_DEVICE' in os.environ:
cmd += ' -v %s' % os.environ['RADIO_DEVICE'] cmd += ' -v spinel+hdlc+uart://%s?arg=%d' % (
os.environ['RADIO_DEVICE'], nodeid)
# Load Thread 1.1 node when testing Thread 1.2 scenarios for interoperability # Load Thread 1.1 node when testing Thread 1.2 scenarios for interoperability
elif self.version == '1.1': elif self.version == '1.1':
@@ -120,7 +121,8 @@ class Node:
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode) cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
if 'RADIO_DEVICE_1_1' in os.environ: if 'RADIO_DEVICE_1_1' in os.environ:
cmd += ' -v %s' % os.environ['RADIO_DEVICE_1_1'] cmd += ' -v spinel+hdlc+uart://%s?arg=%d' % (
os.environ['RADIO_DEVICE_1_1'], nodeid)
cmd += ' %d' % nodeid cmd += ' %d' % nodeid
print("%s" % cmd) print("%s" % cmd)
@@ -146,7 +148,8 @@ class Node:
# If Thread version of node matches the testing environment version. # If Thread version of node matches the testing environment version.
if self.version == self.env_version: if self.version == self.env_version:
if 'RADIO_DEVICE' in os.environ: if 'RADIO_DEVICE' in os.environ:
args = ' %s' % os.environ['RADIO_DEVICE'] args = ' spinel+hdlc+uart://%s?arg=%d' % (
os.environ['RADIO_DEVICE'], nodeid)
else: else:
args = '' args = ''
@@ -184,7 +187,8 @@ class Node:
# Load Thread 1.1 node when testing Thread 1.2 scenarios for interoperability. # Load Thread 1.1 node when testing Thread 1.2 scenarios for interoperability.
elif self.version == '1.1': elif self.version == '1.1':
if 'RADIO_DEVICE_1_1' in os.environ: if 'RADIO_DEVICE_1_1' in os.environ:
args = ' %s' % os.environ['RADIO_DEVICE_1_1'] args = ' spinel+hdlc+uart://%s?arg=%d' % (
os.environ['RADIO_DEVICE_1_1'], nodeid)
else: else:
args = '' args = ''
+1 -1
View File
@@ -330,7 +330,7 @@ class Node(object):
self._use_posix_with_rcp = False self._use_posix_with_rcp = False
if self._use_posix_with_rcp: if self._use_posix_with_rcp:
ncp_socket_path = 'system:{} -s {} {} {}'.format( ncp_socket_path = 'system:{} -s {} spinel+hdlc+uart://{}?arg={}'.format(
self._OT_NCP_FTD_POSIX, self._SPEED_UP_FACTOR, self._OT_RCP, self._OT_NCP_FTD_POSIX, self._SPEED_UP_FACTOR, self._OT_RCP,
index) index)
else: else: