From 588613ba6536519d4cc4dcb23d36a016c72b2ca0 Mon Sep 17 00:00:00 2001 From: Shu Chen Date: Fri, 11 Aug 2017 01:08:17 +0800 Subject: [PATCH] [posix] add microsecond timer support (#2086) --- examples/platforms/posix/alarm.c | 112 +++++++++++++----- .../posix/openthread-core-posix-config.h | 8 ++ tests/fuzz/fuzzer_platform.c | 17 +++ tests/unit/test_diag.cpp | 4 + tests/unit/test_platform.cpp | 39 ++++++ 5 files changed, 152 insertions(+), 28 deletions(-) diff --git a/examples/platforms/posix/alarm.c b/examples/platforms/posix/alarm.c index 23c9f428f..26e113c12 100644 --- a/examples/platforms/posix/alarm.c +++ b/examples/platforms/posix/alarm.c @@ -32,16 +32,27 @@ #include #include +#include #include #include -static bool s_is_running = false; -static uint32_t s_alarm = 0; -static struct timeval s_start; +#define MS_PER_S 1000 +#define US_PER_MS 1000 +#define US_PER_S 1000000 + +#define DEFAULT_TIMEOUT 10 // seconds + +static bool sIsMsRunning = false; +static uint32_t sMsAlarm = 0; + +static bool sIsUsRunning = false; +static uint32_t sUsAlarm = 0; + +static struct timeval sStart; void platformAlarmInit(void) { - gettimeofday(&s_start, NULL); + gettimeofday(&sStart, NULL); } uint32_t otPlatAlarmMilliGetNow(void) @@ -49,52 +60,81 @@ uint32_t otPlatAlarmMilliGetNow(void) struct timeval tv; gettimeofday(&tv, NULL); - timersub(&tv, &s_start, &tv); + timersub(&tv, &sStart, &tv); - return (uint32_t)((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); + return (uint32_t)((tv.tv_sec * MS_PER_S) + (tv.tv_usec / US_PER_MS)); } -void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t t0, uint32_t dt) +void otPlatAlarmMilliStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) { (void)aInstance; - s_alarm = t0 + dt; - s_is_running = true; + sMsAlarm = aT0 + aDt; + sIsMsRunning = true; } void otPlatAlarmMilliStop(otInstance *aInstance) { (void)aInstance; - s_is_running = false; + sIsMsRunning = false; +} + +uint32_t otPlatAlarmMicroGetNow(void) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + timersub(&tv, &sStart, &tv); + + return (uint32_t)(tv.tv_sec * US_PER_S + tv.tv_usec); +} + +void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) +{ + (void)aInstance; + sUsAlarm = aT0 + aDt; + sIsUsRunning = true; +} + +void otPlatAlarmMicroStop(otInstance *aInstance) +{ + (void)aInstance; + sIsUsRunning = false; } void platformAlarmUpdateTimeout(struct timeval *aTimeout) { - int32_t remaining; + int32_t usRemaining = DEFAULT_TIMEOUT * US_PER_S; + int32_t msRemaining = DEFAULT_TIMEOUT * MS_PER_S; if (aTimeout == NULL) { return; } - if (s_is_running) + if (sIsUsRunning) { - remaining = (int32_t)(s_alarm - otPlatAlarmMilliGetNow()); + usRemaining = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow()); + } - if (remaining > 0) - { - aTimeout->tv_sec = remaining / 1000; - aTimeout->tv_usec = (remaining % 1000) * 1000; - } - else - { - aTimeout->tv_sec = 0; - aTimeout->tv_usec = 0; - } + if (sIsMsRunning) + { + msRemaining = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow()); + } + + if (usRemaining <= 0 || msRemaining <= 0) + { + aTimeout->tv_sec = 0; + aTimeout->tv_usec = 0; + } + else if (msRemaining * US_PER_MS < usRemaining) + { + aTimeout->tv_sec = msRemaining / MS_PER_S; + aTimeout->tv_usec = (msRemaining % MS_PER_S) * US_PER_MS; } else { - aTimeout->tv_sec = 10; - aTimeout->tv_usec = 0; + aTimeout->tv_sec = usRemaining / US_PER_S; + aTimeout->tv_usec = usRemaining % US_PER_S; } } @@ -102,13 +142,13 @@ void platformAlarmProcess(otInstance *aInstance) { int32_t remaining; - if (s_is_running) + if (sIsMsRunning) { - remaining = (int32_t)(s_alarm - otPlatAlarmMilliGetNow()); + remaining = (int32_t)(sMsAlarm - otPlatAlarmMilliGetNow()); if (remaining <= 0) { - s_is_running = false; + sIsMsRunning = false; #if OPENTHREAD_ENABLE_DIAG @@ -123,4 +163,20 @@ void platformAlarmProcess(otInstance *aInstance) } } } + +#if OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER + + if (sIsUsRunning) + { + remaining = (int32_t)(sUsAlarm - otPlatAlarmMicroGetNow()); + + if (remaining <= 0) + { + sIsUsRunning = false; + + otPlatAlarmMicroFired(aInstance); + } + } + +#endif // OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER } diff --git a/examples/platforms/posix/openthread-core-posix-config.h b/examples/platforms/posix/openthread-core-posix-config.h index 249e5b838..ddc5d3f03 100644 --- a/examples/platforms/posix/openthread-core-posix-config.h +++ b/examples/platforms/posix/openthread-core-posix-config.h @@ -51,4 +51,12 @@ */ #define OPENTHREAD_CONFIG_ENABLE_DEFAULT_LOG_OUTPUT 1 +/** + * @def OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER + * + * Define to 1 if you want to support microsecond timer in platform. + * + */ +#define OPENTHREAD_CONFIG_ENABLE_PLATFORM_USEC_TIMER 1 + #endif // OPENTHREAD_CORE_POSIX_CONFIG_H_ diff --git a/tests/fuzz/fuzzer_platform.c b/tests/fuzz/fuzzer_platform.c index 4ab2ac997..227020862 100644 --- a/tests/fuzz/fuzzer_platform.c +++ b/tests/fuzz/fuzzer_platform.c @@ -54,6 +54,23 @@ void otPlatAlarmMilliStop(otInstance *aInstance) (void)aInstance; } +uint32_t otPlatAlarmMicroGetNow(void) +{ + return 0; +} + +void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) +{ + (void)aInstance; + (void)aT0; + (void)aDt; +} + +void otPlatAlarmMicroStop(otInstance *aInstance) +{ + (void)aInstance; +} + void otPlatReset(otInstance *aInstance) { (void)aInstance; diff --git a/tests/unit/test_diag.cpp b/tests/unit/test_diag.cpp index 45cb14576..0e33beaba 100644 --- a/tests/unit/test_diag.cpp +++ b/tests/unit/test_diag.cpp @@ -57,6 +57,10 @@ extern "C" void otPlatAlarmMilliFired(otInstance *) { } +extern "C" void otPlatAlarmMicroFired(otInstance *) +{ +} + extern "C" void otPlatRadioTxDone(otInstance *, otRadioFrame *aFrame, otRadioFrame *aAckFrame, otError aError) { (void)aFrame; diff --git a/tests/unit/test_platform.cpp b/tests/unit/test_platform.cpp index 22ba019bc..972084eca 100644 --- a/tests/unit/test_platform.cpp +++ b/tests/unit/test_platform.cpp @@ -174,6 +174,45 @@ extern "C" { } } + void otPlatAlarmMicroStop(otInstance *aInstance) + { + if (g_testPlatAlarmStop) + { + g_testPlatAlarmStop(aInstance); + } + else + { + g_testPlatAlarmSet = false; + } + } + + void otPlatAlarmMicroStartAt(otInstance *aInstance, uint32_t aT0, uint32_t aDt) + { + if (g_testPlatAlarmStartAt) + { + g_testPlatAlarmStartAt(aInstance, aT0, aDt); + } + else + { + g_testPlatAlarmSet = true; + g_testPlatAlarmNext = aT0 + aDt; + } + } + + uint32_t otPlatAlarmMicroGetNow(void) + { + if (g_testPlatAlarmGetNow) + { + return g_testPlatAlarmGetNow(); + } + else + { + struct timeval tv; + gettimeofday(&tv, NULL); + return (uint32_t)((tv.tv_sec * 1000000) + tv.tv_usec + 123456); + } + } + // // Radio //