Skip to content

Commit c5df58b

Browse files
donghengdongheng
dongheng
authored and
dongheng
committed
fix(esp_timer): fix delete timer and timer processs later
Make sure that FreeRTOS deletes timer firstly and then API "esp_timer_delete" free the source.
1 parent 913a06a commit c5df58b

File tree

1 file changed

+77
-33
lines changed

1 file changed

+77
-33
lines changed

components/esp8266/source/esp_timer.c

Lines changed: 77 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -21,33 +21,79 @@
2121

2222
#define ESP_TIMER_HZ CONFIG_FREERTOS_HZ
2323

24+
typedef enum {
25+
ESP_TIMER_INIT = 0,
26+
ESP_TIMER_ONCE,
27+
ESP_TIMER_CYCLE,
28+
ESP_TIMER_STOP,
29+
ESP_TIMER_DELETE,
30+
} esp_timer_state_t;
31+
2432
struct esp_timer {
2533
TimerHandle_t os_timer;
2634

2735
esp_timer_cb_t cb;
2836

2937
void *arg;
3038

31-
TickType_t period_ticks;
39+
esp_timer_state_t state;
3240
};
3341

3442
static const char *TAG = "esp_timer";
3543

44+
static esp_err_t delete_timer(esp_timer_handle_t timer)
45+
{
46+
BaseType_t ret = xTimerDelete(timer->os_timer, portMAX_DELAY);
47+
if (ret == pdPASS)
48+
heap_caps_free(timer);
49+
50+
return ret == pdPASS ? ESP_OK : ESP_ERR_NO_MEM;
51+
}
52+
3653
/**
3754
* @brief FreeRTOS callback function
3855
*/
3956
static void esp_timer_callback(TimerHandle_t xTimer)
4057
{
41-
BaseType_t os_ret;
4258
struct esp_timer *timer = (struct esp_timer *)pvTimerGetTimerID(xTimer);
4359

4460
timer->cb(timer->arg);
4561

46-
if (!timer->period_ticks) {
47-
os_ret = xTimerStop(timer->os_timer, 0);
48-
if (os_ret != pdPASS) {
49-
ESP_LOGE(TAG, "Set timer from periodic to once error");
62+
switch (timer->state) {
63+
case ESP_TIMER_INIT:
64+
case ESP_TIMER_STOP:
65+
break;
66+
case ESP_TIMER_CYCLE: {
67+
BaseType_t ret = xTimerReset(timer->os_timer, portMAX_DELAY);
68+
if (ret != pdPASS) {
69+
ESP_LOGE(TAG, "start timer at callback error");
70+
} else {
71+
ESP_LOGD(TAG, "start timer at callback OK");
72+
}
73+
break;
74+
}
75+
case ESP_TIMER_ONCE: {
76+
BaseType_t ret = xTimerStop(timer->os_timer, portMAX_DELAY);
77+
if (ret != pdPASS) {
78+
ESP_LOGE(TAG, "stop timer at callback error");
79+
} else {
80+
timer->state = ESP_TIMER_STOP;
81+
ESP_LOGD(TAG, "stop timer at callback OK");
82+
}
83+
break;
84+
}
85+
case ESP_TIMER_DELETE: {
86+
esp_err_t ret = delete_timer(timer);
87+
if (ret != ESP_OK) {
88+
ESP_LOGE(TAG, "delete timer at callback error");
89+
} else {
90+
ESP_LOGD(TAG, "delete timer at callback OK");
91+
}
92+
break;
5093
}
94+
default:
95+
ESP_LOGE(TAG, "timer state error is %d", timer->state);
96+
break;
5197
}
5298
}
5399

@@ -83,17 +129,16 @@ esp_err_t esp_timer_create(const esp_timer_create_args_t* create_args,
83129
if (!esp_timer)
84130
return ESP_ERR_NO_MEM;
85131

86-
esp_timer->cb = create_args->callback;
87-
esp_timer->arg = create_args->arg;
88-
esp_timer->period_ticks = 0;
89-
90132
os_timer = xTimerCreate(create_args->name,
91133
portMAX_DELAY,
92-
pdTRUE,
134+
pdFALSE,
93135
esp_timer,
94136
esp_timer_callback);
95137
if (os_timer) {
96138
esp_timer->os_timer = os_timer;
139+
esp_timer->cb = create_args->callback;
140+
esp_timer->arg = create_args->arg;
141+
esp_timer->state = ESP_TIMER_INIT;
97142
*out_handle = (esp_timer_handle_t)esp_timer;
98143
} else {
99144
heap_caps_free(esp_timer);
@@ -120,14 +165,7 @@ esp_err_t esp_timer_start_once(esp_timer_handle_t timer, uint64_t timeout_us)
120165

121166
os_ret = xTimerChangePeriod(os_timer, ticks, portMAX_DELAY);
122167
if (os_ret == pdPASS) {
123-
TickType_t period_ticks = timer->period_ticks;
124-
125-
timer->period_ticks = 0;
126-
os_ret = xTimerStart(os_timer, portMAX_DELAY);
127-
if (os_ret != pdPASS) {
128-
timer->period_ticks = period_ticks;
129-
return ESP_ERR_INVALID_STATE;
130-
}
168+
timer->state = ESP_TIMER_ONCE;
131169
} else {
132170
return ESP_ERR_INVALID_STATE;
133171
}
@@ -152,14 +190,7 @@ esp_err_t esp_timer_start_periodic(esp_timer_handle_t timer, uint64_t period)
152190

153191
os_ret = xTimerChangePeriod(os_timer, ticks, portMAX_DELAY);
154192
if (os_ret == pdPASS) {
155-
TickType_t period_ticks = timer->period_ticks;
156-
157-
timer->period_ticks = ticks;
158-
os_ret = xTimerStart(os_timer, portMAX_DELAY);
159-
if (os_ret != pdPASS) {
160-
timer->period_ticks = period_ticks;
161-
return ESP_ERR_INVALID_STATE;
162-
}
193+
timer->state = ESP_TIMER_CYCLE;
163194
} else {
164195
return ESP_ERR_INVALID_STATE;
165196
}
@@ -178,6 +209,8 @@ esp_err_t esp_timer_stop(esp_timer_handle_t timer)
178209
BaseType_t os_ret;
179210

180211
os_ret = xTimerStop(os_timer, portMAX_DELAY);
212+
if (os_ret == pdPASS)
213+
timer->state = ESP_TIMER_STOP;
181214

182215
return os_ret == pdPASS ? ESP_OK : ESP_ERR_INVALID_STATE;
183216
}
@@ -187,14 +220,25 @@ esp_err_t esp_timer_stop(esp_timer_handle_t timer)
187220
*/
188221
esp_err_t esp_timer_delete(esp_timer_handle_t timer)
189222
{
223+
esp_err_t ret;
224+
190225
assert(timer);
191226

192-
TimerHandle_t os_timer = timer->os_timer;
193-
BaseType_t os_ret;
227+
if (xTimerGetTimerDaemonTaskHandle() == xTaskGetCurrentTaskHandle()) {
228+
timer->state = ESP_TIMER_DELETE;
229+
ret = ESP_OK;
230+
} else {
231+
UBaseType_t prio = uxTaskPriorityGet(NULL);
232+
if (prio >= configTIMER_TASK_PRIORITY)
233+
vTaskPrioritySet(NULL, configTIMER_TASK_PRIORITY - 1);
234+
else
235+
prio = 0;
194236

195-
os_ret = xTimerDelete(os_timer, portMAX_DELAY);
196-
if (os_ret == pdPASS)
197-
heap_caps_free(timer);
237+
ret = delete_timer(timer);
238+
239+
if (prio)
240+
vTaskPrioritySet(NULL, prio);
241+
}
198242

199-
return os_ret == pdPASS ? ESP_OK : ESP_ERR_INVALID_STATE;
243+
return ret;
200244
}

0 commit comments

Comments
 (0)