1 /*
2  * Copyright (C) 2017 XRADIO TECHNOLOGY CO., LTD. All rights reserved.
3  *
4  *  Redistribution and use in source and binary forms, with or without
5  *  modification, are permitted provided that the following conditions
6  *  are met:
7  *    1. Redistributions of source code must retain the above copyright
8  *       notice, this list of conditions and the following disclaimer.
9  *    2. Redistributions in binary form must reproduce the above copyright
10  *       notice, this list of conditions and the following disclaimer in the
11  *       documentation and/or other materials provided with the
12  *       distribution.
13  *    3. Neither the name of XRADIO TECHNOLOGY CO., LTD. nor the names of
14  *       its contributors may be used to endorse or promote products derived
15  *       from this software without specific prior written permission.
16  *
17  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20  *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21  *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22  *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23  *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "os_timer.h"
31 #include "os_util.h"
32 
33 
34 /**
35  * @brief Create and initialize a timer object
36  *
37  * @note Creating a timer does not start the timer running. The OS_TimerStart()
38  *       and OS_TimerChangePeriod() API functions can all be used to start the
39  *       timer running.
40  *
41  * @param[in] timer Pointer to the timer object
42  * @param[in] type Timer type
43  * @param[in] cb Timer expire callback function
44  * @param[in] arg Argument of Timer expire callback function
45  * @param[in] periodMS Timer period in milliseconds
46  * @retval OS_Status, OS_OK on success
47  */
OS_TimerCreate(OS_Timer_t * timer,OS_TimerType type,OS_TimerCallback_t cb,void * arg,OS_Time_t periodMS)48 OS_Status OS_TimerCreate(OS_Timer_t *timer, OS_TimerType type,
49                          OS_TimerCallback_t cb, void *arg, OS_Time_t periodMS)
50 {
51     rt_uint8_t flag;
52 
53     OS_HANDLE_ASSERT(!OS_TimerIsValid(timer), timer->handle);
54 
55     flag = RT_TIMER_FLAG_SOFT_TIMER;
56     if (type == OS_TIMER_PERIODIC) {
57         flag |= RT_TIMER_FLAG_PERIODIC;
58     } else {
59         flag |= RT_TIMER_FLAG_ONE_SHOT;
60     }
61 
62     timer->handle = rt_timer_create("os_timer", cb, arg,
63                                     OS_MSecsToTicks(periodMS), flag);
64     OS_DBG("%s(), handle %p\n", __func__, timer->handle);
65 
66     if (timer->handle == NULL) {
67         OS_ERR("err %"OS_HANDLE_F"\n", timer->handle);
68         return OS_FAIL;
69     }
70     return OS_OK;
71 }
72 
OS_TimerDelete(OS_Timer_t * timer)73 OS_Status OS_TimerDelete(OS_Timer_t *timer)
74 {
75     rt_err_t ret;
76 
77     OS_DBG("%s(), handle %p\n", __func__, timer->handle);
78     OS_HANDLE_ASSERT(OS_TimerIsValid(timer), timer->handle);
79 
80     ret = rt_timer_delete(timer->handle);
81     if (ret != RT_EOK) {
82         OS_ERR("err %"OS_BASETYPE_F"\n", ret);
83         return OS_FAIL;
84     }
85 
86     OS_TimerSetInvalid(timer);
87     return OS_OK;
88 }
89 
90 /**
91  * @brief Start a timer running.
92  * @note If the timer is already running, this function will re-start the timer.
93  * @param[in] timer Pointer to the timer object
94  * @retval OS_Status, OS_OK on success
95  */
OS_TimerStart(OS_Timer_t * timer)96 OS_Status OS_TimerStart(OS_Timer_t *timer)
97 {
98     rt_err_t ret;
99 
100     OS_DBG("%s(), handle %p\n", __func__, timer->handle);
101     OS_HANDLE_ASSERT(OS_TimerIsValid(timer), timer->handle);
102 
103     ret = rt_timer_start(timer->handle);
104     if (ret != RT_EOK) {
105         OS_ERR("err %"OS_BASETYPE_F"\n", ret);
106         return OS_FAIL;
107     }
108 
109     return OS_OK;
110 }
111 
112 /**
113  * @brief Change the period of a timer
114  *
115  * If OS_TimerChangePeriod() is used to change the period of a timer that is
116  * already running, then the timer will use the new period value to recalculate
117  * its expiry time. The recalculated expiry time will then be relative to when
118  * OS_TimerChangePeriod() was called, and not relative to when the timer was
119  * originally started.
120 
121  * If OS_TimerChangePeriod() is used to change the period of a timer that is
122  * not already running, then the timer will use the new period value to
123  * calculate an expiry time, and the timer will start running.
124  *
125  * @param[in] timer Pointer to the timer object
126  * @retval OS_Status, OS_OK on success
127  */
OS_TimerChangePeriod(OS_Timer_t * timer,OS_Time_t periodMS)128 OS_Status OS_TimerChangePeriod(OS_Timer_t *timer, OS_Time_t periodMS)
129 {
130     rt_err_t ret;
131 
132     OS_DBG("%s(), handle %p\n", __func__, timer->handle);
133     OS_HANDLE_ASSERT(OS_TimerIsValid(timer), timer->handle);
134 
135     if (OS_TimerIsActive(timer)) {
136         ret = rt_timer_stop(timer->handle);
137         if (ret != RT_EOK) {
138             OS_ERR("err %"OS_BASETYPE_F"\n", ret);
139             return OS_FAIL;
140         }
141     }
142     ret = rt_timer_control(timer->handle, RT_TIMER_CTRL_SET_TIME, &periodMS);
143     if (ret != RT_EOK) {
144         OS_ERR("err %"OS_BASETYPE_F"\n", ret);
145         return OS_FAIL;
146     }
147     ret = rt_timer_start(timer->handle);
148     if (ret != RT_EOK) {
149         OS_ERR("err %"OS_BASETYPE_F"\n", ret);
150         return OS_FAIL;
151     }
152 
153     return OS_OK;
154 }
155 
156 /**
157  * @brief Stop a timer running.
158  * @param[in] timer Pointer to the timer object
159  * @retval OS_Status, OS_OK on success
160  */
OS_TimerStop(OS_Timer_t * timer)161 OS_Status OS_TimerStop(OS_Timer_t *timer)
162 {
163     rt_err_t ret;
164 
165     OS_DBG("%s(), handle %p\n", __func__, timer->handle);
166     OS_HANDLE_ASSERT(OS_TimerIsValid(timer), timer->handle);
167 
168     if (!OS_TimerIsActive(timer)) {
169         return OS_OK;
170     }
171 
172     ret = rt_timer_stop(timer->handle);
173     if (ret != RT_EOK) {
174         OS_ERR("err %"OS_BASETYPE_F"\n", ret);
175         return OS_FAIL;
176     }
177 
178     return OS_OK;
179 }
180