mirror of
https://github.com/espressif/openthread.git
synced 2026-07-26 22:09:05 +00:00
[posix] use real time signal for microsecond timer (#5122)
This commit is contained in:
@@ -396,6 +396,7 @@ LOCAL_CPPFLAGS := \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_LDLIBS := \
|
||||
-lrt \
|
||||
-lutil
|
||||
|
||||
LOCAL_SRC_FILES := \
|
||||
@@ -481,6 +482,7 @@ LOCAL_SRC_FILES := \
|
||||
$(NULL)
|
||||
|
||||
LOCAL_LDLIBS := \
|
||||
-lrt \
|
||||
-lutil
|
||||
|
||||
LOCAL_STATIC_LIBRARIES = libopenthread-ncp ot-core
|
||||
|
||||
@@ -36,13 +36,7 @@
|
||||
|
||||
#include "utils/code_utils.h"
|
||||
|
||||
#ifndef __linux__
|
||||
#define __linux__ 0
|
||||
#endif
|
||||
|
||||
// linux microsecond timer
|
||||
#if __linux__
|
||||
|
||||
#ifdef __linux__
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
@@ -67,6 +61,12 @@ timer_t sMicroTimer;
|
||||
|
||||
#define DEFAULT_TIMEOUT 10 // seconds
|
||||
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
#define OT_SIMULATION_CLOCK_ID CLOCK_MONOTONIC_RAW
|
||||
#else
|
||||
#define OT_SIMULATION_CLOCK_ID CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
static bool sIsMsRunning = false;
|
||||
static uint32_t sMsAlarm = 0;
|
||||
|
||||
@@ -75,7 +75,7 @@ static uint32_t sUsAlarm = 0;
|
||||
|
||||
static uint32_t sSpeedUpFactor = 1;
|
||||
|
||||
#if __linux__
|
||||
#ifdef __linux__
|
||||
static void microTimerHandler(int aSignal, siginfo_t *aSignalInfo, void *aUserContext)
|
||||
{
|
||||
assert(aSignal == OPENTHREAD_CONFIG_MICRO_TIMER_SIGNAL);
|
||||
@@ -90,7 +90,7 @@ void platformAlarmInit(uint32_t aSpeedUpFactor)
|
||||
{
|
||||
sSpeedUpFactor = aSpeedUpFactor;
|
||||
|
||||
#if __linux__
|
||||
#ifdef __linux__
|
||||
{
|
||||
struct sigaction sa;
|
||||
|
||||
@@ -110,7 +110,7 @@ void platformAlarmInit(uint32_t aSpeedUpFactor)
|
||||
sev.sigev_signo = OPENTHREAD_CONFIG_MICRO_TIMER_SIGNAL;
|
||||
sev.sigev_value.sival_ptr = &sMicroTimer;
|
||||
|
||||
if (-1 == timer_create(CLOCK_REALTIME, &sev, &sMicroTimer))
|
||||
if (-1 == timer_create(CLOCK_MONOTONIC, &sev, &sMicroTimer))
|
||||
{
|
||||
perror("timer_create");
|
||||
exit(EXIT_FAILURE);
|
||||
@@ -125,11 +125,7 @@ uint64_t platformGetNow(void)
|
||||
struct timespec now;
|
||||
int err;
|
||||
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
err = clock_gettime(CLOCK_MONOTONIC_RAW, &now);
|
||||
#else
|
||||
err = clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
#endif
|
||||
err = clock_gettime(OT_SIMULATION_CLOCK_ID, &now);
|
||||
|
||||
VerifyOrDie(err == 0, OT_EXIT_ERROR_ERRNO);
|
||||
|
||||
@@ -181,7 +177,7 @@ void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
sUsAlarm = aT0 + aDt;
|
||||
sIsUsRunning = true;
|
||||
|
||||
#if __linux__
|
||||
#ifdef __linux__
|
||||
{
|
||||
struct itimerspec its;
|
||||
uint32_t diff = sUsAlarm - otPlatAlarmMicroGetNow();
|
||||
@@ -207,7 +203,7 @@ void otPlatAlarmMicroStop(otInstance *aInstance)
|
||||
|
||||
sIsUsRunning = false;
|
||||
|
||||
#if __linux__
|
||||
#ifdef __linux__
|
||||
{
|
||||
struct itimerspec its = {{0, 0}, {0, 0}};
|
||||
|
||||
|
||||
+2
-2
@@ -49,7 +49,7 @@ readonly VIRTUAL_TIME="${VIRTUAL_TIME:-1}"
|
||||
build_simulation()
|
||||
{
|
||||
local version="$1"
|
||||
local options=("-DOT_THREAD_VERSION=${version}")
|
||||
local options=("-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON")
|
||||
|
||||
if [[ ${version} == "1.2" ]]; then
|
||||
options+=("-DOT_DUA=ON")
|
||||
@@ -82,7 +82,7 @@ build_simulation()
|
||||
build_posix()
|
||||
{
|
||||
local version="$1"
|
||||
local options=("-DOT_THREAD_VERSION=${version}")
|
||||
local options=("-DOT_THREAD_VERSION=${version}" "-DBUILD_TESTING=ON")
|
||||
|
||||
if [[ ${version} == "1.2" ]]; then
|
||||
options+=("-DOT_DUA=ON")
|
||||
|
||||
@@ -60,6 +60,12 @@ LDADD_COMMON = \
|
||||
-lutil \
|
||||
$(NULL)
|
||||
|
||||
if OPENTHREAD_TARGET_LINUX
|
||||
LDADD_COMMON += \
|
||||
-lrt \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
if OPENTHREAD_ENABLE_BUILTIN_MBEDTLS
|
||||
LDADD_COMMON += \
|
||||
$(top_builddir)/third_party/mbedtls/libmbedcrypto.a \
|
||||
|
||||
@@ -113,6 +113,7 @@ enum
|
||||
OT_POSIX_OPT_SHORT_MAX = 128,
|
||||
|
||||
OT_POSIX_OPT_RADIO_VERSION,
|
||||
OT_POSIX_OPT_REAL_TIME_SIGNAL,
|
||||
};
|
||||
|
||||
static const struct option kOptions[] = {{"debug-level", required_argument, NULL, OT_POSIX_OPT_DEBUG_LEVEL},
|
||||
@@ -120,6 +121,7 @@ static const struct option kOptions[] = {{"debug-level", required_argument, NULL
|
||||
{"help", no_argument, NULL, OT_POSIX_OPT_HELP},
|
||||
{"interface-name", required_argument, NULL, OT_POSIX_OPT_INTERFACE_NAME},
|
||||
{"radio-version", no_argument, NULL, OT_POSIX_OPT_RADIO_VERSION},
|
||||
{"real-time-signal", required_argument, NULL, OT_POSIX_OPT_REAL_TIME_SIGNAL},
|
||||
{"time-speed", required_argument, NULL, OT_POSIX_OPT_TIME_SPEED},
|
||||
{"verbose", no_argument, NULL, OT_POSIX_OPT_VERBOSE},
|
||||
{0, 0, 0, 0}};
|
||||
@@ -138,6 +140,12 @@ static void PrintUsage(const char *aProgramName, FILE *aStream, int aExitCode)
|
||||
" -s --time-speed factor Time speed up factor.\n"
|
||||
" -v --verbose Also log to stderr.\n",
|
||||
aProgramName);
|
||||
#ifdef __linux__
|
||||
fprintf(aStream,
|
||||
" --real-time-signal (Linux only) The real-time signal number for microsecond timer.\n"
|
||||
" Use +N for relative value to SIGRTMIN, and use N for absolute value.\n");
|
||||
|
||||
#endif
|
||||
fprintf(aStream, "%s", otSysGetRadioUrlHelpString());
|
||||
exit(aExitCode);
|
||||
}
|
||||
@@ -148,6 +156,9 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig)
|
||||
|
||||
aConfig->mPlatformConfig.mSpeedUpFactor = 1;
|
||||
aConfig->mLogLevel = OT_LOG_LEVEL_CRIT;
|
||||
#ifdef __linux__
|
||||
aConfig->mPlatformConfig.mRealTimeSignal = SIGRTMIN;
|
||||
#endif
|
||||
|
||||
optind = 1;
|
||||
|
||||
@@ -194,6 +205,18 @@ static void ParseArg(int aArgCount, char *aArgVector[], PosixConfig *aConfig)
|
||||
case OT_POSIX_OPT_RADIO_VERSION:
|
||||
aConfig->mPrintRadioVersion = true;
|
||||
break;
|
||||
#ifdef __linux__
|
||||
case OT_POSIX_OPT_REAL_TIME_SIGNAL:
|
||||
if (optarg[0] == '+')
|
||||
{
|
||||
aConfig->mPlatformConfig.mRealTimeSignal = SIGRTMIN + atoi(&optarg[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
aConfig->mPlatformConfig.mRealTimeSignal = atoi(optarg);
|
||||
}
|
||||
break;
|
||||
#endif // __linux__
|
||||
case '?':
|
||||
PrintUsage(aArgVector[0], stderr, OT_EXIT_INVALID_ARGUMENTS);
|
||||
break;
|
||||
|
||||
@@ -83,7 +83,14 @@ set_target_properties(
|
||||
CXX_STANDARD 11
|
||||
)
|
||||
|
||||
target_link_libraries(openthread-posix PUBLIC openthread-platform PRIVATE ot-config util)
|
||||
target_link_libraries(openthread-posix
|
||||
PUBLIC
|
||||
openthread-platform
|
||||
PRIVATE
|
||||
ot-config
|
||||
util
|
||||
$<$<STREQUAL:${CMAKE_SYSTEM_NAME},Linux>:rt>
|
||||
)
|
||||
|
||||
target_compile_definitions(openthread-posix
|
||||
PUBLIC
|
||||
|
||||
@@ -50,16 +50,38 @@ static uint32_t sUsAlarm = 0;
|
||||
|
||||
static uint32_t sSpeedUpFactor = 1;
|
||||
|
||||
#ifdef __linux__
|
||||
|
||||
#include <signal.h>
|
||||
#include <time.h>
|
||||
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE && !OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
static timer_t sMicroTimer;
|
||||
static int sRealTimeSignal = 0;
|
||||
|
||||
static void microTimerHandler(int aSignal, siginfo_t *aSignalInfo, void *aUserContext)
|
||||
{
|
||||
assert(aSignal == sRealTimeSignal);
|
||||
assert(aSignalInfo->si_value.sival_ptr == &sMicroTimer);
|
||||
OT_UNUSED_VARIABLE(aSignal);
|
||||
OT_UNUSED_VARIABLE(aSignalInfo);
|
||||
OT_UNUSED_VARIABLE(aUserContext);
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE && !OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
#endif // __linux__
|
||||
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
#define OT_POSIX_CLOCK_ID CLOCK_MONOTONIC_RAW
|
||||
#else
|
||||
#define OT_POSIX_CLOCK_ID CLOCK_MONOTONIC
|
||||
#endif
|
||||
|
||||
#if !OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
uint64_t otPlatTimeGet(void)
|
||||
{
|
||||
struct timespec now;
|
||||
|
||||
#ifdef CLOCK_MONOTONIC_RAW
|
||||
VerifyOrDie(clock_gettime(CLOCK_MONOTONIC_RAW, &now) == 0, OT_EXIT_FAILURE);
|
||||
#else
|
||||
VerifyOrDie(clock_gettime(CLOCK_MONOTONIC, &now) == 0, OT_EXIT_FAILURE);
|
||||
#endif
|
||||
VerifyOrDie(clock_gettime(OT_POSIX_CLOCK_ID, &now) == 0, OT_EXIT_FAILURE);
|
||||
|
||||
return (uint64_t)now.tv_sec * US_PER_S + (uint64_t)now.tv_nsec / NS_PER_US;
|
||||
}
|
||||
@@ -70,9 +92,43 @@ static uint64_t platformAlarmGetNow(void)
|
||||
return otPlatTimeGet() * sSpeedUpFactor;
|
||||
}
|
||||
|
||||
void platformAlarmInit(uint32_t aSpeedUpFactor)
|
||||
void platformAlarmInit(uint32_t aSpeedUpFactor, int aRealTimeSignal)
|
||||
{
|
||||
sSpeedUpFactor = aSpeedUpFactor;
|
||||
|
||||
if (aRealTimeSignal == 0)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
otLogWarnPlat("Real time signal not enabled, microsecond timers may be inaccurate!");
|
||||
#endif
|
||||
}
|
||||
#ifdef __linux__
|
||||
else if (aRealTimeSignal >= SIGRTMIN && aRealTimeSignal <= SIGRTMAX)
|
||||
{
|
||||
#if OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE && !OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
struct sigaction sa;
|
||||
struct sigevent sev;
|
||||
|
||||
sa.sa_flags = SA_SIGINFO;
|
||||
sa.sa_sigaction = microTimerHandler;
|
||||
sigemptyset(&sa.sa_mask);
|
||||
|
||||
VerifyOrDie(sigaction(aRealTimeSignal, &sa, NULL) != -1, OT_EXIT_ERROR_ERRNO);
|
||||
|
||||
sev.sigev_notify = SIGEV_SIGNAL;
|
||||
sev.sigev_signo = aRealTimeSignal;
|
||||
sev.sigev_value.sival_ptr = &sMicroTimer;
|
||||
|
||||
VerifyOrDie(timer_create(CLOCK_MONOTONIC, &sev, &sMicroTimer) != -1, OT_EXIT_ERROR_ERRNO);
|
||||
|
||||
sRealTimeSignal = aRealTimeSignal;
|
||||
#endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE && !OPENTHREAD_POSIX_VIRTUAL_TIME
|
||||
}
|
||||
#endif // __linux__
|
||||
else
|
||||
{
|
||||
DieNow(OT_EXIT_INVALID_ARGUMENTS);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t otPlatAlarmMilliGetNow(void)
|
||||
@@ -107,6 +163,25 @@ void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt)
|
||||
|
||||
sUsAlarm = aT0 + aDt;
|
||||
sIsUsRunning = true;
|
||||
|
||||
#ifdef __linux__
|
||||
if (sRealTimeSignal != 0)
|
||||
{
|
||||
struct itimerspec its;
|
||||
uint32_t diff = sUsAlarm - otPlatAlarmMicroGetNow();
|
||||
|
||||
its.it_value.tv_sec = diff / US_PER_S;
|
||||
its.it_value.tv_nsec = (diff % US_PER_S) * NS_PER_US;
|
||||
|
||||
its.it_interval.tv_sec = 0;
|
||||
its.it_interval.tv_nsec = 0;
|
||||
|
||||
if (-1 == timer_settime(sMicroTimer, 0, &its, NULL))
|
||||
{
|
||||
otLogWarnPlat("Failed to update microsecond timer: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif // __linux__
|
||||
}
|
||||
|
||||
void otPlatAlarmMicroStop(otInstance *aInstance)
|
||||
@@ -114,6 +189,18 @@ void otPlatAlarmMicroStop(otInstance *aInstance)
|
||||
OT_UNUSED_VARIABLE(aInstance);
|
||||
|
||||
sIsUsRunning = false;
|
||||
|
||||
#ifdef __linux__
|
||||
if (sRealTimeSignal != 0)
|
||||
{
|
||||
struct itimerspec its = {{0, 0}, {0, 0}};
|
||||
|
||||
if (-1 == timer_settime(sMicroTimer, 0, &its, NULL))
|
||||
{
|
||||
otLogWarnPlat("Failed to stop microsecond timer: %s", strerror(errno));
|
||||
}
|
||||
}
|
||||
#endif // __linux__
|
||||
}
|
||||
#endif // OPENTHREAD_CONFIG_PLATFORM_USEC_TIMER_ENABLE
|
||||
|
||||
|
||||
@@ -76,9 +76,10 @@ typedef struct otPosixRadioArguments otPosixRadioArguments;
|
||||
*/
|
||||
typedef struct otPlatformConfig
|
||||
{
|
||||
uint32_t mSpeedUpFactor; ///< Speed up factor.
|
||||
const char *mInterfaceName; ///< Thread network interface name.
|
||||
const char *mRadioUrl; ///< Radio url.
|
||||
const char *mInterfaceName; ///< Thread network interface name.
|
||||
const char *mRadioUrl; ///< Radio url.
|
||||
int mRealTimeSignal; ///< The real-time signal for microsecond timer.
|
||||
uint32_t mSpeedUpFactor; ///< Speed up factor.
|
||||
} otPlatformConfig;
|
||||
|
||||
/**
|
||||
|
||||
@@ -106,8 +106,11 @@ extern uint64_t gNodeId;
|
||||
/**
|
||||
* This function initializes the alarm service used by OpenThread.
|
||||
*
|
||||
* @param[in] aSpeedUpFactor The speed up factor.
|
||||
* @param[in] aRealTimeSignal The real time signal for microsecond alarms.
|
||||
*
|
||||
*/
|
||||
void platformAlarmInit(uint32_t aSpeedUpFactor);
|
||||
void platformAlarmInit(uint32_t aSpeedUpFactor, int aRealTimeSignal);
|
||||
|
||||
/**
|
||||
* This function retrieves the time remaining until the alarm fires.
|
||||
|
||||
@@ -57,7 +57,7 @@ otInstance *otSysInit(otPlatformConfig *aPlatformConfig)
|
||||
#endif
|
||||
|
||||
VerifyOrDie(args.GetPath() != nullptr, OT_EXIT_INVALID_ARGUMENTS);
|
||||
platformAlarmInit(aPlatformConfig->mSpeedUpFactor);
|
||||
platformAlarmInit(aPlatformConfig->mSpeedUpFactor, aPlatformConfig->mRealTimeSignal);
|
||||
platformRadioInit(&args);
|
||||
platformRandomInit();
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ class Node:
|
||||
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
|
||||
|
||||
if 'RADIO_DEVICE' in os.environ:
|
||||
cmd += ' -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (
|
||||
cmd += ' --real-time-signal=+1 -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (
|
||||
os.environ['RADIO_DEVICE'], nodeid)
|
||||
else:
|
||||
cmd += ' %d' % nodeid
|
||||
@@ -123,7 +123,7 @@ class Node:
|
||||
cmd = '%s/examples/apps/cli/ot-cli-%s' % (srcdir, mode)
|
||||
|
||||
if 'RADIO_DEVICE_1_1' in os.environ:
|
||||
cmd += ' -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (
|
||||
cmd += ' --real-time-signal=+1 -v spinel+hdlc+uart://%s?forkpty-arg=%d' % (
|
||||
os.environ['RADIO_DEVICE_1_1'], nodeid)
|
||||
else:
|
||||
cmd += ' %d' % nodeid
|
||||
@@ -151,7 +151,7 @@ class Node:
|
||||
# If Thread version of node matches the testing environment version.
|
||||
if self.version == self.env_version:
|
||||
if 'RADIO_DEVICE' in os.environ:
|
||||
args = ' spinel+hdlc+uart://%s?forkpty-arg=%d' % (
|
||||
args = ' --real-time-signal=+1 spinel+hdlc+uart://%s?forkpty-arg=%d' % (
|
||||
os.environ['RADIO_DEVICE'], nodeid)
|
||||
else:
|
||||
args = ''
|
||||
@@ -190,7 +190,7 @@ class Node:
|
||||
# Load Thread 1.1 node when testing Thread 1.2 scenarios for interoperability.
|
||||
elif self.version == '1.1':
|
||||
if 'RADIO_DEVICE_1_1' in os.environ:
|
||||
args = ' spinel+hdlc+uart://%s?forkpty-arg=%d' % (
|
||||
args = ' --real-time-signal=+1 spinel+hdlc+uart://%s?forkpty-arg=%d' % (
|
||||
os.environ['RADIO_DEVICE_1_1'], nodeid)
|
||||
else:
|
||||
args = ''
|
||||
|
||||
Reference in New Issue
Block a user