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 	uint32_t remainder;
140 	uint16_t lazy;
141 };
142 
143 struct ticker_ext_context {
144 	void *context;
145 	struct ticker_expire_info *other_expire_info;
146 };
147 
148 /** \brief Timer operation complete function type.
149  */
150 typedef void (*ticker_op_func) (uint32_t status, void *op_context);
151 
152 /** \brief Timer operation match callback function type.
153  */
154 typedef bool (*ticker_op_match_func) (uint8_t ticker_id, uint32_t ticks_slot,
155 				      uint32_t ticks_to_expire,
156 				      void *op_context);
157 
158 /** \brief Timer module initialization.
159  *
160  * \param[in]  instance_index  Timer mode instance 0 or 1 (uses RTC0 CMP0 or
161  *				CMP1 respectively).
162  * \param[in]  count_node      Max. no. of ticker nodes to initialize.
163  * \param[in]  node
164  * \param[in]  count_user
165  * \param[in]  user
166  * \param[in]  count_op
167  * \param[in]  user_op
168  */
169 uint8_t ticker_init(uint8_t instance_index, uint8_t count_node, void *node,
170 		     uint8_t count_user, void *user, uint8_t count_op,
171 		     void *user_op, ticker_caller_id_get_cb_t caller_id_get_cb,
172 		     ticker_sched_cb_t sched_cb,
173 		     ticker_trigger_set_cb_t trigger_set_cb);
174 bool ticker_is_initialized(uint8_t instance_index);
175 void ticker_trigger(uint8_t instance_index);
176 void ticker_worker(void *param);
177 void ticker_job(void *param);
178 uint8_t ticker_start(uint8_t instance_index, uint8_t user_id,
179 		      uint8_t ticker_id, uint32_t ticks_anchor,
180 		      uint32_t ticks_first, uint32_t ticks_periodic,
181 		      uint32_t remainder_periodic, uint16_t lazy,
182 		      uint32_t ticks_slot, ticker_timeout_func fp_timeout_func,
183 		      void *context, ticker_op_func fp_op_func,
184 		      void *op_context);
185 uint8_t ticker_start_us(uint8_t instance_index, uint8_t user_id,
186 			uint8_t ticker_id, uint32_t ticks_anchor,
187 			uint32_t ticks_first, uint32_t remainder_first,
188 			uint32_t ticks_periodic, uint32_t remainder_periodic,
189 			uint16_t lazy, uint32_t ticks_slot,
190 			ticker_timeout_func fp_timeout_func, void *context,
191 			ticker_op_func fp_op_func, void *op_context);
192 uint8_t ticker_update(uint8_t instance_index, uint8_t user_id,
193 		       uint8_t ticker_id, uint32_t ticks_drift_plus,
194 		       uint32_t ticks_drift_minus, uint32_t ticks_slot_plus,
195 		       uint32_t ticks_slot_minus, uint16_t lazy, uint8_t force,
196 		       ticker_op_func fp_op_func, void *op_context);
197 uint8_t ticker_yield_abs(uint8_t instance_index, uint8_t user_id,
198 			  uint8_t ticker_id, uint32_t ticks_at_yield,
199 			  ticker_op_func fp_op_func, void *op_context);
200 uint8_t ticker_stop(uint8_t instance_index, uint8_t user_id, uint8_t ticker_id,
201 		     ticker_op_func fp_op_func, void *op_context);
202 uint8_t ticker_stop_abs(uint8_t instance_index, uint8_t user_id,
203 			 uint8_t ticker_id, uint32_t ticks_at_stop,
204 			 ticker_op_func fp_op_func, void *op_context);
205 uint8_t ticker_next_slot_get(uint8_t instance_index, uint8_t user_id,
206 			      uint8_t *ticker_id, uint32_t *ticks_current,
207 			      uint32_t *ticks_to_expire,
208 			      ticker_op_func fp_op_func, void *op_context);
209 uint8_t ticker_next_slot_get_ext(uint8_t instance_index, uint8_t user_id,
210 				  uint8_t *ticker_id, uint32_t *ticks_current,
211 				  uint32_t *ticks_to_expire,
212 				  uint32_t *remainder, uint16_t *lazy,
213 				  ticker_op_match_func fp_op_match_func,
214 				  void *match_op_context,
215 				  ticker_op_func fp_op_func, void *op_context);
216 uint8_t ticker_job_idle_get(uint8_t instance_index, uint8_t user_id,
217 			     ticker_op_func fp_op_func, void *op_context);
218 void ticker_job_sched(uint8_t instance_index, uint8_t user_id);
219 uint32_t ticker_ticks_now_get(void);
220 uint32_t ticker_ticks_diff_get(uint32_t ticks_now, uint32_t ticks_old);
221 
222 #if !defined(CONFIG_BT_TICKER_LOW_LAT) && \
223 	!defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
224 uint8_t ticker_priority_set(uint8_t instance_index, uint8_t user_id,
225 			     uint8_t ticker_id, int8_t priority,
226 			     ticker_op_func fp_op_func, void *op_context);
227 #endif /* !CONFIG_BT_TICKER_LOW_LAT && !CONFIG_BT_TICKER_SLOT_AGNOSTIC */
228 
229 #if defined(CONFIG_BT_TICKER_EXT)
230 struct ticker_ext {
231 #if !defined(CONFIG_BT_TICKER_SLOT_AGNOSTIC)
232 	uint32_t ticks_slot_window;    /* Window in which the slot
233 					* reservation may be re-scheduled
234 					* to avoid collision
235 					*/
236 	uint32_t ticks_drift;          /* Actual drift since last expiry,
237 					* includes any ticker update interface
238 					* made changes plus drift due to
239 					* reschedule when not
240 					* is_jitter_in_window, otherwise is only
241 					* the value of drift due to reschedule
242 					*/
243 	uint8_t reschedule_state:3;    /* State of re-scheduling of the
244 					* node. See defines
245 					* TICKER_RESCHEDULE_STATE_XXX
246 					*/
247 	uint8_t is_drift_in_window:1;  /* Drift in slot window, to be placed
248 					* after an overlapping ticker
249 					*/
250 #endif /* CONFIG_BT_TICKER_SLOT_AGNOSTIC */
251 
252 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
253 	uint8_t expire_info_id; /* Other ticker ID for which
254 				 * the ext_timeout_func should include expire
255 				 * info for
256 				 * Set to TICKER_NULL if not used
257 				 */
258 	ticker_timeout_func ext_timeout_func;
259 	void *other_expire_info;
260 #endif /* CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
261 };
262 
263 uint8_t ticker_start_ext(uint8_t instance_index, uint8_t user_id,
264 			  uint8_t ticker_id, uint32_t ticks_anchor,
265 			  uint32_t ticks_first, uint32_t ticks_periodic,
266 			  uint32_t remainder_periodic, uint16_t lazy,
267 			  uint32_t ticks_slot,
268 			  ticker_timeout_func fp_timeout_func, void *context,
269 			  ticker_op_func fp_op_func, void *op_context,
270 			  struct ticker_ext *ext_data);
271 
272 #if defined(CONFIG_BT_TICKER_EXT_EXPIRE_INFO)
273 uint8_t ticker_update_ext(uint8_t instance_index, uint8_t user_id,
274 			   uint8_t ticker_id, uint32_t ticks_drift_plus,
275 			   uint32_t ticks_drift_minus,
276 			   uint32_t ticks_slot_plus, uint32_t ticks_slot_minus,
277 			   uint16_t lazy, uint8_t force,
278 			   ticker_op_func fp_op_func, void *op_context,
279 			   uint8_t must_expire, uint8_t expire_info_id);
280 #else /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
281 uint8_t ticker_update_ext(uint8_t instance_index, uint8_t user_id,
282 			   uint8_t ticker_id, uint32_t ticks_drift_plus,
283 			   uint32_t ticks_drift_minus,
284 			   uint32_t ticks_slot_plus, uint32_t ticks_slot_minus,
285 			   uint16_t lazy, uint8_t force,
286 			   ticker_op_func fp_op_func, void *op_context,
287 			   uint8_t must_expire);
288 #endif /* !CONFIG_BT_TICKER_EXT_EXPIRE_INFO */
289 
290 #endif /* CONFIG_BT_TICKER_EXT */
291