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
37
38
42
43
44
45
46
47
48
49
50
51
52
53
54
55
64
65
74
75
76
77
78
79
80
84
85
90
91
92
93
94
95
96
97
98
99
100
101
102
103
107
108
113
114
115
117
118
119
120
121
122
123
124
125
126
127
128
129
135
136
137
138
139
140
141
142
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
167
168
169
170
175
176
177
178
179
180
181
182
183
184
185
186
187
192
193
194
195
196
197
198
199
200
204
205
206
210
211
212
213
214
215
216
217
218
219
220
224
225
226
227
228
229
230
231
232
233
234
235
236
237
242
243
248
249
250
251
256
261
262
263
264
265
266
267
268
272
273
277
278
279
280
281
282
287
288
293
294
295
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
321
322
323
324
325
326
329
330
331
/* ... */
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include "osi/alarm.h"
#include "osi/allocator.h"
#include "osi/list.h"
#include "esp_timer.h"
#include "btc/btc_task.h"
#include "btc/btc_alarm.h"
#include "osi/mutex.h"
#include "bt_common.h"11 includes
typedef struct alarm_t {
esp_timer_handle_t alarm_hdl;
osi_alarm_callback_t cb;
void *cb_data;
int64_t deadline_us;
}{ ... } osi_alarm_t;
enum {
ALARM_STATE_IDLE,
ALARM_STATE_OPEN,
}{ ... };
static osi_mutex_t alarm_mutex;
static int alarm_state;
#if (BT_BLE_DYNAMIC_ENV_MEMORY == FALSE)
static struct alarm_t alarm_cbs[ALARM_CBS_NUM];
#else
static struct alarm_t *alarm_cbs;
#endif
static osi_alarm_err_t alarm_free(osi_alarm_t *alarm);
static osi_alarm_err_t alarm_set(osi_alarm_t *alarm, period_ms_t timeout, bool is_periodic);
int osi_alarm_create_mux(void)
{
if (alarm_state != ALARM_STATE_IDLE) {
OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state);
return -1;
}{...}
osi_mutex_new(&alarm_mutex);
return 0;
}{ ... }
int osi_alarm_delete_mux(void)
{
if (alarm_state != ALARM_STATE_IDLE) {
OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state);
return -1;
}{...}
osi_mutex_free(&alarm_mutex);
return 0;
}{ ... }
void osi_alarm_init(void)
{
assert(alarm_mutex != NULL);
osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
if (alarm_state != ALARM_STATE_IDLE) {
OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state);
goto end;
}{...}
#if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE)
if ((alarm_cbs = (osi_alarm_t *)osi_malloc(sizeof(osi_alarm_t) * ALARM_CBS_NUM)) == NULL) {
OSI_TRACE_ERROR("%s, malloc failed\n", __func__);
goto end;
}{...}
#endif/* ... */
memset(alarm_cbs, 0x00, sizeof(osi_alarm_t) * ALARM_CBS_NUM);
alarm_state = ALARM_STATE_OPEN;
end:
osi_mutex_unlock(&alarm_mutex);
}{ ... }
void osi_alarm_deinit(void)
{
assert(alarm_mutex != NULL);
osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
if (alarm_state != ALARM_STATE_OPEN) {
OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state);
goto end;
}{...}
for (int i = 0; i < ALARM_CBS_NUM; i++) {
if (alarm_cbs[i].alarm_hdl != NULL) {
alarm_free(&alarm_cbs[i]);
}{...}
}{...}
#if (BT_BLE_DYNAMIC_ENV_MEMORY == TRUE)
osi_free(alarm_cbs);
alarm_cbs = NULL;/* ... */
#endif
alarm_state = ALARM_STATE_IDLE;
end:
osi_mutex_unlock(&alarm_mutex);
}{ ... }
static struct alarm_t *alarm_cbs_lookfor_available(void)
{
int i;
for (i = 0; i < ALARM_CBS_NUM; i++) {
if (alarm_cbs[i].alarm_hdl == NULL) {
OSI_TRACE_DEBUG("%s %d %p\n", __func__, i, &alarm_cbs[i]);
return &alarm_cbs[i];
}{...}
}{...}
return NULL;
}{ ... }
static void alarm_cb_handler(struct alarm_t *alarm)
{
OSI_TRACE_DEBUG("TimerID %p\n", alarm);
if (alarm_state != ALARM_STATE_OPEN) {
OSI_TRACE_WARNING("%s, invalid state %d\n", __func__, alarm_state);
return;
}{...}
btc_msg_t msg = {0};
btc_alarm_args_t arg;
msg.sig = BTC_SIG_API_CALL;
msg.pid = BTC_PID_ALARM;
arg.cb = alarm->cb;
arg.cb_data = alarm->cb_data;
btc_transfer_context(&msg, &arg, sizeof(btc_alarm_args_t), NULL, NULL);
}{ ... }
osi_alarm_t *osi_alarm_new(const char *alarm_name, osi_alarm_callback_t callback, void *data, period_ms_t timer_expire)
{
assert(alarm_mutex != NULL);
struct alarm_t *timer_id = NULL;
osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
if (alarm_state != ALARM_STATE_OPEN) {
OSI_TRACE_ERROR("%s, invalid state %d\n", __func__, alarm_state);
timer_id = NULL;
goto end;
}{...}
timer_id = alarm_cbs_lookfor_available();
if (!timer_id) {
OSI_TRACE_ERROR("%s alarm_cbs exhausted\n", __func__);
timer_id = NULL;
goto end;
}{...}
esp_timer_create_args_t tca = {0};
tca.callback = (esp_timer_cb_t)alarm_cb_handler;
tca.arg = timer_id;
tca.dispatch_method = ESP_TIMER_TASK;
tca.name = alarm_name;
timer_id->cb = callback;
timer_id->cb_data = data;
timer_id->deadline_us = 0;
esp_err_t stat = esp_timer_create(&tca, &timer_id->alarm_hdl);
if (stat != ESP_OK) {
OSI_TRACE_ERROR("%s failed to create timer, err 0x%x\n", __func__, stat);
timer_id = NULL;
goto end;
}{...}
end:
osi_mutex_unlock(&alarm_mutex);
return timer_id;
}{ ... }
static osi_alarm_err_t alarm_free(osi_alarm_t *alarm)
{
if (!alarm || alarm->alarm_hdl == NULL) {
OSI_TRACE_ERROR("%s null\n", __func__);
return OSI_ALARM_ERR_INVALID_ARG;
}{...}
esp_timer_stop(alarm->alarm_hdl);
esp_err_t stat = esp_timer_delete(alarm->alarm_hdl);
if (stat != ESP_OK) {
OSI_TRACE_ERROR("%s failed to delete timer, err 0x%x\n", __func__, stat);
return OSI_ALARM_ERR_FAIL;
}{...}
memset(alarm, 0, sizeof(osi_alarm_t));
return OSI_ALARM_ERR_PASS;
}{ ... }
void osi_alarm_free(osi_alarm_t *alarm)
{
assert(alarm_mutex != NULL);
osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
if (alarm_state != ALARM_STATE_OPEN) {
OSI_TRACE_ERROR("%s, invalid state %d\n", __func__, alarm_state);
goto end;
}{...}
alarm_free(alarm);
end:
osi_mutex_unlock(&alarm_mutex);
return;
}{ ... }
static osi_alarm_err_t alarm_set(osi_alarm_t *alarm, period_ms_t timeout, bool is_periodic)
{
assert(alarm_mutex != NULL);
osi_alarm_err_t ret = OSI_ALARM_ERR_PASS;
osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
if (alarm_state != ALARM_STATE_OPEN) {
OSI_TRACE_ERROR("%s, invalid state %d\n", __func__, alarm_state);
ret = OSI_ALARM_ERR_INVALID_STATE;
goto end;
}{...}
if (!alarm || alarm->alarm_hdl == NULL) {
OSI_TRACE_ERROR("%s null\n", __func__);
ret = OSI_ALARM_ERR_INVALID_ARG;
goto end;
}{...}
int64_t timeout_us = 1000 * (int64_t)timeout;
esp_err_t stat;
if (is_periodic) {
stat = esp_timer_start_periodic(alarm->alarm_hdl, (uint64_t)timeout_us);
}{...} else {
stat = esp_timer_start_once(alarm->alarm_hdl, (uint64_t)timeout_us);
}{...}
if (stat != ESP_OK) {
OSI_TRACE_ERROR("%s failed to start timer, err 0x%x\n", __func__, stat);
ret = OSI_ALARM_ERR_FAIL;
goto end;
}{...}
alarm->deadline_us = is_periodic ? 0 : (timeout_us + esp_timer_get_time());
end:
osi_mutex_unlock(&alarm_mutex);
return ret;
}{ ... }
osi_alarm_err_t osi_alarm_set(osi_alarm_t *alarm, period_ms_t timeout)
{
return alarm_set(alarm, timeout, FALSE);
}{ ... }
osi_alarm_err_t osi_alarm_set_periodic(osi_alarm_t *alarm, period_ms_t period)
{
return alarm_set(alarm, period, TRUE);
}{ ... }
osi_alarm_err_t osi_alarm_cancel(osi_alarm_t *alarm)
{
int ret = OSI_ALARM_ERR_PASS;
osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
if (alarm_state != ALARM_STATE_OPEN) {
OSI_TRACE_ERROR("%s, invalid state %d\n", __func__, alarm_state);
ret = OSI_ALARM_ERR_INVALID_STATE;
goto end;
}{...}
if (!alarm || alarm->alarm_hdl == NULL) {
OSI_TRACE_ERROR("%s null\n", __func__);
ret = OSI_ALARM_ERR_INVALID_ARG;
goto end;
}{...}
esp_err_t stat = esp_timer_stop(alarm->alarm_hdl);
if (stat != ESP_OK) {
OSI_TRACE_DEBUG("%s failed to stop timer, err 0x%x\n", __func__, stat);
ret = OSI_ALARM_ERR_FAIL;
goto end;
}{...}
end:
osi_mutex_unlock(&alarm_mutex);
return ret;
}{ ... }
period_ms_t osi_alarm_get_remaining_ms(const osi_alarm_t *alarm)
{
assert(alarm_mutex != NULL);
int64_t dt_us = 0;
osi_mutex_lock(&alarm_mutex, OSI_MUTEX_MAX_TIMEOUT);
dt_us = alarm->deadline_us - esp_timer_get_time();
osi_mutex_unlock(&alarm_mutex);
return (dt_us > 0) ? (period_ms_t)(dt_us / 1000) : 0;
}{ ... }
uint32_t osi_time_get_os_boottime_ms(void)
{
return (uint32_t)(esp_timer_get_time() / 1000);
}{ ... }
bool osi_alarm_is_active(osi_alarm_t *alarm)
{
assert(alarm != NULL);
if (alarm->alarm_hdl != NULL) {
return esp_timer_is_active(alarm->alarm_hdl);
}{...}
return false;
}{ ... }