1 // Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 // The LL layer for Timer Group register operations.
16 // Note that most of the register operations in this layer are non-atomic operations.
17
18 #pragma once
19
20 #ifdef __cplusplus
21 extern "C" {
22 #endif
23
24 #include <stdlib.h>
25 #include "hal/timer_types.h"
26 #include "soc/timer_periph.h"
27
28 _Static_assert(TIMER_INTR_T0 == TIMG_T0_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t");
29 _Static_assert(TIMER_INTR_T1 == TIMG_T1_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t");
30 _Static_assert(TIMER_INTR_WDT == TIMG_WDT_INT_CLR, "Add mapping to LL interrupt handling, since it's no longer naturally compatible with the timer_intr_t");
31
32 // Get timer group instance with giving group number
33 #define TIMER_LL_GET_HW(num) ((num == 0) ? (&TIMERG0) : (&TIMERG1))
34
35 /**
36 * @brief Set timer clock prescale value
37 *
38 * @param hw Beginning address of the peripheral registers.
39 * @param timer_num The timer number
40 * @param divider Prescale value (0 and 1 are not valid)
41 *
42 * @return None
43 */
timer_ll_set_divider(timg_dev_t * hw,timer_idx_t timer_num,uint32_t divider)44 static inline void timer_ll_set_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t divider)
45 {
46 // refer to TRM 18.2.1
47 if (divider == 65536) {
48 divider = 0;
49 } else if (divider == 1) {
50 divider = 2;
51 }
52 int timer_en = hw->hw_timer[timer_num].config.enable;
53 hw->hw_timer[timer_num].config.enable = 0;
54 hw->hw_timer[timer_num].config.divider = divider;
55 hw->hw_timer[timer_num].config.enable = timer_en;
56 }
57
58 /**
59 * @brief Get timer clock prescale value
60 *
61 * @param hw Beginning address of the peripheral registers.
62 * @param timer_num The timer number
63 * @param divider Pointer to accept the prescale value
64 *
65 * @return None
66 */
timer_ll_get_divider(timg_dev_t * hw,timer_idx_t timer_num,uint32_t * divider)67 static inline void timer_ll_get_divider(timg_dev_t *hw, timer_idx_t timer_num, uint32_t *divider)
68 {
69 uint32_t d = hw->hw_timer[timer_num].config.divider;
70 if (d == 0) {
71 d = 65536;
72 } else if (d == 1) {
73 d = 2;
74 }
75 *divider = d;
76 }
77
78 /**
79 * @brief Load counter value into time-base counter
80 *
81 * @param hw Beginning address of the peripheral registers.
82 * @param timer_num The timer number
83 * @param load_val Counter value
84 *
85 * @return None
86 */
timer_ll_set_counter_value(timg_dev_t * hw,timer_idx_t timer_num,uint64_t load_val)87 static inline void timer_ll_set_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t load_val)
88 {
89 hw->hw_timer[timer_num].load_high = (uint32_t) (load_val >> 32);
90 hw->hw_timer[timer_num].load_low = (uint32_t) load_val;
91 hw->hw_timer[timer_num].reload = 1;
92 }
93
94 /**
95 * @brief Get counter value from time-base counter
96 *
97 * @param hw Beginning address of the peripheral registers.
98 * @param timer_num The timer number
99 * @param timer_val Pointer to accept the counter value
100 *
101 * @return None
102 */
timer_ll_get_counter_value(timg_dev_t * hw,timer_idx_t timer_num,uint64_t * timer_val)103 FORCE_INLINE_ATTR void timer_ll_get_counter_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *timer_val)
104 {
105 hw->hw_timer[timer_num].update = 1;
106 while (hw->hw_timer[timer_num].update) {}
107 *timer_val = ((uint64_t) hw->hw_timer[timer_num].cnt_high << 32) | (hw->hw_timer[timer_num].cnt_low);
108 }
109
110 /**
111 * @brief Set counter mode, include increment mode and decrement mode.
112 *
113 * @param hw Beginning address of the peripheral registers.
114 * @param timer_num The timer number
115 * @param increase_en True to increment mode, fasle to decrement mode
116 *
117 * @return None
118 */
timer_ll_set_counter_increase(timg_dev_t * hw,timer_idx_t timer_num,bool increase_en)119 static inline void timer_ll_set_counter_increase(timg_dev_t *hw, timer_idx_t timer_num, bool increase_en)
120 {
121 hw->hw_timer[timer_num].config.increase = increase_en;
122 }
123
124 /**
125 * @brief Get counter mode, include increment mode and decrement mode.
126 *
127 * @param hw Beginning address of the peripheral registers.
128 * @param timer_num The timer number
129 *
130 * @return
131 * - true Increment mode
132 * - false Decrement mode
133 */
timer_ll_get_counter_increase(timg_dev_t * hw,timer_idx_t timer_num)134 static inline bool timer_ll_get_counter_increase(timg_dev_t *hw, timer_idx_t timer_num)
135 {
136 return hw->hw_timer[timer_num].config.increase;
137 }
138
139 /**
140 * @brief Set counter status, enable or disable counter.
141 *
142 * @param hw Beginning address of the peripheral registers.
143 * @param timer_num The timer number
144 * @param counter_en True to enable counter, false to disable counter
145 *
146 * @return None
147 */
timer_ll_set_counter_enable(timg_dev_t * hw,timer_idx_t timer_num,bool counter_en)148 FORCE_INLINE_ATTR void timer_ll_set_counter_enable(timg_dev_t *hw, timer_idx_t timer_num, bool counter_en)
149 {
150 hw->hw_timer[timer_num].config.enable = counter_en;
151 }
152
153 /**
154 * @brief Get counter status.
155 *
156 * @param hw Beginning address of the peripheral registers.
157 * @param timer_num The timer number
158 *
159 * @return
160 * - true Enable counter
161 * - false Disable conuter
162 */
timer_ll_get_counter_enable(timg_dev_t * hw,timer_idx_t timer_num)163 static inline bool timer_ll_get_counter_enable(timg_dev_t *hw, timer_idx_t timer_num)
164 {
165 return hw->hw_timer[timer_num].config.enable;
166 }
167
168 /**
169 * @brief Set auto reload mode.
170 *
171 * @param hw Beginning address of the peripheral registers.
172 * @param timer_num The timer number
173 * @param auto_reload_en True to enable auto reload mode, flase to disable auto reload mode
174 *
175 * @return None
176 */
timer_ll_set_auto_reload(timg_dev_t * hw,timer_idx_t timer_num,bool auto_reload_en)177 static inline void timer_ll_set_auto_reload(timg_dev_t *hw, timer_idx_t timer_num, bool auto_reload_en)
178 {
179 hw->hw_timer[timer_num].config.autoreload = auto_reload_en;
180 }
181
182 /**
183 * @brief Get auto reload mode.
184 *
185 * @param hw Beginning address of the peripheral registers.
186 * @param timer_num The timer number
187 *
188 * @return
189 * - true Enable auto reload mode
190 * - false Disable auto reload mode
191 */
timer_ll_get_auto_reload(timg_dev_t * hw,timer_idx_t timer_num)192 FORCE_INLINE_ATTR bool timer_ll_get_auto_reload(timg_dev_t *hw, timer_idx_t timer_num)
193 {
194 return hw->hw_timer[timer_num].config.autoreload;
195 }
196
197 /**
198 * @brief Set the counter value to trigger the alarm.
199 *
200 * @param hw Beginning address of the peripheral registers.
201 * @param timer_num The timer number
202 * @param alarm_value Counter value to trigger the alarm
203 *
204 * @return None
205 */
timer_ll_set_alarm_value(timg_dev_t * hw,timer_idx_t timer_num,uint64_t alarm_value)206 FORCE_INLINE_ATTR void timer_ll_set_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t alarm_value)
207 {
208 hw->hw_timer[timer_num].alarm_high = (uint32_t) (alarm_value >> 32);
209 hw->hw_timer[timer_num].alarm_low = (uint32_t) alarm_value;
210 }
211
212 /**
213 * @brief Get the counter value to trigger the alarm.
214 *
215 * @param hw Beginning address of the peripheral registers.
216 * @param timer_num The timer number
217 * @param alarm_value Pointer to accept the counter value to trigger the alarm
218 *
219 * @return None
220 */
timer_ll_get_alarm_value(timg_dev_t * hw,timer_idx_t timer_num,uint64_t * alarm_value)221 static inline void timer_ll_get_alarm_value(timg_dev_t *hw, timer_idx_t timer_num, uint64_t *alarm_value)
222 {
223 *alarm_value = ((uint64_t) hw->hw_timer[timer_num].alarm_high << 32) | (hw->hw_timer[timer_num].alarm_low);
224 }
225
226 /**
227 * @brief Set the alarm status, enable or disable the alarm.
228 *
229 * @param hw Beginning address of the peripheral registers.
230 * @param timer_num The timer number
231 * @param alarm_en True to enable alarm, false to disable alarm
232 *
233 * @return None
234 */
timer_ll_set_alarm_enable(timg_dev_t * hw,timer_idx_t timer_num,bool alarm_en)235 FORCE_INLINE_ATTR void timer_ll_set_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num, bool alarm_en)
236 {
237 hw->hw_timer[timer_num].config.alarm_en = alarm_en;
238 }
239
240 /**
241 * @brief Get the alarm status.
242 *
243 * @param hw Beginning address of the peripheral registers.
244 * @param timer_num The timer number
245 *
246 * @return
247 * - true Enable alarm
248 * - false Disable alarm
249 */
timer_ll_get_alarm_enable(timg_dev_t * hw,timer_idx_t timer_num)250 static inline bool timer_ll_get_alarm_enable(timg_dev_t *hw, timer_idx_t timer_num)
251 {
252 return hw->hw_timer[timer_num].config.alarm_en;
253 }
254
255 /**
256 * @brief Enable timer interrupt.
257 *
258 * @param hw Beginning address of the peripheral registers.
259 * @param timer_num The timer number
260 *
261 * @return None
262 */
timer_ll_intr_enable(timg_dev_t * hw,timer_idx_t timer_num)263 FORCE_INLINE_ATTR void timer_ll_intr_enable(timg_dev_t *hw, timer_idx_t timer_num)
264 {
265 hw->int_ena.val |= BIT(timer_num);
266 hw->hw_timer[timer_num].config.level_int_en = 1;
267 }
268
269 /**
270 * @brief Disable timer interrupt.
271 *
272 * @param hw Beginning address of the peripheral registers.
273 * @param timer_num The timer number
274 *
275 * @return None
276 */
timer_ll_intr_disable(timg_dev_t * hw,timer_idx_t timer_num)277 FORCE_INLINE_ATTR void timer_ll_intr_disable(timg_dev_t *hw, timer_idx_t timer_num)
278 {
279 hw->int_ena.val &= (~BIT(timer_num));
280 hw->hw_timer[timer_num].config.level_int_en = 0;
281 }
282
283 /**
284 * @brief Disable timer interrupt.
285 *
286 * @param hw Beginning address of the peripheral registers.
287 * @param timer_num The timer number
288 *
289 * @return None
290 */
timer_ll_clear_intr_status(timg_dev_t * hw,timer_idx_t timer_num)291 FORCE_INLINE_ATTR void timer_ll_clear_intr_status(timg_dev_t *hw, timer_idx_t timer_num)
292 {
293 hw->int_clr_timers.val |= BIT(timer_num);
294 }
295
296 /**
297 * @brief Get interrupt status.
298 *
299 * @param hw Beginning address of the peripheral registers.
300 * @param intr_status Interrupt status
301 *
302 * @return None
303 */
timer_ll_get_intr_status(timg_dev_t * hw,uint32_t * intr_status)304 FORCE_INLINE_ATTR void timer_ll_get_intr_status(timg_dev_t *hw, uint32_t *intr_status)
305 {
306 *intr_status = hw->int_st_timers.val & 0x03;
307 }
308
309 /**
310 * @brief Get interrupt raw status.
311 *
312 * @param group_num Timer group number, 0 for TIMERG0 or 1 for TIMERG1
313 * @param intr_raw_status Interrupt raw status
314 *
315 * @return None
316 */
timer_ll_get_intr_raw_status(timer_group_t group_num,uint32_t * intr_raw_status)317 FORCE_INLINE_ATTR void timer_ll_get_intr_raw_status(timer_group_t group_num, uint32_t *intr_raw_status)
318 {
319 timg_dev_t *hw = TIMER_LL_GET_HW(group_num);
320 *intr_raw_status = hw->int_raw.val & 0x03;
321 }
322
323 /**
324 * @brief Set the level interrupt status, enable or disable the level interrupt.
325 *
326 * @param hw Beginning address of the peripheral registers.
327 * @param timer_num The timer number
328 * @param level_int_en True to enable level interrupt, false to disable level interrupt
329 *
330 * @return None
331 */
timer_ll_set_level_int_enable(timg_dev_t * hw,timer_idx_t timer_num,bool level_int_en)332 static inline void timer_ll_set_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool level_int_en)
333 {
334 hw->hw_timer[timer_num].config.level_int_en = level_int_en;
335 }
336
337 /**
338 * @brief Get the level interrupt status.
339 *
340 * @param hw Beginning address of the peripheral registers.
341 * @param timer_num The timer number
342 *
343 * @return
344 * - true Enable level interrupt
345 * - false Disable level interrupt
346 */
timer_ll_get_level_int_enable(timg_dev_t * hw,timer_idx_t timer_num)347 static inline bool timer_ll_get_level_int_enable(timg_dev_t *hw, timer_idx_t timer_num)
348 {
349 return hw->hw_timer[timer_num].config.level_int_en;
350 }
351
352 /**
353 * @brief Set the edge interrupt status, enable or disable the edge interrupt.
354 *
355 * @param hw Beginning address of the peripheral registers.
356 * @param timer_num The timer number
357 * @param edge_int_en True to enable edge interrupt, false to disable edge interrupt
358 *
359 * @return None
360 */
timer_ll_set_edge_int_enable(timg_dev_t * hw,timer_idx_t timer_num,bool edge_int_en)361 static inline void timer_ll_set_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num, bool edge_int_en)
362 {
363 hw->hw_timer[timer_num].config.edge_int_en = edge_int_en;
364 }
365
366 /**
367 * @brief Get the edge interrupt status.
368 *
369 * @param hw Beginning address of the peripheral registers.
370 * @param timer_num The timer number
371 *
372 * @return
373 * - true Enable edge interrupt
374 * - false Disable edge interrupt
375 */
timer_ll_get_edge_int_enable(timg_dev_t * hw,timer_idx_t timer_num)376 static inline bool timer_ll_get_edge_int_enable(timg_dev_t *hw, timer_idx_t timer_num)
377 {
378 return hw->hw_timer[timer_num].config.edge_int_en;
379 }
380
381 /**
382 * @brief Get interrupt status register address.
383 *
384 * @param hw Beginning address of the peripheral registers.
385 *
386 * @return Interrupt status register address
387 */
timer_ll_get_intr_status_reg(timg_dev_t * hw)388 static inline uint32_t timer_ll_get_intr_status_reg(timg_dev_t *hw)
389 {
390 return (uint32_t) & (hw->int_st_timers.val);
391 }
392
timer_ll_get_intr_mask_bit(timg_dev_t * hw,timer_idx_t timer_num)393 static inline uint32_t timer_ll_get_intr_mask_bit(timg_dev_t *hw, timer_idx_t timer_num)
394 {
395 return (1U << timer_num);
396 }
397
398 #ifdef __cplusplus
399 }
400 #endif
401