/* FreeRTOS */ #include "FreeRTOS.h" #include "semphr.h" #include "task.h" /* LVGL */ #include "lv_demos.h" #include "lvgl.h" /* App */ #include "app_impl_lcd.h" #include "app_lvgl.h" #define APP_LVGL_WIDTH (360) #define APP_LVGL_HEIGHT (360) static SemaphoreHandle_t s_lvgl_semphr = NULL; static uint16_t s_lcd_buffer[APP_LVGL_WIDTH * 10]; static uint32_t app_lvgl_get_tick_cb(void); static void app_lvgl_lcd_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map); static void app_lvgl_task(void *arguments); int app_lvgl_init(void) { s_lvgl_semphr = xSemaphoreCreateBinary(); if (s_lvgl_semphr == NULL) { return -1; } xSemaphoreGive(s_lvgl_semphr); app_lcd_impl_init(NULL); lv_init(); lv_tick_set_cb(app_lvgl_get_tick_cb); uint16_t hor_res = APP_LVGL_WIDTH; uint16_t ver_res = APP_LVGL_HEIGHT; lv_display_t *display = lv_display_create(hor_res, ver_res); if (display == NULL) { goto deinit_lv_exit; } lv_display_set_flush_cb(display, app_lvgl_lcd_flush_cb); lv_display_set_buffers(display, s_lcd_buffer, NULL, sizeof(s_lcd_buffer), LV_DISPLAY_RENDER_MODE_PARTIAL); lv_demo_widgets(); if (xTaskCreate(app_lvgl_task, "LVGL", 2048, NULL, 3, NULL) != pdPASS) { goto destroy_display_exit; } return 0; destroy_display_exit: lv_display_delete(display); deinit_lv_exit: lv_deinit(); vSemaphoreDelete(s_lvgl_semphr); return -1; } bool app_lvgl_lock(uint32_t timeout_ms) { if (xSemaphoreTake(s_lvgl_semphr, pdMS_TO_TICKS(timeout_ms)) != pdPASS) { return false; } return true; } void app_lvgl_unlock(void) { xSemaphoreGive(s_lvgl_semphr); } static uint32_t app_lvgl_get_tick_cb(void) { return xTaskGetTickCount(); } static void app_lvgl_lcd_flush_cb(lv_display_t *disp, const lv_area_t *area, uint8_t *px_map) { lv_display_flush_ready(disp); } static void app_lvgl_task(void *arguments) { for (;;) { if (app_lvgl_lock(portMAX_DELAY)) { lv_task_handler(); app_lvgl_unlock(); } vTaskDelay(pdMS_TO_TICKS(5)); } }