• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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