Browse Source

[time]时钟框架重构 (#7794)

xqyjlj 1 year ago
parent
commit
0eb75ced70

+ 1 - 1
bsp/qemu-virt64-aarch64/.config

@@ -204,7 +204,7 @@ CONFIG_RT_USING_FDTLIB=y
 # CONFIG_FDT_USING_DEBUG is not set
 CONFIG_RT_USING_RTC=y
 # CONFIG_RT_USING_ALARM is not set
-# CONFIG_RT_USING_SOFT_RTC is not set
+CONFIG_RT_USING_SOFT_RTC=y
 # CONFIG_RT_USING_SDIO is not set
 # CONFIG_RT_USING_SPI is not set
 # CONFIG_RT_USING_WDT is not set

+ 11 - 0
bsp/qemu-virt64-aarch64/applications/mnt.c

@@ -22,6 +22,17 @@ int mnt_init(void)
         {
             rt_kprintf("file system initialization done!\n");
         }
+        else
+        {
+            if (dfs_mount("virtio-blk0", "/", "ext", 0, RT_NULL) == 0)
+            {
+                rt_kprintf("file system initialization done!\n");
+            }
+            else
+            {
+                rt_kprintf("file system initialization fail!\n");
+            }
+        }
     }
 
     return 0;

+ 3 - 0
bsp/qemu-virt64-aarch64/drivers/board.c

@@ -14,6 +14,7 @@
 #include <rthw.h>
 #include <rtthread.h>
 #include <mmu.h>
+#include <gtimer.h>
 
 #ifdef RT_USING_SMART
 #include <lwp_arch.h>
@@ -98,6 +99,8 @@ void rt_hw_board_init(void)
     /* initialize hardware interrupt */
     rt_hw_interrupt_init();
 
+    rt_hw_gtimer_init();
+
     /* support debug feature before components init */
     rt_hw_uart_init();
     rt_console_set_device(RT_CONSOLE_DEVICE_NAME);

+ 2 - 2
bsp/qemu-virt64-aarch64/drivers/drv_rtc.c

@@ -115,8 +115,8 @@ int rt_hw_rtc_init(void)
     rtc_device.device.user_data   = RT_NULL;
 
     /* register a rtc device */
-    rt_device_register(&rtc_device.device, "rtc", RT_DEVICE_FLAG_RDWR);
-
+    rt_device_register(&rtc_device.device, "rtc0", RT_DEVICE_FLAG_RDWR);
+    rt_soft_rtc_set_source("rtc0");
     return 0;
 }
 INIT_DEVICE_EXPORT(rt_hw_rtc_init);

+ 0 - 46
bsp/qemu-virt64-aarch64/drivers/drv_timer.c

@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author       Notes
- * 2018-11-22     Jesven       first version
- */
-
-#include <rthw.h>
-#include <rtthread.h>
-#include <stdint.h>
-#include "cp15.h"
-#include "board.h"
-#include "gtimer.h"
-
-#define TIMER_IRQ   30
-
-static rt_uint64_t timerStep = 0;
-
-static void rt_hw_timer_isr(int vector, void *param)
-{
-    rt_hw_set_gtimer_val(timerStep);
-    rt_tick_increase();
-}
-
-void rt_hw_timer_enable(void)
-{
-    rt_hw_set_gtimer_val(timerStep);
-    rt_hw_interrupt_umask(TIMER_IRQ);
-    rt_hw_gtimer_enable();
-}
-
-int rt_hw_timer_init(void)
-{
-    rt_hw_interrupt_install(TIMER_IRQ, rt_hw_timer_isr, RT_NULL, "tick");
-    __ISB();
-    timerStep = rt_hw_get_gtimer_frq();
-    __DSB();
-    timerStep /= RT_TICK_PER_SECOND;
-    rt_hw_timer_enable();
-
-    return 0;
-}
-INIT_BOARD_EXPORT(rt_hw_timer_init);

+ 0 - 16
bsp/qemu-virt64-aarch64/drivers/drv_timer.h

@@ -1,16 +0,0 @@
-/*
- * Copyright (c) 2006-2022, RT-Thread Development Team
- *
- * SPDX-License-Identifier: Apache-2.0
- *
- * Change Logs:
- * Date           Author       Notes
- * 2018-11-22     Jesven       first version
- */
-
-#ifndef DRV_TIMER_H__
-#define DRV_TIMER_H__
-
-void timer_init(int timer, unsigned int preload);
-
-#endif

+ 1 - 0
bsp/qemu-virt64-aarch64/rtconfig.h

@@ -133,6 +133,7 @@
 #define RT_USING_FDT
 #define RT_USING_FDTLIB
 #define RT_USING_RTC
+#define RT_USING_SOFT_RTC
 #define RT_USING_DEV_BUS
 #define RT_USING_VIRTIO
 #define RT_USING_VIRTIO10

+ 7 - 5
bsp/qemu-virt64-riscv/.config

@@ -84,7 +84,7 @@ CONFIG_RT_USING_DEVICE_OPS=y
 CONFIG_RT_USING_CONSOLE=y
 CONFIG_RT_CONSOLEBUF_SIZE=256
 CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
-CONFIG_RT_VER_NUM=0x50000
+CONFIG_RT_VER_NUM=0x50001
 # CONFIG_RT_USING_STDC_ATOMIC is not set
 CONFIG_ARCH_CPU_64BIT=y
 CONFIG_RT_USING_CACHE=y
@@ -122,10 +122,12 @@ CONFIG_FINSH_ARG_MAX=10
 CONFIG_RT_USING_DFS=y
 CONFIG_DFS_USING_POSIX=y
 CONFIG_DFS_USING_WORKDIR=y
+# CONFIG_RT_USING_DFS_MNTTABLE is not set
+CONFIG_DFS_FD_MAX=32
+CONFIG_RT_USING_DFS_V1=y
+# CONFIG_RT_USING_DFS_V2 is not set
 CONFIG_DFS_FILESYSTEMS_MAX=4
 CONFIG_DFS_FILESYSTEM_TYPES_MAX=4
-CONFIG_DFS_FD_MAX=32
-# CONFIG_RT_USING_DFS_MNTTABLE is not set
 CONFIG_RT_USING_DFS_ELMFAT=y
 
 #
@@ -174,7 +176,7 @@ CONFIG_RT_SERIAL_RB_BUFSZ=64
 # CONFIG_RT_USING_HWTIMER is not set
 CONFIG_RT_USING_CPUTIME=y
 CONFIG_RT_USING_CPUTIME_RISCV=y
-CONFIG_CPUTIME_TIMER_FREQ=300000000
+CONFIG_CPUTIME_TIMER_FREQ=10000000
 # CONFIG_RT_USING_I2C is not set
 # CONFIG_RT_USING_PHY is not set
 CONFIG_RT_USING_PIN=y
@@ -190,7 +192,7 @@ CONFIG_RT_USING_RANDOM=y
 # CONFIG_RT_USING_FDT is not set
 CONFIG_RT_USING_RTC=y
 # CONFIG_RT_USING_ALARM is not set
-# CONFIG_RT_USING_SOFT_RTC is not set
+CONFIG_RT_USING_SOFT_RTC=y
 # CONFIG_RT_USING_SDIO is not set
 # CONFIG_RT_USING_SPI is not set
 # CONFIG_RT_USING_WDT is not set

+ 13 - 2
bsp/qemu-virt64-riscv/applications/mnt.c

@@ -19,9 +19,20 @@ int mnt_init(void)
     if (rt_device_find("virtio-blk0"))
     {
         /* mount virtio-blk as root directory */
-        if (dfs_mount("virtio-blk0", "/", "elm", 0, RT_NULL) != 0)
+        if (dfs_mount("virtio-blk0", "/", "elm", 0, RT_NULL) == 0)
         {
-            LOG_E("virtio-blk0 mount failed\n");
+            rt_kprintf("file system initialization done!\n");
+        }
+        else
+        {
+            if (dfs_mount("virtio-blk0", "/", "ext", 0, RT_NULL) == 0)
+            {
+                rt_kprintf("file system initialization done!\n");
+            }
+            else
+            {
+                rt_kprintf("file system initialization fail!\n");
+            }
         }
     }
 

+ 5 - 3
bsp/qemu-virt64-riscv/rtconfig.h

@@ -53,7 +53,7 @@
 #define RT_USING_CONSOLE
 #define RT_CONSOLEBUF_SIZE 256
 #define RT_CONSOLE_DEVICE_NAME "uart0"
-#define RT_VER_NUM 0x50000
+#define RT_VER_NUM 0x50001
 #define ARCH_CPU_64BIT
 #define RT_USING_CACHE
 #define RT_USING_HW_ATOMIC
@@ -83,9 +83,10 @@
 #define RT_USING_DFS
 #define DFS_USING_POSIX
 #define DFS_USING_WORKDIR
+#define DFS_FD_MAX 32
+#define RT_USING_DFS_V1
 #define DFS_FILESYSTEMS_MAX 4
 #define DFS_FILESYSTEM_TYPES_MAX 4
-#define DFS_FD_MAX 32
 #define RT_USING_DFS_ELMFAT
 
 /* elm-chan's FatFs, Generic FAT Filesystem Module */
@@ -117,12 +118,13 @@
 #define RT_SERIAL_RB_BUFSZ 64
 #define RT_USING_CPUTIME
 #define RT_USING_CPUTIME_RISCV
-#define CPUTIME_TIMER_FREQ 300000000
+#define CPUTIME_TIMER_FREQ 10000000
 #define RT_USING_PIN
 #define RT_USING_NULL
 #define RT_USING_ZERO
 #define RT_USING_RANDOM
 #define RT_USING_RTC
+#define RT_USING_SOFT_RTC
 #define RT_USING_VIRTIO
 #define RT_USING_VIRTIO10
 #define RT_USING_VIRTIO_BLK

+ 8 - 0
components/drivers/include/drivers/rtc.h

@@ -27,6 +27,9 @@ extern "C" {
 #define RT_DEVICE_CTRL_RTC_SET_TIMEVAL  (RT_DEVICE_CTRL_BASE(RTC) + 0x04)              /**< set timeval for gettimeofday */
 #define RT_DEVICE_CTRL_RTC_GET_ALARM    (RT_DEVICE_CTRL_BASE(RTC) + 0x05)              /**< get alarm */
 #define RT_DEVICE_CTRL_RTC_SET_ALARM    (RT_DEVICE_CTRL_BASE(RTC) + 0x06)              /**< set alarm */
+#define RT_DEVICE_CTRL_RTC_GET_TIMESPEC (RT_DEVICE_CTRL_BASE(RTC) + 0x07)              /**< get timespec for clock_gettime */
+#define RT_DEVICE_CTRL_RTC_SET_TIMESPEC (RT_DEVICE_CTRL_BASE(RTC) + 0x08)              /**< set timespec for clock_settime */
+#define RT_DEVICE_CTRL_RTC_GET_TIMERES  (RT_DEVICE_CTRL_BASE(RTC) + 0x09)              /**< get resolution for clock_getres */
 
 /* used for alarm function */
 struct rt_rtc_wkalarm
@@ -64,6 +67,11 @@ rt_err_t set_time(rt_uint32_t hour, rt_uint32_t minute, rt_uint32_t second);
 rt_err_t set_timestamp(time_t timestamp);
 rt_err_t get_timestamp(time_t *timestamp);
 
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+rt_err_t rt_soft_rtc_sync();
+rt_err_t rt_soft_rtc_set_source(const char *name);
+#endif
+
 #ifdef __cplusplus
 }
 #endif

+ 127 - 4
components/drivers/rtc/soft_rtc.c

@@ -13,6 +13,8 @@
 #include <rtthread.h>
 #include <rtdevice.h>
 
+#include <ktime.h>
+
 #ifdef RT_USING_SOFT_RTC
 
 /* 2018-01-30 14:44:50 = RTC_TIME_INIT(2018, 1, 30, 14, 44, 50)  */
@@ -23,9 +25,21 @@
 #define SOFT_RTC_TIME_DEFAULT                    RTC_TIME_INIT(2018, 1, 1, 0, 0 ,0)
 #endif
 
+#ifndef RTC_AUTO_SYNC_FIRST_DELAY
+#define RTC_AUTO_SYNC_FIRST_DELAY 25
+#endif
+#ifndef RTC_AUTO_SYNC_PERIOD
+#define RTC_AUTO_SYNC_PERIOD 3600
+#endif
+
+static struct rt_work rtc_sync_work;
+static rt_device_t    source_device = RT_NULL;
+
 static struct rt_device soft_rtc_dev;
 static rt_tick_t init_tick;
 static time_t init_time;
+static struct timeval   init_tv = {0};
+static struct timespec  init_ts = {0};
 
 #ifdef RT_USING_ALARM
 
@@ -55,9 +69,33 @@ static void soft_rtc_alarm_update(struct rt_rtc_wkalarm *palarm)
 
 #endif
 
+static void set_rtc_time(time_t t)
+{
+    init_time = t - (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND;
+#ifdef RT_USING_ALARM
+    soft_rtc_alarm_update(&wkalarm);
+#endif
+}
+
+static void _source_device_control(int cmd, void *args)
+{
+    if (source_device == RT_NULL)
+        return;
+
+    if (rt_device_open(source_device, 0) == RT_EOK)
+    {
+        rt_device_control(source_device, cmd, args);
+        rt_device_close(source_device);
+    }
+}
+
 static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args)
 {
     time_t *t;
+    struct timeval  *tv;
+    struct timespec *ts;
+    struct timeval   _tv;
+    struct timespec  _ts;
     struct tm time_temp;
 
     RT_ASSERT(dev != RT_NULL);
@@ -72,10 +110,8 @@ static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args)
     case RT_DEVICE_CTRL_RTC_SET_TIME:
     {
         t = (time_t *) args;
-        init_time = *t - (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND;
-#ifdef RT_USING_ALARM
-        soft_rtc_alarm_update(&wkalarm);
-#endif
+        set_rtc_time(*t);
+        _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, t);
         break;
     }
 #ifdef RT_USING_ALARM
@@ -87,6 +123,37 @@ static rt_err_t soft_rtc_control(rt_device_t dev, int cmd, void *args)
         soft_rtc_alarm_update(&wkalarm);
         break;
 #endif
+    case RT_DEVICE_CTRL_RTC_GET_TIMEVAL:
+        tv = (struct timeval *)args;
+        rt_ktime_boottime_get_us(&_tv);
+        tv->tv_sec  = init_time + (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND;
+        tv->tv_usec = init_tv.tv_usec + _tv.tv_usec;
+        break;
+    case RT_DEVICE_CTRL_RTC_SET_TIMEVAL:
+        tv = (struct timeval *)args;
+        rt_ktime_boottime_get_us(&_tv);
+        set_rtc_time(tv->tv_sec);
+        init_tv.tv_usec = tv->tv_usec - _tv.tv_usec;
+        _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, &(tv->tv_sec));
+        break;
+    case RT_DEVICE_CTRL_RTC_GET_TIMESPEC:
+        ts = (struct timespec *)args;
+        rt_ktime_boottime_get_ns(&_ts);
+        ts->tv_sec  = init_time + (rt_tick_get() - init_tick) / RT_TICK_PER_SECOND;
+        ts->tv_nsec = init_ts.tv_nsec + _ts.tv_nsec;
+        break;
+    case RT_DEVICE_CTRL_RTC_SET_TIMESPEC:
+        ts = (struct timespec *)args;
+        rt_ktime_boottime_get_ns(&_ts);
+        set_rtc_time(ts->tv_sec);
+        init_ts.tv_nsec = ts->tv_nsec - _ts.tv_nsec;
+        _source_device_control(RT_DEVICE_CTRL_RTC_SET_TIME, &(ts->tv_sec));
+        break;
+    case RT_DEVICE_CTRL_RTC_GET_TIMERES:
+        ts          = (struct timespec *)args;
+        ts->tv_sec  = 0;
+        ts->tv_nsec = (rt_ktime_cputimer_getres() / RT_KTIME_RESMUL);
+        break;
     }
 
     return RT_EOK;
@@ -153,4 +220,60 @@ static int rt_soft_rtc_init(void)
 }
 INIT_DEVICE_EXPORT(rt_soft_rtc_init);
 
+#ifdef RT_USING_SYSTEM_WORKQUEUE
+
+rt_err_t rt_soft_rtc_sync()
+{
+    time_t time = 0;
+
+    if (source_device == RT_NULL)
+    {
+        rt_kprintf("error: rtc source not found, please set it!!!\n");
+        return RT_ENOSYS;
+    }
+
+    _source_device_control(RT_DEVICE_CTRL_RTC_GET_TIME, &time);
+    set_rtc_time(time);
+    return RT_EOK;
+}
+
+static void rtc_sync_work_func(struct rt_work *work, void *work_data)
+{
+    rt_soft_rtc_sync();
+    rt_work_submit(work, rt_tick_from_millisecond(RTC_AUTO_SYNC_PERIOD * 1000));
+}
+
+rt_err_t rt_soft_rtc_set_source(const char *name)
+{
+    RT_ASSERT(name != RT_NULL);
+    RT_ASSERT(rt_device_find(name));  // make sure source is exist
+
+    source_device = rt_device_find(name);
+    rt_work_init(&rtc_sync_work, rtc_sync_work_func, RT_NULL);
+    rt_work_submit(&rtc_sync_work, rt_tick_from_millisecond(RTC_AUTO_SYNC_FIRST_DELAY * 1000));
+
+    return RT_EOK;
+}
+
+#ifdef FINSH_USING_MSH
+#include <finsh.h>
+static void cmd_rtc_sync(int argc, char **argv)
+{
+    struct timeval  tv  = {0};
+    struct timezone tz  = {0};
+    time_t          now = (time_t)0;
+
+    rt_soft_rtc_sync();
+
+    gettimeofday(&tv, &tz);
+    now = tv.tv_sec;
+    /* output current time */
+    rt_kprintf("local time: %.*s", 25, ctime(&now));
+    rt_kprintf("timestamps: %ld\n", (long)tv.tv_sec);
+}
+MSH_CMD_EXPORT_ALIAS(cmd_rtc_sync, rtc_sync, Update time by real rtc);
+#endif
+
+#endif /* RT_USING_SYSTEM_WORKQUEUE */
+
 #endif /* RT_USING_SOFT_RTC */

+ 19 - 0
components/ktime/SConscript

@@ -0,0 +1,19 @@
+import os
+from building import *
+
+Import('rtconfig')
+
+cwd = GetCurrentDir()
+
+src = Glob('src/*.c')
+list = os.listdir(cwd + "/src")
+if rtconfig.ARCH in list:
+    if os.path.exists(cwd + "/src/" + rtconfig.ARCH + "/" + rtconfig.CPU):
+        src += Glob("src/" + rtconfig.ARCH + "/" + rtconfig.CPU + "/*.c")
+    else:
+        src += Glob("src/" + rtconfig.ARCH + "/*.c")
+CPPPATH = [cwd, cwd + "/inc"]
+
+group = DefineGroup('ktime', src, depend=[''], CPPPATH=CPPPATH)
+
+Return('group')

+ 160 - 0
components/ktime/inc/ktime.h

@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-07-10     xqyjlj       The first version.
+ */
+
+#ifndef __KTIME_H__
+#define __KTIME_H__
+
+#include <stdint.h>
+#include <sys/time.h>
+
+#include "rtthread.h"
+
+#define RT_KTIME_RESMUL (1000000UL)
+
+struct rt_ktime_hrtimer
+{
+    struct rt_object    parent; /**< inherit from rt_object */
+    rt_list_t           row;
+    void               *parameter;
+    unsigned long       init_cnt;
+    unsigned long       timeout_cnt;
+    struct rt_semaphore sem;
+    void (*timeout_func)(void *parameter);
+};
+typedef struct rt_ktime_hrtimer *rt_ktime_hrtimer_t;
+
+/**
+ * @brief Get boottime with us precision
+ *
+ * @param tv: timeval
+ * @return rt_err_t
+ */
+rt_err_t rt_ktime_boottime_get_us(struct timeval *tv);
+
+/**
+ * @brief Get boottime with s precision
+ *
+ * @param t: time_t
+ * @return rt_err_t
+ */
+rt_err_t rt_ktime_boottime_get_s(time_t *t);
+
+/**
+ * @brief Get boottime with ns precision
+ *
+ * @param ts: timespec
+ * @return rt_err_t
+ */
+rt_err_t rt_ktime_boottime_get_ns(struct timespec *ts);
+
+/**
+ * @brief Get cputimer resolution
+ *
+ * @return (resolution * RT_KTIME_RESMUL)
+ */
+unsigned long rt_ktime_cputimer_getres(void);
+
+/**
+ * @brief Get cputimer frequency
+ *
+ * @return frequency
+ */
+unsigned long rt_ktime_cputimer_getfrq(void);
+
+/**
+ * @brief Get cputimer the value of the cnt counter
+ *
+ * @return cnt
+ */
+unsigned long rt_ktime_cputimer_getcnt(void);
+
+/**
+ * @brief Get cputimer the cnt value corresponding to 1 os tick
+ *
+ * @return step
+ */
+unsigned long rt_ktime_cputimer_getstep(void);
+
+/**
+ * @brief Get hrtimer resolution
+ *
+ * @return (resolution * RT_KTIME_RESMUL)
+ */
+unsigned long rt_ktime_hrtimer_getres(void);
+
+/**
+ * @brief Get hrtimer frequency
+ *
+ * @return frequency
+ */
+unsigned long rt_ktime_hrtimer_getfrq(void);
+
+/**
+ * @brief Get hrtimer the value of the cnt counter
+ *
+ * @return cnt
+ */
+unsigned long rt_ktime_hrtimer_getcnt(void);
+
+/**
+ * @brief set hrtimer timeout, when timeout, the timer callback will call timeout
+ *
+ * @param cnt: hrtimer requires a timing cnt value
+ * @param timeout: timeout callback
+ * @param param: parameter
+ * @return rt_err_t
+ */
+rt_err_t rt_ktime_hrtimer_settimeout(unsigned long cnt, void (*timeout)(void *param), void *param);
+
+void     rt_ktime_hrtimer_init(rt_ktime_hrtimer_t timer,
+                               const char        *name,
+                               unsigned long      cnt,
+                               rt_uint8_t         flag,
+                               void (*timeout)(void *parameter),
+                               void *parameter);
+rt_err_t rt_ktime_hrtimer_delete(rt_ktime_hrtimer_t timer);
+rt_err_t rt_ktime_hrtimer_start(rt_ktime_hrtimer_t timer);
+rt_err_t rt_ktime_hrtimer_stop(rt_ktime_hrtimer_t timer);
+rt_err_t rt_ktime_hrtimer_control(rt_ktime_hrtimer_t timer, int cmd, void *arg);
+rt_err_t rt_ktime_hrtimer_detach(rt_ktime_hrtimer_t timer);
+
+/**
+ * @brief sleep by the cputimer cnt value
+ *
+ * @param cnt: the cputimer cnt value
+ * @return rt_err_t
+ */
+rt_err_t rt_ktime_hrtimer_sleep(unsigned long cnt);
+
+/**
+ * @brief sleep by ns
+ *
+ * @param ns: ns
+ * @return rt_err_t
+ */
+rt_err_t rt_ktime_hrtimer_ndelay(unsigned long ns);
+
+/**
+ * @brief sleep by us
+ *
+ * @param us: us
+ * @return rt_err_t
+ */
+rt_err_t rt_ktime_hrtimer_udelay(unsigned long us);
+
+/**
+ * @brief sleep by ms
+ *
+ * @param ms: ms
+ * @return rt_err_t
+ */
+rt_err_t rt_ktime_hrtimer_mdelay(unsigned long ms);
+
+#endif

+ 32 - 0
components/ktime/src/aarch64/cputimer.c

@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-07-10     xqyjlj       The first version.
+ */
+
+#include "gtimer.h"
+#include "ktime.h"
+
+unsigned long rt_ktime_cputimer_getres(void)
+{
+    return ((1000UL * 1000 * 1000) * RT_KTIME_RESMUL) / rt_hw_get_gtimer_frq();
+}
+
+unsigned long rt_ktime_cputimer_getfrq(void)
+{
+    return rt_hw_get_gtimer_frq();
+}
+
+unsigned long rt_ktime_cputimer_getcnt(void)
+{
+    return rt_hw_get_cntpct_val();
+}
+
+unsigned long rt_ktime_cputimer_getstep(void)
+{
+    return rt_ktime_cputimer_getfrq() / RT_TICK_PER_SECOND;
+}

+ 51 - 0
components/ktime/src/boottime.c

@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-07-10     xqyjlj       The first version.
+ */
+
+#include "ktime.h"
+
+#define __KTIME_MUL ((1000UL * 1000 * 1000) / RT_TICK_PER_SECOND)
+
+rt_err_t rt_ktime_boottime_get_us(struct timeval *tv)
+{
+    RT_ASSERT(tv != RT_NULL);
+
+    rt_tick_t     ms = rt_tick_get();
+    unsigned long ns =
+        ((rt_ktime_cputimer_getcnt() % rt_ktime_cputimer_getstep()) * rt_ktime_cputimer_getres()) / RT_KTIME_RESMUL;
+    ns = ((ms % RT_TICK_PER_SECOND) * __KTIME_MUL) + ns;
+
+    tv->tv_sec  = ms / RT_TICK_PER_SECOND;
+    tv->tv_usec = ns / 1000;
+
+    return RT_EOK;
+}
+
+rt_err_t rt_ktime_boottime_get_s(time_t *t)
+{
+    RT_ASSERT(t != RT_NULL);
+
+    *t = rt_tick_get() / RT_TICK_PER_SECOND;
+
+    return RT_EOK;
+}
+
+rt_err_t rt_ktime_boottime_get_ns(struct timespec *ts)
+{
+    RT_ASSERT(ts != RT_NULL);
+
+    rt_tick_t     ms = rt_tick_get();
+    unsigned long ns =
+        ((rt_ktime_cputimer_getcnt() % rt_ktime_cputimer_getstep()) * rt_ktime_cputimer_getres()) / RT_KTIME_RESMUL;
+
+    ts->tv_sec  = ms / RT_TICK_PER_SECOND;
+    ts->tv_nsec = ((ms % RT_TICK_PER_SECOND) * __KTIME_MUL) + ns;
+
+    return RT_EOK;
+}

+ 31 - 0
components/ktime/src/cputimer.c

@@ -0,0 +1,31 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-07-10     xqyjlj       The first version.
+ */
+
+#include "ktime.h"
+
+rt_weak unsigned long rt_ktime_cputimer_getres(void)
+{
+    return ((1000UL * 1000 * 1000) * RT_KTIME_RESMUL) / RT_TICK_PER_SECOND;
+}
+
+rt_weak unsigned long rt_ktime_cputimer_getfrq(void)
+{
+    return RT_TICK_PER_SECOND;
+}
+
+rt_weak unsigned long rt_ktime_cputimer_getcnt(void)
+{
+    return rt_tick_get();
+}
+
+rt_weak unsigned long rt_ktime_cputimer_getstep(void)
+{
+    return 1;
+}

+ 382 - 0
components/ktime/src/hrtimer.c

@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-07-10     xqyjlj       The first version.
+ */
+
+#include <rtdevice.h>
+#include <rthw.h>
+#include <rtthread.h>
+
+#include "ktime.h"
+
+#ifdef ARCH_CPU_64BIT
+#define _HRTIMER_MAX_CNT UINT64_MAX
+#else
+#define _HRTIMER_MAX_CNT UINT32_MAX
+#endif
+
+static rt_list_t          _timer_list = RT_LIST_OBJECT_INIT(_timer_list);
+static rt_ktime_hrtimer_t _nowtimer   = RT_NULL;
+static struct rt_spinlock _spinlock;
+
+rt_weak unsigned long rt_ktime_hrtimer_getres(void)
+{
+    return ((1000UL * 1000 * 1000) * RT_KTIME_RESMUL) / RT_TICK_PER_SECOND;
+}
+
+rt_weak unsigned long rt_ktime_hrtimer_getfrq(void)
+{
+    return RT_TICK_PER_SECOND;
+}
+
+rt_weak unsigned long rt_ktime_hrtimer_getcnt(void)
+{
+    return rt_tick_get();
+}
+
+static void (*_outcb)(void *param) = RT_NULL;
+
+static void _hrtimer_timeout(void *parameter)
+{
+    if (_outcb)
+        _outcb(parameter);
+}
+
+rt_weak rt_err_t rt_ktime_hrtimer_settimeout(unsigned long cnt, void (*timeout)(void *param), void *param)
+{
+    static rt_timer_t timer = RT_NULL;
+
+    if (timer == RT_NULL)
+    {
+        timer = rt_timer_create("shrtimer", _hrtimer_timeout, param, cnt, RT_TIMER_FLAG_ONE_SHOT);
+    }
+    else
+    {
+        rt_tick_t tick = cnt;
+        rt_timer_control(timer, RT_TIMER_CTRL_SET_TIME, &tick);
+        rt_timer_control(timer, RT_TIMER_CTRL_SET_PARM, param);
+    }
+
+    _outcb = timeout;
+    if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
+    {
+        rt_timer_stop(timer);
+    }
+    rt_timer_start(timer);
+    return RT_EOK;
+}
+
+/**
+ * @brief convert cnt from cputimer cnt to hrtimer cnt
+ *
+ * @param cnt
+ * @return unsigned long
+ */
+static unsigned long _cnt_convert(unsigned long cnt)
+{
+    int64_t count = cnt - rt_ktime_cputimer_getcnt();
+    if (count <= 0)
+        return 0;
+
+    return (count * rt_ktime_cputimer_getres()) / rt_ktime_hrtimer_getres();
+}
+
+static void _sleep_timeout(void *parameter)
+{
+    struct rt_semaphore *sem;
+    sem = (struct rt_semaphore *)parameter;
+    rt_sem_release(sem);
+}
+
+static void _set_next_timeout(void);
+static void _timeout_callback(void *parameter)
+{
+    rt_ktime_hrtimer_t timer;
+    timer = (rt_ktime_hrtimer_t)parameter;
+    rt_base_t level;
+
+    level     = rt_spin_lock_irqsave(&_spinlock);
+    _nowtimer = RT_NULL;
+    rt_list_remove(&(timer->row));
+    rt_spin_unlock_irqrestore(&_spinlock, level);
+    if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
+    {
+        timer->timeout_func(timer->parameter);
+    }
+
+    _set_next_timeout();
+}
+
+static void _set_next_timeout(void)
+{
+    rt_ktime_hrtimer_t t;
+    rt_base_t          level;
+
+    if (&_timer_list != _timer_list.prev)
+    {
+        level = rt_spin_lock_irqsave(&_spinlock);
+        t     = rt_list_entry((&_timer_list)->next, struct rt_ktime_hrtimer, row);
+        if (_nowtimer != RT_NULL)
+        {
+            if (t != _nowtimer && t->timeout_cnt < _nowtimer->timeout_cnt)
+            {
+                _nowtimer = t;
+                rt_spin_unlock_irqrestore(&_spinlock, level);
+                rt_ktime_hrtimer_settimeout(_cnt_convert(t->timeout_cnt), _timeout_callback, t);
+            }
+            else
+            {
+                rt_spin_unlock_irqrestore(&_spinlock, level);
+            }
+        }
+        else
+        {
+            _nowtimer = t;
+            rt_spin_unlock_irqrestore(&_spinlock, level);
+            rt_ktime_hrtimer_settimeout(_cnt_convert(t->timeout_cnt), _timeout_callback, t);
+        }
+    }
+    else
+    {
+        _nowtimer = RT_NULL;
+        rt_ktime_hrtimer_settimeout(RT_NULL, RT_NULL, RT_NULL);
+    }
+}
+
+void rt_ktime_hrtimer_init(rt_ktime_hrtimer_t timer,
+                           const char        *name,
+                           unsigned long      cnt,
+                           rt_uint8_t         flag,
+                           void (*timeout)(void *parameter),
+                           void *parameter)
+{
+    /* parameter check */
+    RT_ASSERT(timer != RT_NULL);
+    RT_ASSERT(timeout != RT_NULL);
+    RT_ASSERT(cnt < (_HRTIMER_MAX_CNT / 2));
+
+    /* set flag */
+    timer->parent.flag = flag;
+
+    /* set deactivated */
+    timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+    timer->timeout_func = timeout;
+    timer->parameter    = parameter;
+    timer->timeout_cnt  = cnt + rt_ktime_cputimer_getcnt();
+    timer->init_cnt     = cnt;
+
+    rt_list_init(&(timer->row));
+    rt_sem_init(&(timer->sem), "hrtimer", 0, RT_IPC_FLAG_PRIO);
+}
+
+rt_err_t rt_ktime_hrtimer_delete(rt_ktime_hrtimer_t timer)
+{
+    rt_base_t level;
+
+    /* parameter check */
+    RT_ASSERT(timer != RT_NULL);
+
+    level = rt_spin_lock_irqsave(&_spinlock);
+    rt_list_remove(&timer->row);
+    timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; /* stop timer */
+    rt_spin_unlock_irqrestore(&_spinlock, level);
+
+    _set_next_timeout();
+
+    return RT_EOK;
+}
+
+rt_err_t rt_ktime_hrtimer_start(rt_ktime_hrtimer_t timer)
+{
+    rt_list_t *timer_list;
+    rt_base_t  level;
+
+    /* parameter check */
+    RT_ASSERT(timer != RT_NULL);
+
+    level = rt_spin_lock_irqsave(&_spinlock);
+    rt_list_remove(&timer->row); /* remove timer from list */
+    /* change status of timer */
+    timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+    timer_list = &_timer_list;
+    for (; timer_list != _timer_list.prev; timer_list = timer_list->next)
+    {
+        rt_ktime_hrtimer_t t;
+        rt_list_t         *p = timer_list->next;
+
+        t = rt_list_entry(p, struct rt_ktime_hrtimer, row);
+
+        if ((t->timeout_cnt - timer->timeout_cnt) == 0)
+        {
+            continue;
+        }
+        else if ((t->timeout_cnt - timer->timeout_cnt) < (_HRTIMER_MAX_CNT / 2))
+        {
+            break;
+        }
+    }
+    rt_list_insert_after(timer_list, &(timer->row));
+    timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;
+    rt_spin_unlock_irqrestore(&_spinlock, level);
+
+    _set_next_timeout();
+
+    return RT_EOK;
+}
+
+rt_err_t rt_ktime_hrtimer_stop(rt_ktime_hrtimer_t timer)
+{
+    rt_base_t level;
+
+    RT_ASSERT(timer != RT_NULL); /* timer check */
+
+    level = rt_spin_lock_irqsave(&_spinlock);
+    if (!(timer->parent.flag & RT_TIMER_FLAG_ACTIVATED))
+    {
+        rt_spin_unlock_irqrestore(&_spinlock, level);
+        return -RT_ERROR;
+    }
+    rt_list_remove(&timer->row);
+    timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED; /* change status */
+    rt_spin_unlock_irqrestore(&_spinlock, level);
+
+    _set_next_timeout();
+
+    return RT_EOK;
+}
+
+rt_err_t rt_ktime_hrtimer_control(rt_ktime_hrtimer_t timer, int cmd, void *arg)
+{
+    rt_base_t level;
+
+    /* parameter check */
+    RT_ASSERT(timer != RT_NULL);
+
+    level = rt_spin_lock_irqsave(&_spinlock);
+    switch (cmd)
+    {
+        case RT_TIMER_CTRL_GET_TIME:
+            *(unsigned long *)arg = timer->init_cnt;
+            break;
+
+        case RT_TIMER_CTRL_SET_TIME:
+            RT_ASSERT((*(unsigned long *)arg) < (_HRTIMER_MAX_CNT / 2));
+            timer->init_cnt    = *(unsigned long *)arg;
+            timer->timeout_cnt = *(unsigned long *)arg + rt_ktime_cputimer_getcnt();
+            break;
+
+        case RT_TIMER_CTRL_SET_ONESHOT:
+            timer->parent.flag &= ~RT_TIMER_FLAG_PERIODIC;
+            break;
+
+        case RT_TIMER_CTRL_SET_PERIODIC:
+            timer->parent.flag |= RT_TIMER_FLAG_PERIODIC;
+            break;
+
+        case RT_TIMER_CTRL_GET_STATE:
+            if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
+            {
+                /*timer is start and run*/
+                *(rt_uint32_t *)arg = RT_TIMER_FLAG_ACTIVATED;
+            }
+            else
+            {
+                /*timer is stop*/
+                *(rt_uint32_t *)arg = RT_TIMER_FLAG_DEACTIVATED;
+            }
+            break;
+
+        case RT_TIMER_CTRL_GET_REMAIN_TIME:
+            *(unsigned long *)arg = timer->timeout_cnt;
+            break;
+        case RT_TIMER_CTRL_GET_FUNC:
+            arg = (void *)timer->timeout_func;
+            break;
+
+        case RT_TIMER_CTRL_SET_FUNC:
+            timer->timeout_func = (void (*)(void *))arg;
+            break;
+
+        case RT_TIMER_CTRL_GET_PARM:
+            *(void **)arg = timer->parameter;
+            break;
+
+        case RT_TIMER_CTRL_SET_PARM:
+            timer->parameter = arg;
+            break;
+
+        default:
+            break;
+    }
+    rt_spin_unlock_irqrestore(&_spinlock, level);
+
+    return RT_EOK;
+}
+
+rt_err_t rt_ktime_hrtimer_detach(rt_ktime_hrtimer_t timer)
+{
+    rt_base_t level;
+
+    /* parameter check */
+    RT_ASSERT(timer != RT_NULL);
+
+    level = rt_spin_lock_irqsave(&_spinlock);
+    rt_list_remove(&timer->row);
+    /* stop timer */
+    timer->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
+    rt_spin_unlock_irqrestore(&_spinlock, level);
+
+    _set_next_timeout();
+
+    rt_sem_detach(&(timer->sem));
+
+    return RT_EOK;
+}
+
+/************************** delay ***************************/
+
+rt_err_t rt_ktime_hrtimer_sleep(unsigned long cnt)
+{
+    struct rt_ktime_hrtimer timer;
+
+    if (cnt == 0)
+        return -RT_EINVAL;
+
+    rt_ktime_hrtimer_init(&timer, "hrtimer_sleep", cnt, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_HARD_TIMER,
+                          _sleep_timeout, &(timer.sem));
+
+    rt_ktime_hrtimer_start(&timer); /* reset the timeout of thread timer and start it */
+    rt_sem_take_interruptible(&(timer.sem), RT_WAITING_FOREVER);
+
+    rt_ktime_hrtimer_detach(&timer);
+    return RT_EOK;
+}
+
+rt_err_t rt_ktime_hrtimer_ndelay(unsigned long ns)
+{
+    unsigned long res = rt_ktime_cputimer_getres();
+    return rt_ktime_hrtimer_sleep((ns * RT_KTIME_RESMUL) / res);
+}
+
+rt_err_t rt_ktime_hrtimer_udelay(unsigned long us)
+{
+    return rt_ktime_hrtimer_ndelay(us * 1000);
+}
+
+rt_err_t rt_ktime_hrtimer_mdelay(unsigned long ms)
+{
+    return rt_ktime_hrtimer_ndelay(ms * 1000000);
+}
+
+static int rt_ktime_hrtimer_lock_init(void)
+{
+    RT_UNUSED(_spinlock);
+    rt_spin_lock_init(&_spinlock);
+    return 0;
+}
+INIT_BOARD_EXPORT(rt_ktime_hrtimer_lock_init);

+ 33 - 0
components/ktime/src/risc-v/virt64/cputimer.c

@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2006-2023, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2023-07-10     xqyjlj       The first version.
+ */
+
+#include "ktime.h"
+
+unsigned long rt_ktime_cputimer_getres(void)
+{
+    return ((1000UL * 1000 * 1000) * RT_KTIME_RESMUL) / CPUTIME_TIMER_FREQ;
+}
+
+unsigned long rt_ktime_cputimer_getfrq(void)
+{
+    return CPUTIME_TIMER_FREQ;
+}
+
+unsigned long rt_ktime_cputimer_getcnt(void)
+{
+    unsigned long time_elapsed;
+    __asm__ __volatile__("rdtime %0" : "=r"(time_elapsed));
+    return time_elapsed;
+}
+
+unsigned long rt_ktime_cputimer_getstep(void)
+{
+    return rt_ktime_cputimer_getfrq() / RT_TICK_PER_SECOND;
+}

+ 229 - 498
components/libc/compilers/common/ctime.c

@@ -19,13 +19,16 @@
  * 2021-03-15     Meco Man     fixed a bug of leaking memory in asctime()
  * 2021-05-01     Meco Man     support fixed timezone
  * 2021-07-21     Meco Man     implement that change/set timezone APIs
+ * 2023-07-03     xqyjlj       refactor posix time and timer
  */
 
 #include "sys/time.h"
-#include <sys/errno.h>
-#include <rtthread.h>
+#include <ktime.h>
 #include <rthw.h>
+#include <rtthread.h>
+#include <sys/errno.h>
 #include <unistd.h>
+#include "drivers/rtc.h"
 #ifdef RT_USING_SMART
 #include "lwp.h"
 #endif
@@ -82,69 +85,12 @@ static void num2str(char *c, int i)
     c[1] = i % 10 + '0';
 }
 
-/**
- * Get time from RTC device (without timezone, UTC+0)
- * @param tv: struct timeval
- * @return the operation status, RT_EOK on successful
- */
-static rt_err_t get_timeval(struct timeval *tv)
-{
-#ifdef RT_USING_RTC
-    static rt_device_t device = RT_NULL;
-    rt_err_t rst = -RT_ERROR;
-
-    if (tv == RT_NULL)
-        return -RT_EINVAL;
-
-    /* default is 0 */
-    tv->tv_sec = 0;
-    tv->tv_usec = 0;
-
-    /* optimization: find rtc device only first */
-    if (device == RT_NULL)
-    {
-        device = rt_device_find("rtc");
-    }
-
-    /* read timestamp from RTC device */
-    if (device != RT_NULL)
-    {
-        if (rt_device_open(device, 0) == RT_EOK)
-        {
-            rst = rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &tv->tv_sec);
-            rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIMEVAL, tv);
-            rt_device_close(device);
-        }
-    }
-    else
-    {
-        LOG_W(_WARNING_NO_RTC);
-        return -RT_ENOSYS;
-    }
-
-    return rst;
-
-#else
-    LOG_W(_WARNING_NO_RTC);
-    return -RT_ENOSYS;
-#endif /* RT_USING_RTC */
-}
-
-/**
- * Set time to RTC device (without timezone)
- * @param tv: struct timeval
- * @return the operation status, RT_EOK on successful
- */
-static int set_timeval(struct timeval *tv)
+static rt_err_t _control_rtc(int cmd, void *arg)
 {
 #ifdef RT_USING_RTC
     static rt_device_t device = RT_NULL;
     rt_err_t rst = -RT_ERROR;
 
-    if (tv == RT_NULL)
-        return -RT_EINVAL;
-
-    /* optimization: find rtc device only first */
     if (device == RT_NULL)
     {
         device = rt_device_find("rtc");
@@ -155,8 +101,7 @@ static int set_timeval(struct timeval *tv)
     {
         if (rt_device_open(device, 0) == RT_EOK)
         {
-            rst = rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &tv->tv_sec);
-            rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIMEVAL, tv);
+            rst = rt_device_control(device, cmd, arg);
             rt_device_close(device);
         }
     }
@@ -165,9 +110,7 @@ static int set_timeval(struct timeval *tv)
         LOG_W(_WARNING_NO_RTC);
         return -RT_ENOSYS;
     }
-
     return rst;
-
 #else
     LOG_W(_WARNING_NO_RTC);
     return -RT_ENOSYS;
@@ -351,51 +294,36 @@ RTM_EXPORT(strftime); /* inherent in the toolchain */
  */
 rt_weak time_t time(time_t *t)
 {
-    struct timeval now;
+    time_t _t;
 
-    if(get_timeval(&now) == RT_EOK)
-    {
-        if (t)
-        {
-            *t = now.tv_sec;
-        }
-        return now.tv_sec;
-    }
-    else
+    if (_control_rtc(RT_DEVICE_CTRL_RTC_GET_TIME, &_t) != RT_EOK)
     {
         rt_set_errno(EFAULT);
-        return ((time_t)-1);
+        return -1;
     }
+
+    if (t)
+        *t = _t;
+
+    return _t;
 }
 RTM_EXPORT(time);
 
 rt_weak clock_t clock(void)
 {
-    return rt_tick_get();
+    return rt_tick_get();  // TODO should return cpu usage time
 }
 RTM_EXPORT(clock);
 
 int stime(const time_t *t)
 {
-    struct timeval tv;
-
-    if (t == RT_NULL)
-    {
-        rt_set_errno(EFAULT);
-        return -1;
-    }
-
-    tv.tv_sec = *t;
-    tv.tv_usec = 0;
-    if (set_timeval(&tv) == RT_EOK)
+    if ((t != RT_NULL) && (_control_rtc(RT_DEVICE_CTRL_RTC_SET_TIME, (void *)t) == RT_EOK))
     {
         return 0;
     }
-    else
-    {
-        rt_set_errno(EFAULT);
-        return -1;
-    }
+
+    rt_set_errno(EFAULT);
+    return -1;
 }
 RTM_EXPORT(stime);
 
@@ -497,15 +425,17 @@ int gettimeofday(struct timeval *tv, struct timezone *tz)
         tz->tz_minuteswest = -(tz_get() * 60);
     }
 
-    if (tv != RT_NULL && get_timeval(tv) == RT_EOK)
-    {
-        return 0;
-    }
-    else
+    if (tv != RT_NULL)
     {
-        rt_set_errno(EINVAL);
-        return -1;
+        tv->tv_sec  = 0;
+        tv->tv_usec = 0;
+
+        if (_control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMEVAL, tv) == RT_EOK)
+            return 0;
     }
+
+    rt_set_errno(EINVAL);
+    return -1;
 }
 RTM_EXPORT(gettimeofday);
 
@@ -516,111 +446,65 @@ int settimeofday(const struct timeval *tv, const struct timezone *tz)
      * The tz_dsttime field has never been used under Linux.
      * Thus, the following is purely of historic interest.
      */
-    if (tv != RT_NULL
-        && tv->tv_usec >= 0
-        && set_timeval((struct timeval *)tv) == RT_EOK)
-    {
-        return 0;
-    }
-    else
+    if (tv != RT_NULL && tv->tv_usec >= 0 && tv->tv_sec >= 0)
     {
-        rt_set_errno(EINVAL);
-        return -1;
+        if (_control_rtc(RT_DEVICE_CTRL_RTC_SET_TIMEVAL, (void *)tv) == RT_EOK)
+            return 0;
     }
+
+    rt_set_errno(EINVAL);
+    return -1;
 }
 RTM_EXPORT(settimeofday);
 
 #ifdef RT_USING_POSIX_DELAY
 int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
 {
-    if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= NANOSECOND_PER_SECOND)
+    struct timespec old_ts = {0};
+    struct timespec new_ts = {0};
+
+    if (rqtp == RT_NULL)
     {
-        rt_set_errno(EINVAL);
+        rt_set_errno(EFAULT);
         return -1;
     }
-#ifdef RT_USING_CPUTIME
-    rt_uint64_t unit = clock_cpu_getres();
-    rt_uint64_t ns = rqtp->tv_sec * NANOSECOND_PER_SECOND + rqtp->tv_nsec;
-    rt_uint64_t tick = (ns * (1000UL * 1000)) / unit;
-    rt_cputime_sleep(tick);
 
-    if (rt_get_errno() == -RT_EINTR)
+    if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= NANOSECOND_PER_SECOND)
     {
-        if (rmtp)
-        {
-            uint64_t rmtp_cpu_tick = tick - clock_cpu_gettime();
-            rmtp->tv_sec = ((time_t)((rmtp_cpu_tick * unit) / (1000UL * 1000))) / NANOSECOND_PER_SECOND;
-            rmtp->tv_nsec = ((long)((rmtp_cpu_tick * unit) / (1000UL * 1000))) % NANOSECOND_PER_SECOND;
-        }
-        rt_set_errno(EINTR);
+        rt_set_errno(EINVAL);
         return -1;
     }
-#else
-    rt_tick_t tick, tick_old = rt_tick_get();
-    tick = rqtp->tv_sec * RT_TICK_PER_SECOND + ((uint64_t)rqtp->tv_nsec * RT_TICK_PER_SECOND) / NANOSECOND_PER_SECOND;
-    rt_thread_delay(tick);
-
+    unsigned long ns = rqtp->tv_sec * NANOSECOND_PER_SECOND + rqtp->tv_nsec;
+    rt_ktime_boottime_get_ns(&old_ts);
+    rt_ktime_hrtimer_ndelay(ns);
     if (rt_get_errno() == -RT_EINTR)
     {
         if (rmtp)
         {
-            tick = tick_old + tick - rt_tick_get();
-            /* get the passed time */
-            rmtp->tv_sec = tick / RT_TICK_PER_SECOND;
-            rmtp->tv_nsec = (tick % RT_TICK_PER_SECOND) * (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND);
+            rt_ktime_boottime_get_ns(&new_ts);
+
+            rmtp->tv_sec = 0;
+            rmtp->tv_nsec =
+                (old_ts.tv_nsec + ns) - ((new_ts.tv_sec - old_ts.tv_sec) * NANOSECOND_PER_SECOND + new_ts.tv_nsec);
+
+            if (rmtp->tv_nsec > NANOSECOND_PER_SECOND)
+            {
+                rmtp->tv_nsec %= NANOSECOND_PER_SECOND;
+                rmtp->tv_sec += rmtp->tv_nsec / NANOSECOND_PER_SECOND;
+            }
         }
         rt_set_errno(EINTR);
         return -1;
     }
-#endif
     return 0;
 }
 RTM_EXPORT(nanosleep);
 #endif /* RT_USING_POSIX_DELAY */
 
 #ifdef RT_USING_POSIX_CLOCK
-#ifdef RT_USING_RTC
-static volatile struct timeval _timevalue;
-static int _rt_clock_time_system_init(void)
-{
-    rt_base_t level;
-    time_t time = 0;
-    rt_tick_t tick;
-    rt_device_t device;
-
-    device = rt_device_find("rtc");
-    if (device != RT_NULL)
-    {
-        /* get realtime seconds */
-        if(rt_device_control(device, RT_DEVICE_CTRL_RTC_GET_TIME, &time) == RT_EOK)
-        {
-            level = rt_hw_interrupt_disable();
-            tick = rt_tick_get(); /* get tick */
-            _timevalue.tv_usec = (tick%RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK;
-            _timevalue.tv_sec = time - tick/RT_TICK_PER_SECOND - 1;
-            rt_hw_interrupt_enable(level);
-            return 0;
-        }
-    }
-
-    level = rt_hw_interrupt_disable();
-    _timevalue.tv_usec = 0;
-    _timevalue.tv_sec = 0;
-    rt_hw_interrupt_enable(level);
-
-    return -1;
-}
-INIT_COMPONENT_EXPORT(_rt_clock_time_system_init);
-#endif /* RT_USING_RTC */
 
 int clock_getres(clockid_t clockid, struct timespec *res)
 {
-#ifndef RT_USING_RTC
-    LOG_W(_WARNING_NO_RTC);
-    return -1;
-#else
-    int ret = 0;
-
     if (res == RT_NULL)
     {
         rt_set_errno(EFAULT);
@@ -629,40 +513,29 @@ int clock_getres(clockid_t clockid, struct timespec *res)
 
     switch (clockid)
     {
-    case CLOCK_REALTIME:
-#ifndef RT_USING_CPUTIME
-        res->tv_sec = 0;
-        res->tv_nsec = NANOSECOND_PER_SECOND/RT_TICK_PER_SECOND;
-        break;
-#endif
-#ifdef RT_USING_CPUTIME
-    case CLOCK_CPUTIME_ID:
-        res->tv_sec  = 0;
-        res->tv_nsec = (clock_cpu_getres() / (1000UL * 1000));
-        break;
-#endif
+        case CLOCK_REALTIME:  // use RTC
+        case CLOCK_REALTIME_COARSE:
+            return _control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMERES, res);
+
+        case CLOCK_MONOTONIC:  // use cputimer
+        case CLOCK_MONOTONIC_COARSE:
+        case CLOCK_MONOTONIC_RAW:
+        case CLOCK_BOOTTIME:
+        case CLOCK_PROCESS_CPUTIME_ID:
+        case CLOCK_THREAD_CPUTIME_ID:
+            res->tv_sec  = 0;
+            res->tv_nsec = (rt_ktime_cputimer_getres() / RT_KTIME_RESMUL);
+            return 0;
 
-    default:
-        res->tv_sec  = 0;
-        res->tv_nsec = 0;
-        ret = -1;
-        rt_set_errno(EINVAL);
-        break;
+        default:
+            rt_set_errno(EINVAL);
+            return -1;
     }
-
-    return ret;
-#endif /* RT_USING_RTC */
 }
 RTM_EXPORT(clock_getres);
 
 int clock_gettime(clockid_t clockid, struct timespec *tp)
 {
-#ifndef RT_USING_RTC
-    LOG_W(_WARNING_NO_RTC);
-    return -1;
-#else
-    int ret = 0;
-
     if (tp == RT_NULL)
     {
         rt_set_errno(EFAULT);
@@ -671,172 +544,117 @@ int clock_gettime(clockid_t clockid, struct timespec *tp)
 
     switch (clockid)
     {
-    case CLOCK_REALTIME:
-#ifndef RT_USING_CPUTIME
-        {
-            rt_tick_t tick;
-            rt_base_t level;
-
-            level = rt_hw_interrupt_disable();
-            tick = rt_tick_get(); /* get tick */
-            tp->tv_sec  = _timevalue.tv_sec + tick / RT_TICK_PER_SECOND;
-            tp->tv_nsec = (_timevalue.tv_usec + (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK) * 1000U;
-            rt_hw_interrupt_enable(level);
-            if (tp->tv_nsec > 1000000000ULL)
-            {
-                tp->tv_nsec %= 1000000000ULL;
-                tp->tv_sec += 1;
-            }
-        }
-        break;
-#endif
-#ifdef RT_USING_CPUTIME
-    case CLOCK_MONOTONIC:
-    case CLOCK_CPUTIME_ID:
-        {
-            uint64_t unit = 0;
-            uint64_t cpu_tick;
+        case CLOCK_REALTIME:  // use RTC
+        case CLOCK_REALTIME_COARSE:
+            return _control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMESPEC, tp);
 
-            unit = clock_cpu_getres();
-            cpu_tick = clock_cpu_gettime();
+        case CLOCK_MONOTONIC:  // use boottime
+        case CLOCK_MONOTONIC_COARSE:
+        case CLOCK_MONOTONIC_RAW:
+        case CLOCK_BOOTTIME:
+            return rt_ktime_boottime_get_ns(tp);
 
-            tp->tv_sec  = ((uint64_t)((cpu_tick * unit) / (1000UL * 1000))) / NANOSECOND_PER_SECOND;
-            tp->tv_nsec = ((uint64_t)((cpu_tick * unit) / (1000UL * 1000))) % NANOSECOND_PER_SECOND;
-        }
-        break;
-#endif
-    default:
-        tp->tv_sec  = 0;
-        tp->tv_nsec = 0;
-        rt_set_errno(EINVAL);
-        ret = -1;
-    }
+        case CLOCK_PROCESS_CPUTIME_ID:
+        case CLOCK_THREAD_CPUTIME_ID:
+            return rt_ktime_boottime_get_ns(tp);  // TODO not yet implemented
 
-    return ret;
-#endif /* RT_USING_RTC */
+        default:
+            tp->tv_sec  = 0;
+            tp->tv_nsec = 0;
+            rt_set_errno(EINVAL);
+            return -1;
+    }
 }
 RTM_EXPORT(clock_gettime);
 
 int clock_nanosleep(clockid_t clockid, int flags, const struct timespec *rqtp, struct timespec *rmtp)
 {
-#ifndef RT_USING_RTC
-    LOG_W(_WARNING_NO_RTC);
-    return -1;
-#else
+    struct timespec ts = {0};
+    rt_err_t        err;
+
+    if (rqtp == RT_NULL)
+    {
+        rt_set_errno(EFAULT);
+        return -1;
+    }
+
     if (rqtp->tv_sec < 0 || rqtp->tv_nsec < 0 || rqtp->tv_nsec >= NANOSECOND_PER_SECOND)
     {
         rt_set_errno(EINVAL);
         return -1;
     }
+
     switch (clockid)
     {
-    case CLOCK_REALTIME:
-    {
-        rt_tick_t tick, tick_old = rt_tick_get();
-        if ((flags & TIMER_ABSTIME) == TIMER_ABSTIME)
-        {
-            rt_int64_t ts = ((rqtp->tv_sec - _timevalue.tv_sec) * RT_TICK_PER_SECOND);
-            rt_int64_t tns = (rqtp->tv_nsec - _timevalue.tv_usec * 1000) * (RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND);
-            tick = ts + tns;
-            rt_tick_t rt_tick = rt_tick_get();
-            tick = tick < rt_tick ? 0 : tick - rt_tick;
-        }
-        else
-        {
-            tick = rqtp->tv_sec * RT_TICK_PER_SECOND + ((uint64_t)(rqtp->tv_nsec) * RT_TICK_PER_SECOND) / NANOSECOND_PER_SECOND;
-        }
-        rt_thread_delay(tick);
+        case CLOCK_REALTIME:  // use RTC
+            if (flags & TIMER_ABSTIME)
+                err = _control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMESPEC, &ts);
+            break;
 
-        if (rt_get_errno() == -RT_EINTR)
-        {
-            if (rmtp)
-            {
-                tick = tick_old + tick - rt_tick_get();
-                /* get the passed time */
-                rmtp->tv_sec = tick / RT_TICK_PER_SECOND;
-                rmtp->tv_nsec = (tick % RT_TICK_PER_SECOND) * (NANOSECOND_PER_SECOND / RT_TICK_PER_SECOND);
-            }
-            rt_set_errno(EINTR);
+        case CLOCK_MONOTONIC:  // use boottime
+        case CLOCK_PROCESS_CPUTIME_ID:
+            if (flags & TIMER_ABSTIME)
+                err = rt_ktime_boottime_get_ns(&ts);
+            break;
+
+        default:
+            rt_set_errno(EINVAL);
             return -1;
-        }
     }
-    break;
 
-#ifdef RT_USING_CPUTIME
-    case CLOCK_MONOTONIC:
-    case CLOCK_CPUTIME_ID:
+    if (err != RT_EOK)
+        return err;
+
+    int64_t ns = rqtp->tv_nsec - ts.tv_nsec + (rqtp->tv_sec - ts.tv_sec) * NANOSECOND_PER_SECOND;
+    if (ns <= 0)
+        return 0;
+
+    if (flags & TIMER_ABSTIME)
     {
-        rt_uint64_t cpu_tick_old = clock_cpu_gettime();
-        uint64_t unit = clock_cpu_getres();
-        rt_uint64_t ns = rqtp->tv_sec * NANOSECOND_PER_SECOND + rqtp->tv_nsec;
-        rt_uint64_t tick = (ns * (1000UL * 1000)) / unit;
-        if ((flags & TIMER_ABSTIME) == TIMER_ABSTIME)
-            tick -= cpu_tick_old;
-        rt_cputime_sleep(tick);
-
-        if (rt_get_errno() == -RT_EINTR)
-        {
-            if (rmtp)
-            {
-                uint64_t rmtp_cpu_tick = tick - clock_cpu_gettime();
-                rmtp->tv_sec = ((time_t)((rmtp_cpu_tick * unit) / (1000UL * 1000))) / NANOSECOND_PER_SECOND;
-                rmtp->tv_nsec = ((long)((rmtp_cpu_tick * unit) / (1000UL * 1000))) % NANOSECOND_PER_SECOND;
-            }
-            rt_set_errno(EINTR);
-            return -1;
-        }
+        ts.tv_nsec = ns % NANOSECOND_PER_SECOND;
+        ts.tv_sec  = ns / NANOSECOND_PER_SECOND;
+        return nanosleep(&ts, rmtp);
     }
-    break;
-#endif
-    default:
-        rt_set_errno(EINVAL);
-        return -1;
+    else
+    {
+        return nanosleep(rqtp, rmtp);
     }
-    return 0;
-#endif
 }
 RTM_EXPORT(clock_nanosleep);
 
 int clock_settime(clockid_t clockid, const struct timespec *tp)
 {
-#ifndef RT_USING_RTC
-    LOG_W(_WARNING_NO_RTC);
-    return -1;
-#else
-    rt_base_t level;
-    int second;
-    rt_tick_t tick;
-    rt_device_t device;
-
-    if ((clockid != CLOCK_REALTIME) || (tp == RT_NULL))
+    if (tp == RT_NULL)
     {
         rt_set_errno(EFAULT);
         return -1;
     }
 
-    /* get second */
-    second = tp->tv_sec;
-
-    level = rt_hw_interrupt_disable();
-    tick = rt_tick_get(); /* get tick */
-    /* update timevalue */
-    _timevalue.tv_usec = MICROSECOND_PER_SECOND - (tick % RT_TICK_PER_SECOND) * MICROSECOND_PER_TICK;
-    _timevalue.tv_sec = second - tick / RT_TICK_PER_SECOND - 1;
-    rt_hw_interrupt_enable(level);
-
-    /* update for RTC device */
-    device = rt_device_find("rtc");
-    if (device != RT_NULL)
+    if (tp->tv_sec < 0 || tp->tv_nsec < 0 || tp->tv_nsec >= NANOSECOND_PER_SECOND)
     {
-        /* set realtime seconds */
-        if(rt_device_control(device, RT_DEVICE_CTRL_RTC_SET_TIME, &second) == RT_EOK)
-        {
-            return 0;
-        }
+        rt_set_errno(EINVAL);
+        return -1;
     }
 
-    return -1;
-#endif /* RT_USING_RTC */
+    switch (clockid)
+    {
+        case CLOCK_REALTIME:
+            return _control_rtc(RT_DEVICE_CTRL_RTC_SET_TIMESPEC, (void *)tp);
+
+        case CLOCK_REALTIME_COARSE:
+        case CLOCK_MONOTONIC:
+        case CLOCK_MONOTONIC_COARSE:
+        case CLOCK_MONOTONIC_RAW:
+        case CLOCK_BOOTTIME:
+        case CLOCK_PROCESS_CPUTIME_ID:
+        case CLOCK_THREAD_CPUTIME_ID:
+            rt_set_errno(EPERM);
+            return -1;
+
+        default:
+            rt_set_errno(EINVAL);
+            return -1;
+    }
 }
 RTM_EXPORT(clock_settime);
 
@@ -884,18 +702,12 @@ RTM_EXPORT(rt_timespec_to_tick);
 
 struct timer_obj
 {
-    union
-    {
-        struct rt_timer timer;
-#ifdef RT_USING_CPUTIME
-        struct rt_cputimer cputimer;
-#endif
-    };
+    struct rt_ktime_hrtimer hrtimer;
     void (*sigev_notify_function)(union sigval val);
     union sigval val;
     struct timespec interval;              /* Reload value */
     struct timespec value;                 /* Reload value */
-    rt_uint64_t reload;                    /* Reload value in ms */
+    unsigned long reload;                    /* Reload value in ms */
     rt_uint32_t status;
     int sigev_signo;
     clockid_t clockid;
@@ -915,21 +727,13 @@ static void rtthread_timer_wrapper(void *timerobj)
         timer->status = NOT_ACTIVE;
     }
 
-#ifdef RT_USING_CPUTIME
-    if (timer->clockid == CLOCK_CPUTIME_ID && clock_cpu_issettimeout())
-    {
-        timer->reload = ((timer->interval.tv_sec * NANOSECOND_PER_SECOND + timer->interval.tv_nsec) * (1000UL * 1000)) / clock_cpu_getres();
-        if (timer->reload)
-            rt_cputimer_control(&timer->cputimer, RT_TIMER_CTRL_SET_TIME, &(timer->reload));
-    }
-    else
-#endif /* RT_USING_CPUTIME */
+    timer->reload = ((timer->interval.tv_sec * NANOSECOND_PER_SECOND + timer->interval.tv_nsec) * RT_KTIME_RESMUL) /
+                    rt_ktime_cputimer_getres();
+    if (timer->reload)
     {
-        timer->reload = (timer->interval.tv_sec * RT_TICK_PER_SECOND) + (timer->interval.tv_nsec * RT_TICK_PER_SECOND) / NANOSECOND_PER_SECOND;
-        if (timer->reload)
-            rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_TIME, &(timer->reload));
+        rt_ktime_hrtimer_control(&timer->hrtimer, RT_TIMER_CTRL_SET_TIME, &(timer->reload));
+        rt_ktime_hrtimer_start(&timer->hrtimer);
     }
-
 #ifdef RT_USING_SMART
     sys_kill(timer->pid, timer->sigev_signo);
 #else
@@ -960,14 +764,33 @@ int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
     struct timer_obj *timer;
     char timername[RT_NAME_MAX] = {0};
 
-    if (clockid > CLOCK_ID_MAX ||
-        (evp->sigev_notify != SIGEV_NONE &&
-         evp->sigev_notify != SIGEV_SIGNAL))
+    if (evp == RT_NULL || timerid == RT_NULL)
+    {
+        rt_set_errno(EINVAL);
+        return -1;
+    }
+
+    if (evp->sigev_notify == SIGEV_THREAD)  // TODO need to implement
     {
         rt_set_errno(EINVAL);
         return -1;
     }
 
+    switch (clockid)
+    {
+        case CLOCK_REALTIME:
+        case CLOCK_REALTIME_ALARM:
+        case CLOCK_MONOTONIC:
+        case CLOCK_BOOTTIME:
+        case CLOCK_BOOTTIME_ALARM:
+        case CLOCK_PROCESS_CPUTIME_ID:
+        case CLOCK_THREAD_CPUTIME_ID:
+            break;  // Only these ids are supported
+        default:
+            rt_set_errno(EINVAL);
+            return -1;
+    }
+
     timer = rt_malloc(sizeof(struct timer_obj));
     if(timer == RT_NULL)
     {
@@ -989,19 +812,8 @@ int timer_create(clockid_t clockid, struct sigevent *evp, timer_t *timerid)
     timer->status = NOT_ACTIVE;
     timer->clockid = clockid;
 
-#ifdef RT_USING_CPUTIME
-    if (timer->clockid == CLOCK_CPUTIME_ID && clock_cpu_issettimeout())
-    {
-        rt_cputimer_init(&timer->cputimer, timername, rtthread_timer_wrapper, timer, 0, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
-    }
-    else
-#endif /* RT_USING_CPUTIME */
-    {
-        if (evp->sigev_notify == SIGEV_NONE)
-            rt_timer_init(&timer->timer, timername, RT_NULL, RT_NULL, 0, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
-        else
-            rt_timer_init(&timer->timer, timername, rtthread_timer_wrapper, timer, 0, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_SOFT_TIMER);
-    }
+    rt_ktime_hrtimer_init(&timer->hrtimer, timername, 0, RT_TIMER_FLAG_ONE_SHOT | RT_TIMER_FLAG_HARD_TIMER,
+                          rtthread_timer_wrapper, timer);
 
     _timerid = resource_id_get(&id_timer);
     if (_timerid < 0)
@@ -1048,28 +860,14 @@ int timer_delete(timer_t timerid)
         return -1;
     }
 
-#ifdef RT_USING_CPUTIME
-    if (timer->clockid == CLOCK_CPUTIME_ID && clock_cpu_issettimeout())
-    {
-        if (timer->status == ACTIVE)
-        {
-            timer->status = NOT_ACTIVE;
-            rt_cputimer_stop(&timer->cputimer);
-        }
-        rt_cputimer_detach(&timer->cputimer);
-    }
-    else
-#endif /* RT_USING_CPUTIME */
+    if (timer->status == ACTIVE)
     {
-        if (timer->status == ACTIVE)
-        {
-            timer->status = NOT_ACTIVE;
-            rt_timer_stop(&timer->timer);
-        }
-        rt_timer_detach(&timer->timer);
+        timer->status = NOT_ACTIVE;
+        rt_ktime_hrtimer_stop(&timer->hrtimer);
     }
-    rt_free(timer);
+    rt_ktime_hrtimer_detach(&timer->hrtimer);
 
+    rt_free(timer);
     return 0;
 }
 RTM_EXPORT(timer_delete);
@@ -1111,45 +909,11 @@ int timer_gettime(timer_t timerid, struct itimerspec *its)
 
     if (timer->status == ACTIVE)
     {
-#ifdef RT_USING_CPUTIME
-        if (timer->clockid == CLOCK_CPUTIME_ID && clock_cpu_issettimeout())
-        {
-            rt_uint64_t remain_tick;
-            rt_uint64_t remaining;
-            rt_cputimer_control(&timer->cputimer, RT_TIMER_CTRL_GET_REMAIN_TIME, &remain_tick);
-            remaining = ((remain_tick - clock_cpu_gettime()) * (1000UL * 1000)) / clock_cpu_getres();
-            seconds = remaining / NANOSECOND_PER_SECOND;
-            nanoseconds = remaining % NANOSECOND_PER_SECOND;
-        }
-        else
-#endif /* RT_USING_CPUTIME */
-        {
-            rt_tick_t remain_tick;
-            rt_tick_t remaining;
-
-            rt_timer_control(&timer->timer, RT_TIMER_CTRL_GET_REMAIN_TIME, &remain_tick);
-
-            /* 'remain_tick' is minimum-unit in the RT-Thread' timer,
-            * so the seconds, nanoseconds will be calculated by 'remain_tick'.
-            */
-            remaining = remain_tick - rt_tick_get();
-
-            /* calculate 'second' */
-            seconds = remaining / RT_TICK_PER_SECOND;
-
-            /* calculate 'nanosecond';  To avoid lost of accuracy, because "RT_TICK_PER_SECOND" maybe 100, 1000, 1024 and so on.
-            *
-            *        remain_tick                  millisecond                                 remain_tick * MILLISECOND_PER_SECOND
-            *  ------------------------- = --------------------------  --->  millisecond = -------------------------------------------
-            *    RT_TICK_PER_SECOND          MILLISECOND_PER_SECOND                                RT_TICK_PER_SECOND
-            *
-            *                    remain_tick * MILLISECOND_PER_SECOND                          remain_tick * MILLISECOND_PER_SECOND * MICROSECOND_PER_SECOND
-            *   millisecond = ----------------------------------------  ---> nanosecond = -------------------------------------------------------------------
-            *                         RT_TICK_PER_SECOND                                                           RT_TICK_PER_SECOND
-            *
-            */
-            nanoseconds = (((remaining % RT_TICK_PER_SECOND) * MILLISECOND_PER_SECOND) * MICROSECOND_PER_SECOND) / RT_TICK_PER_SECOND;
-        }
+        unsigned long remain_cnt;
+        rt_ktime_hrtimer_control(&timer->hrtimer, RT_TIMER_CTRL_GET_REMAIN_TIME, &remain_cnt);
+        nanoseconds = ((remain_cnt - rt_ktime_cputimer_getcnt()) * rt_ktime_cputimer_getres()) / RT_KTIME_RESMUL;
+        seconds     = nanoseconds / NANOSECOND_PER_SECOND;
+        nanoseconds = nanoseconds % NANOSECOND_PER_SECOND;
         its->it_value.tv_sec = (rt_int32_t)seconds;
         its->it_value.tv_nsec = (rt_int32_t)nanoseconds;
     }
@@ -1174,6 +938,9 @@ RTM_EXPORT(timer_gettime);
 int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
                   struct itimerspec *ovalue)
 {
+    struct timespec ts = {0};
+    rt_err_t        err = RT_EOK;
+
     struct timer_obj *timer;
     timer = _g_timerid[(rt_ubase_t)timerid];
     if (timer == NULL ||
@@ -1199,97 +966,61 @@ int timer_settime(timer_t timerid, int flags, const struct itimerspec *value,
     {
         if (timer->status == ACTIVE)
         {
-#ifdef RT_USING_CPUTIME
-            if (timer->clockid == CLOCK_CPUTIME_ID && clock_cpu_issettimeout())
-                rt_cputimer_stop(&timer->cputimer);
-            else
-#endif /* RT_USING_CPUTIME */
-                rt_timer_stop(&timer->timer);
+            rt_ktime_hrtimer_stop(&timer->hrtimer);
         }
 
         timer->status = NOT_ACTIVE;
         return 0;
     }
 
-    /* calculate timer period(tick);  To avoid lost of accuracy, because "RT_TICK_PER_SECOND" maybe 100, 1000, 1024 and so on.
-        *
-        *          tick                        nanosecond                          nanosecond * RT_TICK_PER_SECOND
-        *  ------------------------- = --------------------------  --->  tick = -------------------------------------
-        *    RT_TICK_PER_SECOND           NANOSECOND_PER_SECOND                         NANOSECOND_PER_SECOND
-        *
-        */
-#ifdef RT_USING_CPUTIME
-    if (timer->clockid == CLOCK_CPUTIME_ID && clock_cpu_issettimeout())
+    switch (timer->clockid)
     {
-        rt_uint64_t tick;
-        uint64_t unit = clock_cpu_getres();
-
-        tick = ((value->it_value.tv_sec * NANOSECOND_PER_SECOND + value->it_value.tv_nsec) * (1000UL * 1000)) / unit;
-        if ((flags & TIMER_ABSTIME) == TIMER_ABSTIME)
-        {
-            tick -= clock_cpu_gettime();
-        }
-        timer->reload = tick;
-    }
-    else
-#endif /* RT_USING_CPUTIME */
-    {
-        if ((flags & TIMER_ABSTIME) == TIMER_ABSTIME)
-        {
-#ifndef RT_USING_RTC
-            LOG_W(_WARNING_NO_RTC);
+        case CLOCK_REALTIME:
+        case CLOCK_REALTIME_ALARM:
+            if (flags & TIMER_ABSTIME)
+                err = _control_rtc(RT_DEVICE_CTRL_RTC_GET_TIMESPEC, &ts);
+            break;
+        case CLOCK_MONOTONIC:
+        case CLOCK_BOOTTIME:
+        case CLOCK_BOOTTIME_ALARM:
+        case CLOCK_PROCESS_CPUTIME_ID:
+        case CLOCK_THREAD_CPUTIME_ID:
+            if (flags & TIMER_ABSTIME)
+                err = rt_ktime_boottime_get_ns(&ts);
+            break;
+        default:
+            rt_set_errno(EINVAL);
             return -1;
-#else
-                rt_int64_t ts = ((value->it_value.tv_sec - _timevalue.tv_sec) * RT_TICK_PER_SECOND);
-                rt_int64_t tns = (value->it_value.tv_nsec - _timevalue.tv_usec * 1000) * (RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND);
-                rt_int64_t reload = ts + tns;
-                rt_tick_t rt_tick = rt_tick_get();
-
-                timer->reload = reload < rt_tick ? 0 : reload - rt_tick;
-#endif
-        }
-        else
-            timer->reload = (value->it_value.tv_sec * RT_TICK_PER_SECOND) + value->it_value.tv_nsec * (RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND);
     }
-    timer->interval.tv_sec = value->it_interval.tv_sec;
+
+    if (err != RT_EOK)
+        return err;
+
+    int64_t ns = value->it_value.tv_nsec - ts.tv_nsec + (value->it_value.tv_sec - ts.tv_sec) * NANOSECOND_PER_SECOND;
+
+    if (ns <= 0)
+        return 0;
+
+    unsigned long res       = rt_ktime_cputimer_getres();
+    timer->reload           = (ns * RT_KTIME_RESMUL) / res;
+    timer->interval.tv_sec  = value->it_interval.tv_sec;
     timer->interval.tv_nsec = value->it_interval.tv_nsec;
-    timer->value.tv_sec = value->it_value.tv_sec;
-    timer->value.tv_nsec = value->it_value.tv_nsec;
+    timer->value.tv_sec     = value->it_value.tv_sec;
+    timer->value.tv_nsec    = value->it_value.tv_nsec;
 
     if (timer->status == ACTIVE)
     {
-#ifdef RT_USING_CPUTIME
-        if (timer->clockid == CLOCK_CPUTIME_ID && clock_cpu_issettimeout())
-            rt_cputimer_stop(&timer->cputimer);
-        else
-#endif /* RT_USING_CPUTIME */
-            rt_timer_stop(&timer->timer);
+        rt_ktime_hrtimer_stop(&timer->hrtimer);
     }
-
     timer->status = ACTIVE;
 
-#ifdef RT_USING_CPUTIME
-    if (timer->clockid == CLOCK_CPUTIME_ID && clock_cpu_issettimeout())
-    {
-        if ((value->it_interval.tv_sec == 0) && (value->it_interval.tv_nsec == 0))
-            rt_cputimer_control(&timer->cputimer, RT_TIMER_CTRL_SET_ONESHOT, RT_NULL);
-        else
-            rt_cputimer_control(&timer->cputimer, RT_TIMER_CTRL_SET_PERIODIC, RT_NULL);
-
-        rt_cputimer_control(&timer->cputimer, RT_TIMER_CTRL_SET_TIME, &(timer->reload));
-        rt_cputimer_start(&timer->cputimer);
-    }
+    if ((value->it_interval.tv_sec == 0) && (value->it_interval.tv_nsec == 0))
+        rt_ktime_hrtimer_control(&timer->hrtimer, RT_TIMER_CTRL_SET_ONESHOT, RT_NULL);
     else
-#endif /* RT_USING_CPUTIME */
-    {
-        if ((value->it_interval.tv_sec == 0) && (value->it_interval.tv_nsec == 0))
-            rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_ONESHOT, RT_NULL);
-        else
-            rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_PERIODIC, RT_NULL);
+        rt_ktime_hrtimer_control(&timer->hrtimer, RT_TIMER_CTRL_SET_PERIODIC, RT_NULL);
 
-        rt_timer_control(&timer->timer, RT_TIMER_CTRL_SET_TIME, &(timer->reload));
-        rt_timer_start(&timer->timer);
-    }
+    rt_ktime_hrtimer_control(&timer->hrtimer, RT_TIMER_CTRL_SET_TIME, &(timer->reload));
+    rt_ktime_hrtimer_start(&timer->hrtimer);
 
     return 0;
 }

+ 35 - 2
components/libc/compilers/common/include/sys/time.h

@@ -139,8 +139,12 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
 #if defined(RT_USING_POSIX_CLOCK) || defined (RT_USING_POSIX_TIMER)
 /* POSIX clock and timer */
 
+#ifndef CLOCK_REALTIME_COARSE
+#define CLOCK_REALTIME_COARSE 0
+#endif /* CLOCK_REALTIME_COARSE */
+
 #ifndef CLOCK_REALTIME
-#define CLOCK_REALTIME      1
+#define CLOCK_REALTIME 1
 #endif /* CLOCK_REALTIME */
 
 #define CLOCK_CPUTIME_ID    2
@@ -150,13 +154,37 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
 #endif /* CLOCK_PROCESS_CPUTIME_ID */
 
 #ifndef CLOCK_THREAD_CPUTIME_ID
-#define CLOCK_THREAD_CPUTIME_ID  CLOCK_CPUTIME_ID
+#define CLOCK_THREAD_CPUTIME_ID 3
 #endif /* CLOCK_THREAD_CPUTIME_ID */
 
 #ifndef CLOCK_MONOTONIC
 #define CLOCK_MONOTONIC     4
 #endif /* CLOCK_MONOTONIC */
 
+#ifndef CLOCK_MONOTONIC_RAW
+#define CLOCK_MONOTONIC_RAW 5
+#endif /* CLOCK_MONOTONIC_RAW */
+
+#ifndef CLOCK_MONOTONIC_COARSE
+#define CLOCK_MONOTONIC_COARSE 6
+#endif /* CLOCK_MONOTONIC_COARSE */
+
+#ifndef CLOCK_BOOTTIME
+#define CLOCK_BOOTTIME 7
+#endif /* CLOCK_BOOTTIME */
+
+#ifndef CLOCK_REALTIME_ALARM
+#define CLOCK_REALTIME_ALARM 8
+#endif /* CLOCK_REALTIME_ALARM */
+
+#ifndef CLOCK_BOOTTIME_ALARM
+#define CLOCK_BOOTTIME_ALARM 9
+#endif /* CLOCK_BOOTTIME_ALARM */
+
+#ifndef CLOCK_SGI_CYCLE
+#define CLOCK_SGI_CYCLE 10 // newlib says they don't have this definition,  make the compiler happy
+#endif /* CLOCK_SGI_CYCLE */
+
 #ifndef TIMER_ABSTIME
 #define TIMER_ABSTIME       4
 #endif /* TIMER_ABSTIME */
@@ -166,6 +194,11 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp);
 #else
 #define CLOCK_ID_MAX CLOCK_MONOTONIC
 #endif
+
+#ifndef CLOCK_TAI
+#define CLOCK_TAI 11  // newlib says they don't have this definition,  make the compiler happy
+#endif /* CLOCK_TAI */
+
 #endif /* defined(RT_USING_POSIX_CLOCK) || defined (RT_USING_POSIX_TIMER) */
 
 #ifdef RT_USING_POSIX_CLOCK

+ 1 - 1
components/libc/posix/signal/posix_signal.c

@@ -172,7 +172,7 @@ int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *ti
 
     if (timeout)
     {
-        tick = rt_timespec_to_tick(timeout);
+        tick = timeout->tv_sec * RT_TICK_PER_SECOND + timeout->tv_nsec * RT_TICK_PER_SECOND / NANOSECOND_PER_SECOND;
     }
 
     ret = rt_signal_wait(set, info, tick);

+ 1 - 4
libcpu/risc-v/virt64/tick.c

@@ -28,7 +28,6 @@ static uint64_t get_ticks()
 int tick_isr(void)
 {
     // uint64_t core_id = current_coreid();
-    int tick_cycles = 40000;
     // clint->mtimecmp[core_id] += tick_cycles;
     rt_tick_increase();
     sbi_set_timer(get_ticks() + tick_cycles);
@@ -41,14 +40,12 @@ int rt_hw_tick_init(void)
 {
     /* Read core id */
     // unsigned long core_id = current_coreid();
-    unsigned long interval = 1000/RT_TICK_PER_SECOND;
 
     /* Clear the Supervisor-Timer bit in SIE */
     clear_csr(sie, SIP_STIP);
 
     /* calculate the tick cycles */
-    // tick_cycles = interval * sysctl_clock_get_freq(SYSCTL_CLOCK_CPU) / CLINT_CLOCK_DIV / 1000ULL - 1;
-    tick_cycles = 40000;
+    tick_cycles = CPUTIME_TIMER_FREQ / RT_TICK_PER_SECOND;
     /* Set timer */
     sbi_set_timer(get_ticks() + tick_cycles);