clock.c 3.7 KB
Newer Older
1
/*
mysterywolf's avatar
mysterywolf 已提交
2
 * Copyright (c) 2006-2021, RT-Thread Development Team
B
Bernard Xiong 已提交
3
 *
4
 * SPDX-License-Identifier: Apache-2.0
B
Bernard Xiong 已提交
5
 *
6 7 8 9
 * Change Logs:
 * Date           Author       Notes
 * 2006-03-12     Bernard      first version
 * 2006-05-27     Bernard      add support for same priority thread schedule
10
 * 2006-08-10     Bernard      remove the last rt_schedule in rt_tick_increase
11
 * 2010-03-08     Bernard      remove rt_passed_second
12
 * 2010-05-20     Bernard      fix the tick exceeds the maximum limits
13
 * 2010-07-13     Bernard      fix rt_tick_from_millisecond issue found by kuronca
14
 * 2011-06-26     Bernard      add rt_tick_set function.
S
shaojinchun 已提交
15
 * 2018-11-22     Jesven       add per cpu tick
16 17
 * 2020-12-29     Meco Man     implement rt_tick_get_millisecond()
 * 2021-06-01     Meco Man     add critical section projection for rt_tick_increase()
18 19
 */

20
#include <rthw.h>
21 22
#include <rtthread.h>

S
shaojinchun 已提交
23 24 25
#ifdef RT_USING_SMP
#define rt_tick rt_cpu_index(0)->tick
#else
26
static volatile rt_tick_t rt_tick = 0;
mysterywolf's avatar
mysterywolf 已提交
27
#endif /* RT_USING_SMP */
28 29 30 31 32

/**
 * @addtogroup Clock
 */

D
dogandog 已提交
33
/**@{*/
34 35

/**
36
 * @brief    This function will return current tick from operating system startup
37
 *
38
 * @return   Return current tick
39
 */
D
dzzxzz 已提交
40
rt_tick_t rt_tick_get(void)
41
{
42 43
    /* return the global tick */
    return rt_tick;
44
}
45
RTM_EXPORT(rt_tick_get);
46

47
/**
48
 * @brief    This function will set current tick
G
guozhanxin 已提交
49
 *
50
 * @param    tick is the value that you will set.
51 52 53
 */
void rt_tick_set(rt_tick_t tick)
{
54
    rt_base_t level;
55

56 57 58
    level = rt_hw_interrupt_disable();
    rt_tick = tick;
    rt_hw_interrupt_enable(level);
59 60
}

61
/**
62 63
 * @brief    This function will notify kernel there is one tick passed.
 *           Normally, this function is invoked by clock ISR.
64
 */
D
dzzxzz 已提交
65
void rt_tick_increase(void)
66
{
67
    struct rt_thread *thread;
68 69 70
    rt_base_t level;

    level = rt_hw_interrupt_disable();
71

72
    /* increase the global tick */
S
shaojinchun 已提交
73 74 75
#ifdef RT_USING_SMP
    rt_cpu_self()->tick ++;
#else
76
    ++ rt_tick;
mysterywolf's avatar
mysterywolf 已提交
77
#endif /* RT_USING_SMP */
78

79 80
    /* check time slice */
    thread = rt_thread_self();
81

82 83 84 85 86
    -- thread->remaining_tick;
    if (thread->remaining_tick == 0)
    {
        /* change to initialized tick */
        thread->remaining_tick = thread->init_tick;
87
        thread->stat |= RT_THREAD_STAT_YIELD;
88

89
        rt_hw_interrupt_enable(level);
90
        rt_schedule();
91
    }
92 93 94 95
    else
    {
        rt_hw_interrupt_enable(level);
    }
96

97 98
    /* check timer */
    rt_timer_check();
99 100 101
}

/**
102
 * @brief    This function will calculate the tick from millisecond.
103
 *
104 105 106 107
 * @param    ms is the specified millisecond
 *              - Negative Number wait forever
 *              - Zero not wait
 *              - Max 0x7fffffff
108
 *
109
 * @return   Return the calculated tick
110
 */
111
rt_tick_t rt_tick_from_millisecond(rt_int32_t ms)
112
{
113
    rt_tick_t tick;
B
bernard 已提交
114 115

    if (ms < 0)
E
Ernest Chen 已提交
116 117
    {
        tick = (rt_tick_t)RT_WAITING_FOREVER;
118
    }
B
bernard 已提交
119
    else
120 121
    {
        tick = RT_TICK_PER_SECOND * (ms / 1000);
E
Ernest Chen 已提交
122
        tick += (RT_TICK_PER_SECOND * (ms % 1000) + 999) / 1000;
123
    }
mysterywolf's avatar
mysterywolf 已提交
124

125
    /* return the calculated tick */
B
bernard 已提交
126
    return tick;
127
}
128
RTM_EXPORT(rt_tick_from_millisecond);
129

mysterywolf's avatar
mysterywolf 已提交
130
/**
131
 * @brief    This function will return the passed millisecond from boot.
G
guozhanxin 已提交
132
 *
G
guozhanxin 已提交
133
 * @note     if the value of RT_TICK_PER_SECOND is lower than 1000 or
134 135
 *           is not an integral multiple of 1000, this function will not
 *           provide the correct 1ms-based tick.
G
guozhanxin 已提交
136
 *
137
 * @return   Return passed millisecond from boot
mysterywolf's avatar
mysterywolf 已提交
138
 */
mysterywolf's avatar
update  
mysterywolf 已提交
139
RT_WEAK rt_tick_t rt_tick_get_millisecond(void)
mysterywolf's avatar
mysterywolf 已提交
140
{
mysterywolf's avatar
update  
mysterywolf 已提交
141 142
#if 1000 % RT_TICK_PER_SECOND == 0u
    return rt_tick_get() * (1000u / RT_TICK_PER_SECOND);
mysterywolf's avatar
mysterywolf 已提交
143 144 145 146
#else
    #warning "rt-thread cannot provide a correct 1ms-based tick any longer,\
    please redefine this function in another file by using a high-precision hard-timer."
    return 0;
mysterywolf's avatar
mysterywolf 已提交
147
#endif /* 1000 % RT_TICK_PER_SECOND == 0u */
mysterywolf's avatar
mysterywolf 已提交
148 149
}

D
dogandog 已提交
150
/**@}*/
151