1 /*
2  * Copyright (c) 2016-2018 Nordic Semiconductor ASA
3  * Copyright (c) 2016 Vinayak Kariappa Chettimada
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 /** \defgroup Timer API return codes.
9  *
10  * @{
11  */
12 #define TICKER_STATUS_SUCCESS 0 /**< Success. */
13 #define TICKER_STATUS_FAILURE 1 /**< Failure. */
14 #define TICKER_STATUS_BUSY    2 /**< Busy, requested feature will
15 				  * complete later in time as job is
16 				  * disabled or at lower execution
17 				  * priority than the caller.
18 				  */
19 /**
20  * @}
21  */
22 
23 /** \defgroup Timer API common defaults parameter values.
24  *
25  * @{
26  */
27 #define TICKER_NULL             ((uint8_t)((uint8_t)0 - 1))
28 #define TICKER_NULL_REMAINDER   0
29 #define TICKER_NULL_PERIOD      0
30 #define TICKER_NULL_SLOT        0
31 #define TICKER_NULL_LAZY        0
32 #define TICKER_NULL_MUST_EXPIRE 0
33 
34 /**
35  * @}
36  */
37 
38 /** \brief Timer node type size.
39  */
40 #if defined(CONFIG_BT_TICKER_EXT)
41 #if defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
42 #define TICKER_NODE_T_SIZE      40
43 #elif defined(CONFIG_BT_TICKER_LOW_LAT)
44 #define TICKER_NODE_T_SIZE      44
45 #else
46 #define TICKER_NODE_T_SIZE      48
47 #endif /* CONFIG_BT_TICKER_SLOT_AGNOSTIC */
48 #else /* CONFIG_BT_TICKER_EXT */
49 #if defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
50 #define TICKER_NODE_T_SIZE      36
51 #elif defined(CONFIG_BT_TICKER_LOW_LAT)
52 #define TICKER_NODE_T_SIZE      40
53 #else
54 #define TICKER_NODE_T_SIZE      44
55 #endif /* CONFIG_BT_TICKER_SLOT_AGNOSTIC */
56 #endif /* CONFIG_BT_TICKER_EXT */
57 
58 /** \brief Timer user type size.
59  */
60 #define TICKER_USER_T_SIZE      8
61 
62 /** \brief Timer user operation type size.
63  */
64 #if defined(CONFIG_BT_TICKER_EXT)
65 #if defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
66 #if defined(CONFIG_BT_TICKER_REMAINDER_SUPPORT)
67 #define TICKER_USER_OP_T_SIZE   44
68 #else /* !CONFIG_BT_TICKER_REMAINDER_SUPPORT */
69 #define TICKER_USER_OP_T_SIZE   40
70 #endif /* !CONFIG_BT_TICKER_REMAINDER_SUPPORT */
71 #else /* !CONFIG_BT_TICKER_SLOT_AGNOSTIC */
72 #if defined(CONFIG_BT_TICKER_REMAINDER_SUPPORT)
73 #if defined(CONFIG_BT_TICKER_START_REMAINDER)
74 #define TICKER_USER_OP_T_SIZE   52
75 #else /* !CONFIG_BT_TICKER_START_REMAINDER */
76 #define TICKER_USER_OP_T_SIZE   48
77 #endif /* !CONFIG_BT_TICKER_START_REMAINDER */
78 #else /* !CONFIG_BT_TICKER_REMAINDER_SUPPORT */
79 #define TICKER_USER_OP_T_SIZE   44
80 #endif /* !CONFIG_BT_TICKER_REMAINDER_SUPPORT */
81 #endif /* !CONFIG_BT_TICKER_SLOT_AGNOSTIC */
82 #else /* !CONFIG_BT_TICKER_EXT */
83 #if defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
84 #if defined(CONFIG_BT_TICKER_REMAINDER_SUPPORT)
85 #define TICKER_USER_OP_T_SIZE   40
86 #else /* !CONFIG_BT_TICKER_REMAINDER_SUPPORT */
87 #define TICKER_USER_OP_T_SIZE   36
88 #endif /* !CONFIG_BT_TICKER_REMAINDER_SUPPORT */
89 #else /* !CONFIG_BT_TICKER_SLOT_AGNOSTIC */
90 #if defined(CONFIG_BT_TICKER_REMAINDER_SUPPORT)
91 #if defined(CONFIG_BT_TICKER_START_REMAINDER)
92 #define TICKER_USER_OP_T_SIZE   48
93 #else /* !CONFIG_BT_TICKER_START_REMAINDER */
94 #define TICKER_USER_OP_T_SIZE   44
95 #endif /* !CONFIG_BT_TICKER_START_REMAINDER */
96 #else /* !CONFIG_BT_TICKER_REMAINDER_SUPPORT */
97 #define TICKER_USER_OP_T_SIZE   40
98 #endif /* !CONFIG_BT_TICKER_REMAINDER_SUPPORT */
99 #endif /* !CONFIG_BT_TICKER_SLOT_AGNOSTIC */
100 #endif /* !CONFIG_BT_TICKER_EXT */
101 
102 #define TICKER_CALL_ID_NONE     0
103 #define TICKER_CALL_ID_ISR      1
104 #define TICKER_CALL_ID_TRIGGER  2
105 #define TICKER_CALL_ID_WORKER   3
106 #define TICKER_CALL_ID_JOB      4
107 #define TICKER_CALL_ID_PROGRAM  5
108 
109 /* Use to ensure callback is invoked in all intervals, even when latencies
110  * occur.
111  */
112 #define TICKER_LAZY_MUST_EXPIRE      0xFFFF
113 
114 /* Use in ticker_start to set lazy to 0 and do not change the must_expire
115  * state.
116  */
117 #define TICKER_LAZY_MUST_EXPIRE_KEEP 0xFFFE
118 
119 /* Set this priority to ensure ticker node is always scheduled. Only one
120  * ticker node can have priority TICKER_PRIORITY_CRITICAL at a time
121  */
122 #define TICKER_PRIORITY_CRITICAL -128
123 
124 typedef uint8_t (*ticker_caller_id_get_cb_t)(uint8_t user_id);
125 typedef void (*ticker_sched_cb_t)(uint8_t caller_id, uint8_t callee_id,
126 				  uint8_t chain, void *instance);
127 typedef void (*ticker_trigger_set_cb_t)(uint32_t value);
128 
129 /** \brief Timer timeout function type.
130  */
131 typedef void (*ticker_timeout_func) (uint32_t ticks_at_expire,
132 				     uint32_t ticks_drift, uint32_t remainder,
133 				     uint16_t lazy, uint8_t force,
134 				     void *context);
135 
136 
137 struct ticker_expire_info {
138 	uint32_t ticks_to_expire;
139 #if defined(CONFIG_BT_TICKER_REMAINDER_SUPPORT)
140 	uint32_t remainder;
141 #endif /* CONFIG_BT_TICKER_REMAINDER_SUPPORT */
142 	uint16_t lazy;
143 };
144 
145 struct ticker_ext_context {
146 	void *context;
147 	struct ticker_expire_info *other_expire_info;
148 };
149 
150 /** \brief Timer operation complete function type.
151  */
152 typedef void (*ticker_op_func) (uint32_t status, void *op_context);
153 
154 /** \brief Timer operation match callback function type.
155  */
156 typedef bool (*ticker_op_match_func) (uint8_t ticker_id, uint32_t ticks_slot,
157 				      uint32_t ticks_to_expire,
158 				      void *op_context);
159 
160 /** \brief Timer module initialization.
161  *
162  * \param[in]  instance_index  Timer mode instance 0 or 1 (uses RTC0 CMP0 or
163  *				CMP1 respectively).
164  * \param[in]  count_node      Max. no. of ticker nodes to initialize.
165  * \param[in]  node
166  * \param[in]  count_user
167  * \param[in]  user
168  * \param[in]  count_op
169  * \param[in]  user_op
170  */
171 uint8_t ticker_init(uint8_t instance_index, uint8_t count_node, void *node,
172 		     uint8_t count_user, void *user, uint8_t count_op,
173 		     void *user_op, ticker_caller_id_get_cb_t caller_id_get_cb,
174 		     ticker_sched_cb_t sched_cb,
175 		     ticker_trigger_set_cb_t trigger_set_cb);
176 bool ticker_is_initialized(uint8_t instance_index);
177 void ticker_trigger(uint8_t instance_index);
178 void ticker_worker(void *param);
179 void ticker_job(void *param);
180 uint8_t ticker_start(uint8_t instance_index, uint8_t user_id,
181 		      uint8_t ticker_id, uint32_t ticks_anchor,
182 		      uint32_t ticks_first, uint32_t ticks_periodic,
183 		      uint32_t remainder_periodic, uint16_t lazy,
184 		      uint32_t ticks_slot, ticker_timeout_func fp_timeout_func,
185 		      void *context, ticker_op_func fp_op_func,
186 		      void *op_context);
187 uint8_t ticker_start_us(uint8_t instance_index, uint8_t user_id,
188 			uint8_t ticker_id, uint32_t ticks_anchor,
189 			uint32_t ticks_first, uint32_t remainder_first,
190 			uint32_t ticks_periodic, uint32_t remainder_periodic,
191 			uint16_t lazy, uint32_t ticks_slot,
192 			ticker_timeout_func fp_timeout_func, void *context,
193 			ticker_op_func fp_op_func, void *op_context);
194 uint8_t ticker_update(uint8_t instance_index, uint8_t user_id,
195 		       uint8_t ticker_id, uint32_t ticks_drift_plus,
196 		       uint32_t ticks_drift_minus, uint32_t ticks_slot_plus,
197 		       uint32_t ticks_slot_minus, uint16_t lazy, uint8_t force,
198 		       ticker_op_func fp_op_func, void *op_context);
199 uint8_t ticker_yield_abs(uint8_t instance_index, uint8_t user_id,
200 			  uint8_t ticker_id, uint32_t ticks_at_yield,
201 			  ticker_op_func fp_op_func, void *op_context);
202 uint8_t ticker_stop(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
203 		     ticker_op_func fp_op_func, void *op_context);
204 uint8_t ticker_stop_abs(uint8_t instance_index, uint8_t user_id,
205 			 uint8_t ticker_id, uint32_t ticks_at_stop,
206 			 ticker_op_func fp_op_func, void *op_context);
207 uint8_t ticker_next_slot_get(uint8_t instance_index, uint8_t user_id,
208 			      uint8_t *ticker_id, uint32_t *ticks_current,
209 			      uint32_t *ticks_to_expire,
210 			      ticker_op_func fp_op_func, void *op_context);
211 uint8_t ticker_next_slot_get_ext(uint8_t instance_index, uint8_t user_id,
212 				  uint8_t *ticker_id, uint32_t *ticks_current,
213 				  uint32_t *ticks_to_expire,
214 				  uint32_t *remainder, uint16_t *lazy,
215 				  ticker_op_match_func fp_op_match_func,
216 				  void *match_op_context,
217 				  ticker_op_func fp_op_func, void *op_context);
218 uint8_t ticker_job_idle_get(uint8_t instance_index, uint8_t user_id,
219 			     ticker_op_func fp_op_func, void *op_context);
220 void ticker_job_sched(uint8_t instance_index, uint8_t user_id);
221 uint32_t ticker_ticks_now_get(void);
222 uint32_t ticker_ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old);
223 
224 #if !defined(CONFIG_BT_TICKER_LOW_LAT) && \
225 	!defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
226 uint8_t ticker_priority_set(uint8_t instance_index, uint8_t user_id,
227 			     uint8_t ticker_id, int8_t priority,
228 			     ticker_op_func fp_op_func, void *op_context);
229 #endif /* !CONFIG_BT_TICKER_LOW_LAT && !CONFIG_BT_TICKER_SLOT_AGNOSTIC */
230 
231 #if defined(CONFIG_BT_TICKER_EXT)
232 struct ticker_ext {
233 #if !defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
234 	uint32_t ticks_slot_window;    /* Window in which the slot
235 					* reservation may be re-scheduled
236 					* to avoid collision
237 					*/
238 	uint32_t ticks_drift;          /* Actual drift since last expiry,
239 					* includes any ticker update interface
240 					* made changes plus drift due to
241 					* reschedule when not
242 					* is_jitter_in_window, otherwise is only
243 					* the value of drift due to reschedule
244 					*/
245 	uint8_t reschedule_state:3;    /* State of re-scheduling of the
246 					* node. See defines
247 					* TICKER_RESCHEDULE_STATE_XXX
248 					*/
249 	uint8_t is_drift_in_window:1;  /* Drift in slot window, to be placed
250 					* after an overlapping ticker
251 					*/
252 #endif /* CONFIG_BT_TICKER_SLOT_AGNOSTIC */
253 
254 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
255 	uint8_t expire_info_id; /* Other ticker ID for which
256 				 * the ext_timeout_func should include expire
257 				 * info for
258 				 * Set to TICKER_NULL if not used
259 				 */
260 	ticker_timeout_func ext_timeout_func;
261 	void *other_expire_info;
262 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
263 };
264 
265 uint8_t ticker_start_ext(uint8_t instance_index, uint8_t user_id,
266 			  uint8_t ticker_id, uint32_t ticks_anchor,
267 			  uint32_t ticks_first, uint32_t ticks_periodic,
268 			  uint32_t remainder_periodic, uint16_t lazy,
269 			  uint32_t ticks_slot,
270 			  ticker_timeout_func fp_timeout_func, void *context,
271 			  ticker_op_func fp_op_func, void *op_context,
272 			  struct ticker_ext *ext_data);
273 
274 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
275 uint8_t ticker_update_ext(uint8_t instance_index, uint8_t user_id,
276 			   uint8_t ticker_id, uint32_t ticks_drift_plus,
277 			   uint32_t ticks_drift_minus,
278 			   uint32_t ticks_slot_plus, uint32_t ticks_slot_minus,
279 			   uint16_t lazy, uint8_t force,
280 			   ticker_op_func fp_op_func, void *op_context,
281 			   uint8_t must_expire, uint8_t expire_info_id);
282 #else /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
283 uint8_t ticker_update_ext(uint8_t instance_index, uint8_t user_id,
284 			   uint8_t ticker_id, uint32_t ticks_drift_plus,
285 			   uint32_t ticks_drift_minus,
286 			   uint32_t ticks_slot_plus, uint32_t ticks_slot_minus,
287 			   uint16_t lazy, uint8_t force,
288 			   ticker_op_func fp_op_func, void *op_context,
289 			   uint8_t must_expire);
290 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
291 
292 #endif /* CONFIG_BT_TICKER_EXT */
293