1 /*
2  * Copyright (c) 2016, Wind River Systems, Inc.
3  * Additional Copyright (c) 2018 Espressif Systems (Shanghai) PTE LTD
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #ifndef _BLE_MESH_TIMER_H_
9 #define _BLE_MESH_TIMER_H_
10 
11 #include "mesh_types.h"
12 #include "mesh_slist.h"
13 #include "mesh_atomic.h"
14 
15 #ifdef __cplusplus
16 extern "C" {
17 #endif
18 
19 /* number of nsec per usec */
20 #define NSEC_PER_USEC   1000
21 
22 /* number of microseconds per millisecond */
23 #define USEC_PER_MSEC   1000
24 
25 /* number of milliseconds per second */
26 #define MSEC_PER_SEC    1000
27 
28 /* number of microseconds per second */
29 #define USEC_PER_SEC    ((USEC_PER_MSEC) * (MSEC_PER_SEC))
30 
31 /* number of nanoseconds per second */
32 #define NSEC_PER_SEC    ((NSEC_PER_USEC) * (USEC_PER_MSEC) * (MSEC_PER_SEC))
33 
34 /* timeout is not in use */
35 #define _INACTIVE       (-1)
36 
37 struct k_work;
38 
39 /**
40  * @typedef k_work_handler_t
41  * @brief Work item handler function type.
42  *
43  * A work item's handler function is executed by a workqueue's thread
44  * when the work item is processed by the workqueue.
45  *
46  * @param work Address of the work item.
47  *
48  * @return N/A
49  */
50 typedef void (*k_work_handler_t)(struct k_work *work);
51 
52 struct k_work {
53     void *_reserved;
54     k_work_handler_t handler;
55     int index;
56 };
57 
58 #define _K_WORK_INITIALIZER(work_handler)   \
59 {                                           \
60     ._reserved = NULL,                      \
61     .handler = work_handler,                \
62 }
63 
64 /**
65  * @brief Generate null timeout delay.
66  *
67  * This macro generates a timeout delay that that instructs a kernel API
68  * not to wait if the requested operation cannot be performed immediately.
69  *
70  * @return Timeout delay value.
71  */
72 #define K_NO_WAIT       0
73 
74 /**
75  * @brief Generate timeout delay from milliseconds.
76  *
77  * This macro generates a timeout delay that that instructs a kernel API
78  * to wait up to @a ms milliseconds to perform the requested operation.
79  *
80  * @param ms Duration in milliseconds.
81  *
82  * @return Timeout delay value.
83  */
84 #define K_MSEC(ms)      (ms)
85 
86 /**
87  * @brief Generate timeout delay from seconds.
88  *
89  * This macro generates a timeout delay that that instructs a kernel API
90  * to wait up to @a s seconds to perform the requested operation.
91  *
92  * @param s Duration in seconds.
93  *
94  * @return Timeout delay value.
95  */
96 #define K_SECONDS(s)    K_MSEC((s) * MSEC_PER_SEC)
97 
98 /**
99  * @brief Generate timeout delay from minutes.
100  *
101  * This macro generates a timeout delay that that instructs a kernel API
102  * to wait up to @a m minutes to perform the requested operation.
103  *
104  * @param m Duration in minutes.
105  *
106  * @return Timeout delay value.
107  */
108 #define K_MINUTES(m)    K_SECONDS((m) * 60)
109 
110 /**
111  * @brief Generate timeout delay from hours.
112  *
113  * This macro generates a timeout delay that that instructs a kernel API
114  * to wait up to @a h hours to perform the requested operation.
115  *
116  * @param h Duration in hours.
117  *
118  * @return Timeout delay value.
119  */
120 #define K_HOURS(h)      K_MINUTES((h) * 60)
121 
122 /**
123  * @brief Generate infinite timeout delay.
124  *
125  * This macro generates a timeout delay that that instructs a kernel API
126  * to wait as long as necessary to perform the requested operation.
127  *
128  * @return Timeout delay value.
129  */
130 #define K_FOREVER       (-1)
131 
132 /**
133  * @brief Get system uptime (32-bit version).
134  *
135  * This routine returns the lower 32-bits of the elapsed time since the system
136  * booted, in milliseconds.
137  *
138  * This routine can be more efficient than k_uptime_get(), as it reduces the
139  * need for interrupt locking and 64-bit math. However, the 32-bit result
140  * cannot hold a system uptime time larger than approximately 50 days, so the
141  * caller must handle possible rollovers.
142  *
143  * @return Current uptime.
144  */
145 uint32_t k_uptime_get_32(void);
146 
147 struct k_delayed_work {
148     struct k_work work;
149 };
150 
151 /**
152  * @brief Submit a delayed work item to the system workqueue.
153  *
154  * This routine schedules work item @a work to be processed by the system
155  * workqueue after a delay of @a delay milliseconds. The routine initiates
156  * an asynchronous countdown for the work item and then returns to the caller.
157  * Only when the countdown completes is the work item actually submitted to
158  * the workqueue and becomes pending.
159  *
160  * Submitting a previously submitted delayed work item that is still
161  * counting down cancels the existing submission and restarts the countdown
162  * using the new delay. If the work item is currently pending on the
163  * workqueue's queue because the countdown has completed it is too late to
164  * resubmit the item, and resubmission fails without impacting the work item.
165  * If the work item has already been processed, or is currently being processed,
166  * its work is considered complete and the work item can be resubmitted.
167  *
168  * @warning
169  * Work items submitted to the system workqueue should avoid using handlers
170  * that block or yield since this may prevent the system workqueue from
171  * processing other work items in a timely manner.
172  *
173  * @note Can be called by ISRs.
174  *
175  * @param work Address of delayed work item.
176  * @param delay Delay before submitting the work item (in milliseconds).
177  *
178  * @retval 0 Work item countdown started.
179  * @retval -EINPROGRESS Work item is already pending.
180  * @retval -EINVAL Work item is being processed or has completed its work.
181  * @retval -EADDRINUSE Work item is pending on a different workqueue.
182  */
183 int k_delayed_work_submit(struct k_delayed_work *work, int32_t delay);
184 
185 int k_delayed_work_submit_periodic(struct k_delayed_work *work, int32_t period);
186 
187 /**
188  * @brief Get time remaining before a delayed work gets scheduled.
189  *
190  * This routine computes the (approximate) time remaining before a
191  * delayed work gets executed. If the delayed work is not waiting to be
192  * scheduled, it returns zero.
193  *
194  * @param work     Delayed work item.
195  *
196  * @return Remaining time (in milliseconds).
197  */
198 int32_t k_delayed_work_remaining_get(struct k_delayed_work *work);
199 
200 /**
201  * @brief Submit a work item to the system workqueue.
202  *
203  * This routine submits work item @a work to be processed by the system
204  * workqueue. If the work item is already pending in the workqueue's queue
205  * as a result of an earlier submission, this routine has no effect on the
206  * work item. If the work item has already been processed, or is currently
207  * being processed, its work is considered complete and the work item can be
208  * resubmitted.
209  *
210  * @warning
211  * Work items submitted to the system workqueue should avoid using handlers
212  * that block or yield since this may prevent the system workqueue from
213  * processing other work items in a timely manner.
214  *
215  * @note Can be called by ISRs.
216  *
217  * @param work Address of work item.
218  *
219  * @return N/A
220  */
k_work_submit(struct k_work * work)221 static inline void k_work_submit(struct k_work *work)
222 {
223     if (work && work->handler) {
224         work->handler(work);
225     }
226 }
227 
228 /**
229  * @brief Initialize a work item.
230  *
231  * This routine initializes a workqueue work item, prior to its first use.
232  *
233  * @param work Address of work item.
234  * @param handler Function to invoke each time work item is processed.
235  *
236  * @return N/A
237  */
k_work_init(struct k_work * work,k_work_handler_t handler)238 static inline void k_work_init(struct k_work *work, k_work_handler_t handler)
239 {
240     work->handler = handler;
241 }
242 
243 int k_delayed_work_cancel(struct k_delayed_work *work);
244 
245 int k_delayed_work_free(struct k_delayed_work *work);
246 
247 int k_delayed_work_init(struct k_delayed_work *work, k_work_handler_t handler);
248 
249 /**
250  * @brief Get system uptime.
251  *
252  * This routine returns the elapsed time since the system booted,
253  * in milliseconds.
254  *
255  * @return Current uptime.
256  */
257 int64_t k_uptime_get(void);
258 
259 void bt_mesh_timer_init(void);
260 void bt_mesh_timer_deinit(void);
261 
262 #ifdef __cplusplus
263 }
264 #endif
265 
266 #endif /* _BLE_MESH_TIMER_H_ */
267