first commit
This commit is contained in:
commit
0ef2017d18
28 files changed
+1882
No files matched your search
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Minimal LVGL 9 port layer: tick source, service task, and a recursive lock.
|
||||
*
|
||||
* LVGL needs three things the application must supply: a millisecond tick, a
|
||||
* periodic call to lv_timer_handler(), and mutual exclusion around its API.
|
||||
*/
|
||||
|
||||
#include "esp_check.h"
|
||||
#include "esp_log.h"
|
||||
#include "esp_timer.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/semphr.h"
|
||||
#include "freertos/task.h"
|
||||
#include "lvgl.h"
|
||||
|
||||
#include "lvgl_port.h"
|
||||
|
||||
static const char *TAG = "lvgl_port";
|
||||
|
||||
#define LVGL_TICK_PERIOD_MS 2
|
||||
#define LVGL_TASK_STACK_SIZE 8192
|
||||
#define LVGL_TASK_PRIORITY 4
|
||||
#define LVGL_TASK_MAX_DELAY_MS 500
|
||||
#define LVGL_TASK_MIN_DELAY_MS 1
|
||||
|
||||
static SemaphoreHandle_t lvgl_mutex = NULL;
|
||||
static esp_timer_handle_t tick_timer = NULL;
|
||||
static volatile bool paused = false;
|
||||
|
||||
static void lvgl_tick_cb(void *arg)
|
||||
{
|
||||
lv_tick_inc(LVGL_TICK_PERIOD_MS);
|
||||
}
|
||||
|
||||
static void lvgl_task(void *arg)
|
||||
{
|
||||
ESP_LOGI(TAG, "LVGL task started");
|
||||
|
||||
while (1) {
|
||||
uint32_t delay_ms = LVGL_TASK_MAX_DELAY_MS;
|
||||
|
||||
if (paused) {
|
||||
/* Leave the framebuffer untouched -- the panel keeps scanning it
|
||||
* out, so the last frame stays on screen. */
|
||||
vTaskDelay(pdMS_TO_TICKS(20));
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lvgl_port_lock(-1)) {
|
||||
delay_ms = lv_timer_handler();
|
||||
lvgl_port_unlock();
|
||||
}
|
||||
|
||||
if (delay_ms > LVGL_TASK_MAX_DELAY_MS) {
|
||||
delay_ms = LVGL_TASK_MAX_DELAY_MS;
|
||||
} else if (delay_ms < LVGL_TASK_MIN_DELAY_MS) {
|
||||
delay_ms = LVGL_TASK_MIN_DELAY_MS;
|
||||
}
|
||||
|
||||
vTaskDelay(pdMS_TO_TICKS(delay_ms));
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t lvgl_port_init(void)
|
||||
{
|
||||
/* Recursive: lv_timer_handler() runs callbacks that may re-enter code
|
||||
* which also takes the lock. */
|
||||
lvgl_mutex = xSemaphoreCreateRecursiveMutex();
|
||||
ESP_RETURN_ON_FALSE(lvgl_mutex != NULL, ESP_ERR_NO_MEM, TAG, "mutex alloc failed");
|
||||
|
||||
lv_init();
|
||||
|
||||
ESP_LOGI(TAG, "LVGL %d.%d.%d initialized",
|
||||
lv_version_major(), lv_version_minor(), lv_version_patch());
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t lvgl_port_start(void)
|
||||
{
|
||||
const esp_timer_create_args_t timer_args = {
|
||||
.callback = lvgl_tick_cb,
|
||||
.name = "lvgl_tick",
|
||||
};
|
||||
ESP_RETURN_ON_ERROR(esp_timer_create(&timer_args, &tick_timer), TAG,
|
||||
"tick timer create failed");
|
||||
ESP_RETURN_ON_ERROR(esp_timer_start_periodic(tick_timer, LVGL_TICK_PERIOD_MS * 1000),
|
||||
TAG, "tick timer start failed");
|
||||
|
||||
const BaseType_t ok = xTaskCreate(lvgl_task, "lvgl", LVGL_TASK_STACK_SIZE,
|
||||
NULL, LVGL_TASK_PRIORITY, NULL);
|
||||
ESP_RETURN_ON_FALSE(ok == pdPASS, ESP_ERR_NO_MEM, TAG, "LVGL task create failed");
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void lvgl_port_pause(void)
|
||||
{
|
||||
if (paused) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Take the lock before setting the flag so we cannot stop the task
|
||||
* mid-render, then release it -- the flag alone keeps the task idle and
|
||||
* callers stay free to mutate widgets while paused.
|
||||
*/
|
||||
if (lvgl_port_lock(1000)) {
|
||||
paused = true;
|
||||
lvgl_port_unlock();
|
||||
} else {
|
||||
ESP_LOGW(TAG, "pause: lock timed out, pausing anyway");
|
||||
paused = true;
|
||||
}
|
||||
}
|
||||
|
||||
void lvgl_port_resume(void)
|
||||
{
|
||||
paused = false;
|
||||
}
|
||||
|
||||
bool lvgl_port_is_paused(void)
|
||||
{
|
||||
return paused;
|
||||
}
|
||||
|
||||
bool lvgl_port_lock(int timeout_ms)
|
||||
{
|
||||
const TickType_t ticks = (timeout_ms < 0) ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
|
||||
return xSemaphoreTakeRecursive(lvgl_mutex, ticks) == pdTRUE;
|
||||
}
|
||||
|
||||
void lvgl_port_unlock(void)
|
||||
{
|
||||
xSemaphoreGiveRecursive(lvgl_mutex);
|
||||
}
|
||||
Reference in new issue
Block a user