1 /*
2 * Copyright (c) 2006-2023, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2023-11-15 BetMul first version
9 */
10
11 #include "drv_hwtimer.h"
12
13 #include <rtthread.h>
14 #include <rtdevice.h>
15 #include "driver/gptimer.h"
16 #include "sdkconfig.h"
17
18 #ifdef RT_USING_HWTIMER
19
20 /**
21 * handle interrupt for hwtimer.
22 */
mcu_hwtimer_intr_handler(gptimer_handle_t gptimer,const gptimer_alarm_event_data_t * edata,void * user_ctx)23 static bool mcu_hwtimer_intr_handler(gptimer_handle_t gptimer, const gptimer_alarm_event_data_t *edata, void *user_ctx)
24 {
25 rt_interrupt_enter();
26
27 rt_hwtimer_t *hwtimer = (rt_hwtimer_t *)user_ctx;
28 rt_device_hwtimer_isr(hwtimer);
29
30 rt_interrupt_leave();
31
32 return 0;
33 }
34
35 /**
36 * init the hwtimer
37 */
mcu_hwtimer_init(rt_hwtimer_t * timer,rt_uint32_t state)38 static void mcu_hwtimer_init(rt_hwtimer_t *timer, rt_uint32_t state)
39 {
40 gptimer_handle_t gptimer = (gptimer_handle_t)timer->parent.user_data;
41
42 // let the gptimer into enable status
43 ESP_ERROR_CHECK(gptimer_enable(gptimer));
44 }
45
46 /**
47 * start the hwtimer, change status into running
48 */
mcu_hwtimer_start(rt_hwtimer_t * timer,rt_uint32_t cnt,rt_hwtimer_mode_t mode)49 static rt_err_t mcu_hwtimer_start(rt_hwtimer_t *timer, rt_uint32_t cnt, rt_hwtimer_mode_t mode)
50 {
51 gptimer_handle_t gptimer = (gptimer_handle_t)timer->parent.user_data;
52 gptimer_alarm_config_t alarm_config = {
53 .alarm_count = cnt,
54 };
55 if (mode == HWTIMER_MODE_ONESHOT)
56 {
57
58 }
59 else
60 {
61 alarm_config.reload_count = 0;
62 alarm_config.flags.auto_reload_on_alarm = true;
63 }
64 ESP_ERROR_CHECK(gptimer_set_alarm_action(gptimer, &alarm_config));
65 ESP_ERROR_CHECK(gptimer_start(gptimer));
66
67 return RT_EOK;
68 }
69
70 /**
71 * stop the hwtimer, change the status from running into enable
72 */
mcu_hwtimer_stop(rt_hwtimer_t * timer)73 static void mcu_hwtimer_stop(rt_hwtimer_t *timer)
74 {
75 gptimer_handle_t gptimer = (gptimer_handle_t)timer->parent.user_data;
76
77 ESP_ERROR_CHECK(gptimer_stop(gptimer));
78 }
79
80 /**
81 * get count
82 */
mcu_hwtimer_count_get(rt_hwtimer_t * timer)83 static rt_uint32_t mcu_hwtimer_count_get(rt_hwtimer_t *timer)
84 {
85 gptimer_handle_t gptimer = (gptimer_handle_t)timer->parent.user_data;
86 // get count number
87 uint64_t value;
88 ESP_ERROR_CHECK(gptimer_get_raw_count(gptimer, &value));
89 return (rt_uint32_t)value;
90 }
91
92 /**
93 * control the hwtimer
94 */
mcu_hwtimer_control(rt_hwtimer_t * timer,rt_uint32_t cmd,void * args)95 static rt_err_t mcu_hwtimer_control(rt_hwtimer_t *timer, rt_uint32_t cmd, void *args)
96 {
97
98 rt_err_t err = RT_EOK;
99
100 switch (cmd)
101 {
102 case HWTIMER_CTRL_FREQ_SET:
103 err = -RT_ERROR;
104 break;
105
106 case HWTIMER_CTRL_INFO_GET:
107 err = -RT_ERROR;
108 break;
109
110 case HWTIMER_CTRL_MODE_SET:
111 timer->mode = *(rt_uint32_t *)args;
112 break;
113
114 case HWTIMER_CTRL_STOP:
115 mcu_hwtimer_stop(timer);
116 break;
117 }
118
119 return err;
120 }
121
122 static struct rt_hwtimer_device _hwtimer;
123 static const struct rt_hwtimer_ops _hwtimer_ops =
124 {
125 .init = mcu_hwtimer_init,
126 .start = mcu_hwtimer_start,
127 .stop = mcu_hwtimer_stop,
128 .count_get = mcu_hwtimer_count_get,
129 .control = mcu_hwtimer_control};
130
131 static const struct rt_hwtimer_info _hwtimer_info =
132 {
133 // TODO:what is the true max and min?
134 .maxfreq = 1000000UL,
135 .minfreq = 1000000UL,
136 .maxcnt = 0xFFFF,
137 .cntmode = HWTIMER_MODE_ONESHOT};
138
rt_hw_hwtimer_init(void)139 int rt_hw_hwtimer_init(void)
140 {
141
142 char *name = "timer0";
143
144 gptimer_handle_t gptimer = NULL;
145 gptimer_config_t timer_config = {
146 .clk_src = GPTIMER_CLK_SRC_DEFAULT,
147 .direction = GPTIMER_COUNT_UP,
148 .resolution_hz = 1 * 1000 * 1000,
149 };
150
151 gptimer_event_callbacks_t cbs = {
152 .on_alarm = mcu_hwtimer_intr_handler,
153 };
154
155 ESP_ERROR_CHECK(gptimer_new_timer(&timer_config, &gptimer));
156 ESP_ERROR_CHECK(gptimer_register_event_callbacks(gptimer, &cbs, &_hwtimer));
157
158 _hwtimer.info = &_hwtimer_info;
159 _hwtimer.ops = &_hwtimer_ops;
160
161 return rt_device_hwtimer_register(&_hwtimer, name, (void *)gptimer);
162
163 }
164
165 INIT_DEVICE_EXPORT(rt_hw_hwtimer_init);
166 #endif /* RT_USING_HWTIMER */
167