-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathesp_timer_shim.c
More file actions
155 lines (142 loc) · 4.31 KB
/
esp_timer_shim.c
File metadata and controls
155 lines (142 loc) · 4.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "blobs/include/esp_timer.h"
#ifndef ESPRADIO_TIMER_SHIM_DEBUG
#define ESPRADIO_TIMER_SHIM_DEBUG 0
#endif
extern uint64_t espradio_time_us_now(void);
struct esp_timer {
struct esp_timer *next;
esp_timer_cb_t callback;
void *arg;
uint64_t period_us;
uint64_t expiry_us;
bool periodic;
bool active;
};
static struct esp_timer *s_timer_list;
__attribute__((weak)) esp_err_t esp_timer_create(const esp_timer_create_args_t *create_args,
esp_timer_handle_t *out_handle) {
if ((create_args == NULL) || (out_handle == NULL) || (create_args->callback == NULL)) {
return ESP_ERR_INVALID_ARG;
}
void *espradio_arena_alloc(size_t);
struct esp_timer *t = (struct esp_timer *)espradio_arena_alloc(sizeof(struct esp_timer));
if (t == NULL) {
return ESP_ERR_NO_MEM;
}
memset(t, 0, sizeof(*t));
t->callback = create_args->callback;
t->arg = create_args->arg;
t->next = s_timer_list;
s_timer_list = t;
*out_handle = t;
return ESP_OK;
}
__attribute__((weak)) esp_err_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us) {
if (timer == NULL) {
return ESP_ERR_INVALID_ARG;
}
struct esp_timer *t = (struct esp_timer *)timer;
uint64_t now = espradio_time_us_now();
t->periodic = false;
t->period_us = timeout_us;
t->expiry_us = now + timeout_us;
t->active = true;
if (timeout_us == 0 && t->callback != NULL) {
t->callback(t->arg);
t->active = false;
}
return ESP_OK;
}
__attribute__((weak)) esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period) {
if ((timer == NULL) || (period == 0)) {
return ESP_ERR_INVALID_ARG;
}
struct esp_timer *t = (struct esp_timer *)timer;
uint64_t now = espradio_time_us_now();
t->periodic = true;
t->period_us = period;
t->expiry_us = now + period;
t->active = true;
return ESP_OK;
}
__attribute__((weak)) esp_err_t esp_timer_restart(esp_timer_handle_t timer, uint64_t timeout_us) {
if (timer == NULL) {
return ESP_ERR_INVALID_ARG;
}
struct esp_timer *t = (struct esp_timer *)timer;
uint64_t now = espradio_time_us_now();
t->periodic = false;
t->period_us = timeout_us;
t->expiry_us = now + timeout_us;
t->active = true;
return ESP_OK;
}
__attribute__((weak)) esp_err_t esp_timer_stop(esp_timer_handle_t timer) {
if (timer == NULL) {
return ESP_ERR_INVALID_ARG;
}
struct esp_timer *t = (struct esp_timer *)timer;
t->active = false;
return ESP_OK;
}
__attribute__((weak)) esp_err_t esp_timer_delete(esp_timer_handle_t timer) {
if (timer == NULL) {
return ESP_ERR_INVALID_ARG;
}
struct esp_timer *t = (struct esp_timer *)timer;
struct esp_timer **pp = &s_timer_list;
while (*pp != NULL) {
if (*pp == t) {
*pp = t->next;
break;
}
pp = &(*pp)->next;
}
void espradio_arena_free(void *);
espradio_arena_free(t);
return ESP_OK;
}
__attribute__((weak)) int64_t esp_timer_get_time(void) {
return (int64_t)espradio_time_us_now();
}
__attribute__((weak)) bool esp_timer_is_active(esp_timer_handle_t timer) {
if (timer == NULL) {
return false;
}
return ((struct esp_timer *)timer)->active;
}
int espradio_esp_timer_poll_due(int max_fire) {
if (max_fire <= 0) {
return 0;
}
int fired = 0;
uint64_t now = espradio_time_us_now();
for (struct esp_timer *t = s_timer_list; t != NULL && fired < max_fire; t = t->next) {
if ((!t->active) || (t->callback == NULL)) {
continue;
}
if (now < t->expiry_us) {
continue;
}
uintptr_t cb_addr = (uintptr_t)t->callback;
if (cb_addr < 0x40000000u || cb_addr >= 0x42800000u) {
printf("esp_timer: BAD callback=%p arg=%p — skipping\n",
(void *)t->callback, t->arg);
t->active = false;
continue;
}
t->callback(t->arg);
fired++;
now = espradio_time_us_now();
if (t->periodic) {
t->expiry_us = now + t->period_us;
} else {
t->active = false;
}
}
return fired;
}