--- /dev/null
+// 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 */
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "sdkconfig.h"
+#include "soc/rtc.h"
+#include "esp_clk.h"
#if portNUM_PROCESSORS == 2
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();
+}
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
+}