1 /*
2  * Copyright (c) 2006-2024, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2024/01/11     flyingcys    The first version
9  */
10 
11 #include <rthw.h>
12 #include <rtthread.h>
13 
14 #include <encoding.h>
15 #include "tick.h"
16 
17 static volatile rt_uint64_t time_elapsed = 0;
18 static volatile unsigned long tick_cycles = 0;
19 
20 #define CLINT_BASE (BSP_PLIC_PHY_ADDR + 0x4000000UL)
21 
22 static volatile rt_uint32_t *mtimecmp_l = (volatile rt_uint32_t *)(CLINT_BASE + 0x4000UL);
23 static volatile rt_uint32_t *mtimecmp_h = (volatile rt_uint32_t *)(CLINT_BASE + 0x4004UL);
24 
set_ticks(rt_uint64_t value)25 rt_inline void set_ticks(rt_uint64_t value)
26 {
27     *mtimecmp_l = 0xFFFFFFFF;
28     *mtimecmp_h = (rt_uint32_t)(value >> 32);
29     *mtimecmp_l = (rt_uint32_t)(value & 0xFFFFFFFF);
30 }
31 
get_ticks(void)32 static rt_uint64_t get_ticks(void)
33 {
34     __asm__ __volatile__(
35         "rdtime %0"
36         : "=r"(time_elapsed));
37     return time_elapsed;
38 }
39 
rt_hw_tick_isr(void)40 int rt_hw_tick_isr(void)
41 {
42     rt_tick_increase();
43     set_ticks(get_ticks() + tick_cycles);
44     return 0;
45 }
46 
47 /* Sets and enable the timer interrupt */
rt_hw_tick_init(void)48 int rt_hw_tick_init(void)
49 {
50     /* Clear the Machine-Timer bit in MIE */
51     clear_csr(mie, MIP_MTIP);
52 
53     tick_cycles = BSP_TIMER_CLK_FREQ / RT_TICK_PER_SECOND;
54 
55     set_ticks(get_ticks() + tick_cycles);
56 
57     rt_kprintf("[rt_hw_tick_init] time_elapsed: %d tick_cycles:%d\n", time_elapsed, tick_cycles);
58 
59     /* Enable the Machine-Timer bit in MIE */
60     set_csr(mie, MIP_MTIP);
61 
62     return 0;
63 }
64 
65 /**
66  * This function will delay for some us.
67  *
68  * @param us the delay time of us
69  */
rt_hw_us_delay(rt_uint32_t us)70 void rt_hw_us_delay(rt_uint32_t us)
71 {
72     unsigned long start_time;
73     unsigned long end_time;
74     unsigned long run_time;
75 
76     start_time = get_ticks();
77     end_time = start_time + us * (BSP_TIMER_CLK_FREQ / 1000000);
78     do{
79         run_time = get_ticks();
80     } while(run_time < end_time);
81 }
82