]> granicus.if.org Git - esp-idf/commitdiff
newlib: Add some functions from _POSIX_TIMERS
authorKonstantin Kondrashov <konstantin@espressif.com>
Mon, 25 Jun 2018 06:12:12 +0000 (11:12 +0500)
committerKonstantin Kondrashov <konstantin@espressif.com>
Tue, 3 Jul 2018 02:28:29 +0000 (07:28 +0500)
clock_gettime();
clock_settime();
clock_getres();

Closes https://github.com/espressif/esp-idf/issues/1302

components/newlib/platform_include/time.h [new file with mode: 0644]
components/newlib/test/test_time.c
components/newlib/time.c

diff --git a/components/newlib/platform_include/time.h b/components/newlib/platform_include/time.h
new file mode 100644 (file)
index 0000000..954d824
--- /dev/null
@@ -0,0 +1,35 @@
+// Copyright 2018 Espressif Systems (Shanghai) PTE LTD
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+//     http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+
+#ifndef _ESP_TIME_H
+#define _ESP_TIME_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include_next <time.h>
+
+#define _POSIX_TIMERS 1
+#define CLOCK_MONOTONIC (clockid_t)4
+#define CLOCK_BOOTTIME (clockid_t)4
+
+int _EXFUN(clock_settime, (clockid_t clock_id, const struct timespec *tp));
+int _EXFUN(clock_gettime, (clockid_t clock_id, struct timespec *tp));
+int _EXFUN(clock_getres,  (clockid_t clock_id, struct timespec *res));
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* _ESP_TIME_H */
index 47df5b9de2fe83134ee5529998f5442933f9fb23..0b9b4daa9f9d2508ce2e05d7c30384d15abffa0f 100644 (file)
@@ -9,6 +9,8 @@
 #include "freertos/task.h"
 #include "freertos/semphr.h"
 #include "sdkconfig.h"
+#include "soc/rtc.h"
+#include "esp_clk.h"
 
 
 #if portNUM_PROCESSORS == 2
@@ -289,3 +291,108 @@ TEST_CASE("test for thread safety adjtime and gettimeofday functions", "[newlib]
 
     TEST_ASSERT(adjtime_test_result == false && gettimeofday_test_result == false);
 }
+
+#if defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC ) || defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 )
+#define WITH_RTC 1
+#endif
+
+#if defined( CONFIG_ESP32_TIME_SYSCALL_USE_FRC1 ) || defined( CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1 )
+#define WITH_FRC 1
+#endif
+void test_posix_timers_clock (void)
+{
+#ifndef _POSIX_TIMERS
+    TEST_ASSERT_MESSAGE(false, "_POSIX_TIMERS - is not defined");
+#endif
+
+#if defined( WITH_FRC )
+    printf("WITH_FRC    ");
+#endif
+
+#if defined( WITH_RTC )
+    printf("WITH_RTC    ");
+#endif
+
+#ifdef CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL
+    printf("External (crystal) Frequency = %d Hz\n", rtc_clk_slow_freq_get_hz());
+#else
+    printf("Internal Frequency = %d Hz\n", rtc_clk_slow_freq_get_hz());
+#endif
+
+    TEST_ASSERT(clock_settime(CLOCK_REALTIME, NULL) == -1);
+    TEST_ASSERT(clock_gettime(CLOCK_REALTIME, NULL) == -1);
+    TEST_ASSERT(clock_getres(CLOCK_REALTIME,  NULL) == -1);
+
+    TEST_ASSERT(clock_settime(CLOCK_MONOTONIC, NULL) == -1);
+    TEST_ASSERT(clock_gettime(CLOCK_MONOTONIC, NULL) == -1);
+    TEST_ASSERT(clock_getres(CLOCK_MONOTONIC,  NULL) == -1);
+
+#if defined( WITH_FRC ) || defined( WITH_RTC )
+    struct timeval now = {0};
+    now.tv_sec  = 10L;
+    now.tv_usec = 100000L;
+    TEST_ASSERT(settimeofday(&now, NULL) == 0);
+    TEST_ASSERT(gettimeofday(&now, NULL) == 0);
+
+    struct timespec ts = {0};
+
+    TEST_ASSERT(clock_settime(0xFFFFFFFF, &ts) == -1);
+    TEST_ASSERT(clock_gettime(0xFFFFFFFF, &ts) == -1);
+    TEST_ASSERT(clock_getres(0xFFFFFFFF,  &ts) == 0);
+
+    TEST_ASSERT(clock_gettime(CLOCK_REALTIME, &ts) == 0);
+    TEST_ASSERT(now.tv_sec == ts.tv_sec);
+    TEST_ASSERT_INT_WITHIN(5000000L, ts.tv_nsec, now.tv_usec * 1000L);
+
+    ts.tv_sec  = 20;
+    ts.tv_nsec = 100000000L;
+    TEST_ASSERT(clock_settime(CLOCK_REALTIME, &ts) == 0);
+    TEST_ASSERT(gettimeofday(&now, NULL) == 0);
+    TEST_ASSERT(now.tv_sec == ts.tv_sec);
+    TEST_ASSERT_INT_WITHIN(5000L, now.tv_usec,  ts.tv_nsec / 1000L);
+
+    TEST_ASSERT(clock_settime(CLOCK_MONOTONIC, &ts) == -1);
+
+    uint64_t delta_monotonic_us = 0;
+#if defined( WITH_FRC )
+
+    TEST_ASSERT(clock_getres(CLOCK_REALTIME, &ts) == 0);
+    TEST_ASSERT_EQUAL_INT(1000, ts.tv_nsec);
+    TEST_ASSERT(clock_getres(CLOCK_MONOTONIC, &ts) == 0);
+    TEST_ASSERT_EQUAL_INT(1000, ts.tv_nsec);
+
+    TEST_ASSERT(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
+    delta_monotonic_us = esp_timer_get_time() - (ts.tv_sec * 1000000L + ts.tv_nsec / 1000L);
+    TEST_ASSERT(delta_monotonic_us > 0 || delta_monotonic_us == 0);
+    TEST_ASSERT_INT_WITHIN(5000L, 0, delta_monotonic_us);
+
+    #elif defined( WITH_RTC )
+
+    TEST_ASSERT(clock_getres(CLOCK_REALTIME, &ts) == 0);
+    TEST_ASSERT_EQUAL_INT(1000000000L / rtc_clk_slow_freq_get_hz(), ts.tv_nsec);
+    TEST_ASSERT(clock_getres(CLOCK_MONOTONIC, &ts) == 0);
+    TEST_ASSERT_EQUAL_INT(1000000000L / rtc_clk_slow_freq_get_hz(), ts.tv_nsec);
+
+    TEST_ASSERT(clock_gettime(CLOCK_MONOTONIC, &ts) == 0);
+    delta_monotonic_us = esp_clk_rtc_time() - (ts.tv_sec * 1000000L + ts.tv_nsec / 1000L);
+    TEST_ASSERT(delta_monotonic_us > 0 || delta_monotonic_us == 0);
+    TEST_ASSERT_INT_WITHIN(5000L, 0, delta_monotonic_us);
+
+#endif // WITH_FRC
+
+#else
+    struct timespec ts = {0};
+    TEST_ASSERT(clock_settime(CLOCK_REALTIME, &ts) == -1);
+    TEST_ASSERT(clock_gettime(CLOCK_REALTIME, &ts) == -1);
+    TEST_ASSERT(clock_getres(CLOCK_REALTIME,  &ts) == -1);
+
+    TEST_ASSERT(clock_settime(CLOCK_MONOTONIC, &ts) == -1);
+    TEST_ASSERT(clock_gettime(CLOCK_MONOTONIC, &ts) == -1);
+    TEST_ASSERT(clock_getres(CLOCK_MONOTONIC,  &ts) == -1);
+#endif // defined( WITH_FRC ) || defined( WITH_RTC )
+}
+
+TEST_CASE("test posix_timers clock_... functions", "[newlib]")
+{
+    test_posix_timers_clock();
+}
index 6137f21435cd31e3dd0054f2306fa949b48cc530..892ab2ff83df15067d01302d261d87016c5e73ca 100644 (file)
@@ -380,3 +380,87 @@ void esp_sync_counters_rtc_and_frc()
     set_boot_time(get_adjusted_boot_time() + ((int64_t)s_microseconds_offset - s_microseconds_offset_cur));
 #endif
 }
+
+
+int clock_settime (clockid_t clock_id, const struct timespec *tp)
+{
+#if defined( WITH_FRC ) || defined( WITH_RTC )
+    if (tp == NULL) {
+        errno = EINVAL;
+        return -1;
+    }
+    struct timeval tv;
+    switch (clock_id) {
+        case CLOCK_REALTIME:
+            tv.tv_sec = tp->tv_sec;
+            tv.tv_usec = tp->tv_nsec / 1000L;
+            settimeofday(&tv, NULL);
+            break;
+        default:
+            errno = EINVAL;
+            return -1;
+    }
+    return 0;
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
+}
+
+int clock_gettime (clockid_t clock_id, struct timespec *tp)
+{
+#if defined( WITH_FRC ) || defined( WITH_RTC )
+    if (tp == NULL) {
+        errno = EINVAL;
+        return -1;
+    }
+    struct timeval tv;
+    _gettimeofday_r(NULL, &tv, NULL);
+    uint64_t monotonic_time_us = 0;
+    switch (clock_id) {
+        case CLOCK_REALTIME:
+            tp->tv_sec = tv.tv_sec;
+            tp->tv_nsec = tv.tv_usec * 1000L;
+            break;
+        case CLOCK_MONOTONIC:
+#if defined( WITH_FRC )
+            monotonic_time_us = (uint64_t) esp_timer_get_time();
+#elif defined( WITH_RTC )
+            monotonic_time_us = get_rtc_time_us();
+#endif // WITH_FRC
+            tp->tv_sec = monotonic_time_us / 1000000LL;
+            tp->tv_nsec = (monotonic_time_us % 1000000LL) * 1000L;
+            break;
+        default:
+            errno = EINVAL;
+            return -1;
+    }
+    return 0;
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
+}
+
+int clock_getres (clockid_t clock_id, struct timespec *res)
+{
+#if defined( WITH_FRC ) || defined( WITH_RTC )
+    if (res == NULL) {
+        errno = EINVAL;
+        return -1;
+    }
+#if defined( WITH_FRC )
+    res->tv_sec = 0;
+    res->tv_nsec = 1000L;
+#elif defined( WITH_RTC )
+    res->tv_sec = 0;
+    uint32_t rtc_freq = rtc_clk_slow_freq_get_hz();
+    assert(rtc_freq != 0);
+    res->tv_nsec = 1000000000L / rtc_freq;
+#endif // WITH_FRC
+    return 0;
+#else
+    errno = ENOSYS;
+    return -1;
+#endif
+}