Skip to content

Commit 73d2862

Browse files
TIMER refactoring (#7904)
* refactor using GPtimer * Updated timer HW test * fix examples * Add v2.0.7 in issue template (#7871) * refactor using GPtimer * Updated timer HW test * fix examples * Revert "Add v2.0.7 in issue template (#7871)" This reverts commit fcc3b17. * Update upload-artifact to v3 in HW CI * Revert "Update upload-artifact to v3 in HW CI" This reverts commit 1ba2280. * replace resolution with frequency * remove count_down option * countup removed from examples + header * Refactored timer object * code cleanup + examples and tests fixes * TimerAlarm fix --------- Co-authored-by: Vojtěch Bartoška <[email protected]>
1 parent f48cb4b commit 73d2862

File tree

5 files changed

+192
-273
lines changed

5 files changed

+192
-273
lines changed

cores/esp32/esp32-hal-timer.c

+123-203
Original file line numberDiff line numberDiff line change
@@ -13,261 +13,181 @@
1313
// limitations under the License.
1414

1515
#include "esp32-hal-timer.h"
16-
#include "driver/timer.h"
16+
#include "driver/gptimer.h"
1717
#include "soc/soc_caps.h"
18+
#include "clk_tree.h"
1819

19-
typedef union {
20-
struct {
21-
uint32_t reserved0: 10;
22-
uint32_t alarm_en: 1; /*When set alarm is enabled*/
23-
uint32_t level_int_en: 1; /*When set level type interrupt will be generated during alarm*/
24-
uint32_t edge_int_en: 1; /*When set edge type interrupt will be generated during alarm*/
25-
uint32_t divider: 16; /*Timer clock (T0/1_clk) pre-scale value.*/
26-
uint32_t autoreload: 1; /*When set timer 0/1 auto-reload at alarming is enabled*/
27-
uint32_t increase: 1; /*When set timer 0/1 time-base counter increment. When cleared timer 0 time-base counter decrement.*/
28-
uint32_t enable: 1; /*When set timer 0/1 time-base counter is enabled*/
29-
};
30-
uint32_t val;
31-
} timer_cfg_t;
32-
33-
#define NUM_OF_TIMERS SOC_TIMER_GROUP_TOTAL_TIMERS
20+
typedef void (*voidFuncPtr)(void);
21+
typedef void (*voidFuncPtrArg)(void*);
3422

35-
typedef struct hw_timer_s
36-
{
37-
uint8_t group;
38-
uint8_t num;
39-
} hw_timer_t;
23+
typedef struct {
24+
voidFuncPtr fn;
25+
void* arg;
26+
} interrupt_config_t;
4027

41-
// Works for all chips
42-
static hw_timer_t timer_dev[4] = {
43-
{0,0}, {1,0}, {0,1}, {1,1}
28+
struct timer_struct_t {
29+
gptimer_handle_t timer_handle;
30+
interrupt_config_t interrupt_handle;
4431
};
4532

46-
// NOTE: (in IDF 5.0 there wont be need to know groups/numbers
47-
// timer_init() will list thru all timers and return free timer handle)
48-
49-
50-
inline uint64_t timerRead(hw_timer_t *timer){
51-
52-
uint64_t value;
53-
timer_get_counter_value(timer->group, timer->num,&value);
54-
return value;
55-
}
33+
inline uint64_t timerRead(hw_timer_t * timer){
5634

57-
uint64_t timerAlarmRead(hw_timer_t *timer){
5835
uint64_t value;
59-
timer_get_alarm_value(timer->group, timer->num, &value);
36+
gptimer_get_raw_count(timer->timer_handle, &value);
6037
return value;
6138
}
6239

63-
void timerWrite(hw_timer_t *timer, uint64_t val){
64-
timer_set_counter_value(timer->group, timer->num, val);
65-
}
66-
67-
void timerAlarmWrite(hw_timer_t *timer, uint64_t alarm_value, bool autoreload){
68-
timer_set_alarm_value(timer->group, timer->num, alarm_value);
69-
timerSetAutoReload(timer,autoreload);
70-
}
71-
72-
void timerSetConfig(hw_timer_t *timer, uint32_t config){
73-
timer_cfg_t cfg;
74-
cfg.val = config;
75-
timer_set_alarm(timer->group, timer->num, cfg.alarm_en);
76-
timerSetDivider(timer,cfg.divider);
77-
timerSetAutoReload(timer,cfg.autoreload);
78-
timerSetCountUp(timer, cfg.increase);
79-
80-
if (cfg.enable) {
81-
timerStart(timer);
82-
}
83-
else{
84-
timerStop(timer);
85-
}
86-
return;
87-
}
88-
89-
uint32_t timerGetConfig(hw_timer_t *timer){
90-
timer_config_t timer_cfg;
91-
timer_get_config(timer->group, timer->num,&timer_cfg);
92-
93-
//Translate to default uint32_t
94-
timer_cfg_t cfg;
95-
cfg.alarm_en = timer_cfg.alarm_en;
96-
cfg.autoreload = timer_cfg.auto_reload;
97-
cfg.divider = timer_cfg.divider;
98-
cfg.edge_int_en = timer_cfg.intr_type;
99-
cfg.level_int_en = !timer_cfg.intr_type;
100-
cfg.enable = timer_cfg.counter_en;
101-
cfg.increase = timer_cfg.counter_dir;
102-
103-
return cfg.val;
104-
}
105-
106-
void timerSetCountUp(hw_timer_t *timer, bool countUp){
107-
timer_set_counter_mode(timer->group, timer->num,countUp);
40+
void timerWrite(hw_timer_t * timer, uint64_t val){
41+
gptimer_set_raw_count(timer->timer_handle, val);
10842
}
10943

110-
bool timerGetCountUp(hw_timer_t *timer){
111-
timer_cfg_t config;
112-
config.val = timerGetConfig(timer);
113-
return config.increase;
114-
}
115-
116-
void timerSetAutoReload(hw_timer_t *timer, bool autoreload){
117-
timer_set_auto_reload(timer->group, timer->num,autoreload);
118-
}
119-
120-
bool timerGetAutoReload(hw_timer_t *timer){
121-
timer_cfg_t config;
122-
config.val= timerGetConfig(timer);
123-
return config.autoreload;
124-
}
125-
126-
// Set divider from 2 to 65535
127-
void timerSetDivider(hw_timer_t *timer, uint16_t divider){
128-
if(divider < 2)
129-
{
130-
log_e("Timer divider must be set in range of 2 to 65535");
131-
return;
132-
}
133-
timer_set_divider(timer->group, timer->num,divider);
134-
}
135-
136-
uint16_t timerGetDivider(hw_timer_t *timer){
137-
timer_cfg_t config;
138-
config.val = timerGetConfig(timer);
139-
return config.divider;
140-
}
141-
142-
void timerStart(hw_timer_t *timer){
143-
timer_start(timer->group, timer->num);
144-
}
145-
146-
void timerStop(hw_timer_t *timer){
147-
timer_pause(timer->group, timer->num);
44+
void timerAlarm(hw_timer_t * timer, uint64_t alarm_value, bool autoreload, uint64_t reload_count){
45+
esp_err_t err = ESP_OK;
46+
gptimer_alarm_config_t alarm_cfg = {
47+
.alarm_count = alarm_value,
48+
.reload_count = reload_count,
49+
.flags.auto_reload_on_alarm = autoreload,
50+
};
51+
err = gptimer_set_alarm_action(timer->timer_handle, &alarm_cfg);
52+
if (err != ESP_OK){
53+
log_e("Timer Alarm Write failed, error num=%d", err);
54+
}
14855
}
14956

150-
void timerRestart(hw_timer_t *timer){
151-
timerWrite(timer,0);
57+
uint32_t timerGetFrequency(hw_timer_t * timer){
58+
uint32_t frequency;
59+
gptimer_get_resolution(timer->timer_handle, &frequency);
60+
return frequency;
15261
}
15362

154-
bool timerStarted(hw_timer_t *timer){
155-
timer_cfg_t config;
156-
config.val = timerGetConfig(timer);
157-
return config.enable;
63+
void timerStart(hw_timer_t * timer){
64+
gptimer_start(timer->timer_handle);
15865
}
15966

160-
void timerAlarmEnable(hw_timer_t *timer){
161-
timer_set_alarm(timer->group, timer->num,true);
67+
void timerStop(hw_timer_t * timer){
68+
gptimer_stop(timer->timer_handle);
16269
}
16370

164-
void timerAlarmDisable(hw_timer_t *timer){
165-
timer_set_alarm(timer->group, timer->num,false);
71+
void timerRestart(hw_timer_t * timer){
72+
gptimer_set_raw_count(timer->timer_handle,0);
16673
}
16774

168-
bool timerAlarmEnabled(hw_timer_t *timer){
169-
timer_cfg_t config;
170-
config.val = timerGetConfig(timer);
171-
return config.alarm_en;
172-
}
75+
hw_timer_t * timerBegin(uint32_t frequency){
76+
esp_err_t err = ESP_OK;
77+
uint32_t counter_src_hz = 0;
78+
uint32_t divider = 0;
79+
soc_periph_gptimer_clk_src_t clk;
17380

174-
static void _on_apb_change(void * arg, apb_change_ev_t ev_type, uint32_t old_apb, uint32_t new_apb){
175-
hw_timer_t * timer = (hw_timer_t *)arg;
176-
if(ev_type == APB_BEFORE_CHANGE){
177-
timerStop(timer);
178-
} else {
179-
old_apb /= 1000000;
180-
new_apb /= 1000000;
181-
uint16_t divider = (new_apb * timerGetDivider(timer)) / old_apb;
182-
timerSetDivider(timer,divider);
183-
timerStart(timer);
81+
soc_periph_gptimer_clk_src_t gptimer_clks[] = SOC_GPTIMER_CLKS;
82+
for (size_t i = 0; i < sizeof(gptimer_clks) / sizeof(gptimer_clks[0]); i++){
83+
clk = gptimer_clks[i];
84+
clk_tree_src_get_freq_hz(clk, CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz);
85+
divider = counter_src_hz / frequency;
86+
if((divider >= 2) && (divider <= 65536)){
87+
break;
88+
}
89+
else divider = 0;
18490
}
185-
}
18691

187-
hw_timer_t * timerBegin(uint8_t num, uint16_t divider, bool countUp){
188-
if(num >= NUM_OF_TIMERS)
189-
{
190-
log_e("Timer number %u exceeds available number of Timers.", num);
92+
if(divider == 0){
93+
log_e("Resolution cannot be reached with any clock source, aborting!");
19194
return NULL;
19295
}
19396

194-
hw_timer_t * timer = &timer_dev[num]; //Get Timer group/num from 0-3 number
195-
196-
timer_config_t config = {
197-
.divider = divider,
198-
.counter_dir = countUp,
199-
.counter_en = TIMER_PAUSE,
200-
.alarm_en = TIMER_ALARM_DIS,
201-
.auto_reload = false,
97+
gptimer_config_t config = {
98+
.clk_src = clk,
99+
.direction = GPTIMER_COUNT_UP,
100+
.resolution_hz = frequency,
101+
.flags.intr_shared = true,
202102
};
203103

204-
timer_init(timer->group, timer->num, &config);
205-
timer_set_counter_value(timer->group, timer->num, 0);
206-
timerStart(timer);
207-
addApbChangeCallback(timer, _on_apb_change);
104+
hw_timer_t *timer = malloc(sizeof(hw_timer_t));
105+
106+
err = gptimer_new_timer(&config, &timer->timer_handle);
107+
if (err != ESP_OK){
108+
log_e("Failed to create a new GPTimer, error num=%d", err);
109+
free(timer);
110+
return NULL;
111+
}
112+
gptimer_enable(timer->timer_handle);
113+
gptimer_start(timer->timer_handle);
208114
return timer;
209115
}
210116

211-
void timerEnd(hw_timer_t *timer){
212-
removeApbChangeCallback(timer, _on_apb_change);
213-
timer_deinit(timer->group, timer->num);
117+
void timerEnd(hw_timer_t * timer){
118+
esp_err_t err = ESP_OK;
119+
gptimer_disable(timer->timer_handle);
120+
err = gptimer_del_timer(timer->timer_handle);
121+
if (err != ESP_OK){
122+
log_e("Failed to destroy GPTimer, error num=%d", err);
123+
return;
124+
}
125+
free(timer);
214126
}
215127

216-
bool IRAM_ATTR timerFnWrapper(void *arg){
217-
void (*fn)(void) = arg;
218-
fn();
219-
128+
bool IRAM_ATTR timerFnWrapper(gptimer_handle_t timer, const gptimer_alarm_event_data_t *edata, void * args){
129+
interrupt_config_t * isr = (interrupt_config_t*)args;
130+
if(isr->fn) {
131+
if(isr->arg){
132+
((voidFuncPtrArg)isr->fn)(isr->arg);
133+
} else {
134+
isr->fn();
135+
}
136+
}
220137
// some additional logic or handling may be required here to approriately yield or not
221138
return false;
222139
}
223140

224-
void timerAttachInterruptFlag(hw_timer_t *timer, void (*fn)(void), bool edge, int intr_alloc_flags){
225-
if(edge){
226-
log_w("EDGE timer interrupt is not supported! Setting to LEVEL...");
227-
}
228-
timer_isr_callback_add(timer->group, timer->num, timerFnWrapper, fn, intr_alloc_flags);
229-
}
141+
void timerAttachInterruptFunctionalArg(hw_timer_t * timer, void (*userFunc)(void*), void * arg){
142+
esp_err_t err = ESP_OK;
143+
gptimer_event_callbacks_t cbs = {
144+
.on_alarm = timerFnWrapper,
145+
};
230146

231-
void timerAttachInterrupt(hw_timer_t *timer, void (*fn)(void), bool edge){
232-
timerAttachInterruptFlag(timer, fn, edge, 0);
233-
}
147+
timer->interrupt_handle.fn = (voidFuncPtr)userFunc;
148+
timer->interrupt_handle.arg = arg;
234149

235-
void timerDetachInterrupt(hw_timer_t *timer){
236-
timer_isr_callback_remove(timer->group, timer->num);
150+
gptimer_disable(timer->timer_handle);
151+
err = gptimer_register_event_callbacks(timer->timer_handle, &cbs, &timer->interrupt_handle);
152+
if (err != ESP_OK){
153+
log_e("Timer Attach Interrupt failed, error num=%d", err);
154+
}
155+
gptimer_enable(timer->timer_handle);
237156
}
238157

239-
uint64_t timerReadMicros(hw_timer_t *timer){
240-
uint64_t timer_val = timerRead(timer);
241-
uint16_t div = timerGetDivider(timer);
242-
return timer_val * div / (getApbFrequency() / 1000000);
158+
159+
void timerAttachInterruptArg(hw_timer_t * timer, void (*userFunc)(void*), void * arg){
160+
timerAttachInterruptFunctionalArg(timer, userFunc, arg);
243161
}
244162

245-
uint64_t timerReadMilis(hw_timer_t *timer){
246-
uint64_t timer_val = timerRead(timer);
247-
uint16_t div = timerGetDivider(timer);
248-
return timer_val * div / (getApbFrequency() / 1000);
163+
void timerAttachInterrupt(hw_timer_t * timer, voidFuncPtr userFunc){
164+
timerAttachInterruptFunctionalArg(timer, (voidFuncPtrArg)userFunc, NULL);
249165
}
250166

251-
double timerReadSeconds(hw_timer_t *timer){
252-
uint64_t timer_val = timerRead(timer);
253-
uint16_t div = timerGetDivider(timer);
254-
return (double)timer_val * div / getApbFrequency();
167+
void timerDetachInterrupt(hw_timer_t * timer){
168+
esp_err_t err = ESP_OK;
169+
err = gptimer_set_alarm_action(timer->timer_handle, NULL);
170+
timer->interrupt_handle.fn = NULL;
171+
timer->interrupt_handle.arg = NULL;
172+
if (err != ESP_OK){
173+
log_e("Timer Detach Interrupt failed, error num=%d", err);
174+
}
255175
}
256176

257-
uint64_t timerAlarmReadMicros(hw_timer_t *timer){
258-
uint64_t timer_val = timerAlarmRead(timer);
259-
uint16_t div = timerGetDivider(timer);
260-
return timer_val * div / (getApbFrequency() / 1000000);
177+
uint64_t timerReadMicros(hw_timer_t * timer){
178+
uint64_t timer_val = timerRead(timer);
179+
uint32_t frequency = timerGetFrequency(timer);
180+
return timer_val * 1000000 / frequency;
261181
}
262182

263-
uint64_t timerAlarmReadMilis(hw_timer_t *timer){
264-
uint64_t timer_val = timerAlarmRead(timer);
265-
uint16_t div = timerGetDivider(timer);
266-
return timer_val * div / (getApbFrequency() / 1000);
183+
uint64_t timerReadMilis(hw_timer_t * timer){
184+
uint64_t timer_val = timerRead(timer);
185+
uint32_t frequency = timerGetFrequency(timer);
186+
return timer_val * 1000 / frequency;
267187
}
268188

269-
double timerAlarmReadSeconds(hw_timer_t *timer){
270-
uint64_t timer_val = timerAlarmRead(timer);
271-
uint16_t div = timerGetDivider(timer);
272-
return (double)timer_val * div / getApbFrequency();
189+
double timerReadSeconds(hw_timer_t * timer){
190+
uint64_t timer_val = timerRead(timer);
191+
uint32_t frequency = timerGetFrequency(timer);
192+
return (double)timer_val / frequency;
273193
}

0 commit comments

Comments
 (0)