๐ English Abstract
This article provides an in-depth technical analysis of resolving GUI frame drops and micro-stuttering in ESP32-S3 applications using the LVGL graphics library. It details how to overcome PSRAM bandwidth bottlenecks, implement LVGL Direct Mode double buffering, and optimize GDMA (General Direct Memory Access) transfers for high-resolution displays. Key real-world hardware integration practices, including core pinning, cache coherence, and memory bus contention tuning, are thoroughly explored.
ESP32-S3๋ ๊ณ ์ฑ๋ฅ ๋์ผ์ฝ์ด MCU์ ๋๋ถ์ด ๋์ฉ๋ ์ธ๋ถ PSRAM(Pseudo Static Random Access Memory)์ ์ง์ํ์ฌ, ์๋ฒ ๋๋ ๋๋ฐ์ด์ค์์ ์๋ คํ ๊ทธ๋ํฝ ์ฌ์ฉ์ ์ธํฐํ์ด์ค(GUI, Graphical User Interface)๋ฅผ ๊ตฌํํ๋ ๋ฐ ๋งค์ฐ ๋๋ฆฌ ์ฌ์ฉ๋๊ณ ์์ต๋๋ค. ํนํ ์คํ์์ค ๊ทธ๋ํฝ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ธ LVGL(Light and Versatile Graphics Library)๊ณผ์ ์กฐํฉ์ ์ค๋งํธ ๊ฐ์ , ์ฐ์ ์ฉ HMI(Human Machine Interface), ์จ์ด๋ฌ๋ธ ๊ธฐ๊ธฐ ๊ฐ๋ฐ์ ํ์ค์ผ๋ก ์๋ฆฌ๋ฅผ ์ก์์ต๋๋ค.
ํ์ง๋ง 480x480 ๋๋ 800x480 ํด์๋ ์ด์์ LCD(RGB ๋๋ QSPI/3-Wire SPI ์ธํฐํ์ด์ค)๋ฅผ ๊ตฌ๋ํ ๋, ํ๋ฉด์ด ๋๊ธฐ๊ฑฐ๋ ์ฐข์ด์ง๋ ํฐ์ด๋ง ํ์(Tearing Effect), ๊ทธ๋ฆฌ๊ณ ํ๋ ์ ๋ ์ดํธ(FPS)๊ฐ 10~20fps ์์ค์ผ๋ก ๊ธ๊ฒฉํ ๋จ์ด์ง๋ ํ๋ ์ ๋๋กญ(Frame Drop) ๋ฌธ์ ๋ฅผ ๋น๋ฒํ๊ฒ ๊ฒช๊ฒ ๋ฉ๋๋ค. ESP32-S3์ ๋์ ํด๋ญ์ด 240MHz์ ๋ฌํจ์๋ ๋ถ๊ตฌํ๊ณ ๋ฐ์ํ๋ ์ด ๋ฌธ์ ์ ๊ทผ๋ณธ ์์ธ์ CPU ์ฐ์ฐ ๋ฅ๋ ฅ์ด ์๋ PSRAM ๋์ญํญ ๋ณ๋ชฉ(PSRAM Bandwidth Bottleneck)๊ณผ ์๋ชป๋ ๋ฉ๋ชจ๋ฆฌ ๋ฒํผ๋ง ์ ๋ต์ ์์ต๋๋ค.
๋ณธ ํฌ์คํ ์์๋ ESP32-S3 ๋ฐ LVGL ํ๊ฒฝ์์ ๋ฐ์ํ๋ ํ๋ฉด ์ ํ ํ์์ ํ๋์จ์ด์ ์์ธ์ ๊ตฌ์กฐ์ ์ผ๋ก ๋ถ์ํ๊ณ , ์ด๋ฅผ ์๋ฒฝํ ํด๊ฒฐํ ์ ์๋ Direct Mode ์ด์ค ๋ฒํผ๋ง(Double Buffering) ๊ธฐ์ ๋ฐ DMA ๋น๋๊ธฐ ์ ์ก(Asynchronous Transfer) ์ต์ ํ ํธ๋ฌ๋ธ์ํ ๊ธฐ๋ฒ์ ์ค๋ฌด ๊ด์ ์์ ๋ค๋ฃน๋๋ค.
1. ESP32-S3 PSRAM ๋์ญํญ ๋ณ๋ชฉ์ ๊ทผ๋ณธ ์์ธ ๋ถ์
ESP32-S3๋ ๋ด๋ถ SRAM(Internal SRAM, ์ฝ 512KB)๊ณผ ์ธ๋ถ PSRAM(External PSRAM, ์ต๋ 16MB)์ 2๊ณ์ธต ๋ฉ๋ชจ๋ฆฌ ๊ตฌ์กฐ๋ฅผ ๊ฐ์ง๋๋ค. ๋์คํ๋ ์ด ๋ฒํผ(Frame Buffer)์ ํฌ๊ธฐ๊ฐ 480x480 ํด์๋(16๋นํธ RGB565 ๊ธฐ์ค ์ฝ 460KB) ์ด์์ด ๋๋ฉด ๋ด๋ถ SRAM๋ง์ผ๋ก๋ 2๊ฐ ์ด์์ ๋ฒํผ๋ฅผ ํ ๋นํ ์ ์์ผ๋ฏ๋ก, ํ์์ ์ผ๋ก PSRAM์ ๋ฒํผ๋ฅผ ๋ฐฐ์นํด์ผ ํฉ๋๋ค.
์ด ๊ณผ์ ์์ ๋ค์๊ณผ ๊ฐ์ ํ๋์จ์ด์ ๋ณ๋ชฉ ์์๊ฐ ๋ฐ์ํฉ๋๋ค.
- Quad PSRAM vs Octal PSRAM์ ์ก์ธ์ค ์๋ ์ฐจ์ด: Quad SPI(QSPI) PSRAM์ 4๊ฐ ๋นํธ ๋ผ์ธ์ ์ฌ์ฉํ๋ฉฐ 80MHz ๋์ ์ ์คํจ ๋์ญํญ์ด ์ ํ์ ์ ๋๋ค. ๋ฐ๋ฉด Octal SPI(OPI) PSRAM์ 8๊ฐ ๋ผ์ธ์ ์ฌ์ฉํ์ฌ 2๋ฐฐ ์ด์์ ๋์ญํญ์ ์ ๊ณตํ์ง๋ง, ๋ ๋๋ง๊ณผ ๋์คํ๋ ์ด ๊ฐฑ์ ์ด ๋์์ ์ผ์ด๋ ๊ฒฝ์ฐ ์ฌ์ ํ ๋ฒ์ค ๊ฒฝํฉ(Bus Contention)์ด ์ผ์ด๋ฉ๋๋ค.
- ์บ์ ๋ฏธ์ค(Cache Miss) ๋ฐ CPU ์คํจ(CPU Stall): CPU๊ฐ PSRAM์ ์ง์ ์ ๊ทผํ์ฌ ๋์คํ๋ ์ด ํฝ์ ์ ๊ทธ๋ฆด ๋(Software Rendering), L1 ๋ฐ์ดํฐ ์บ์ miss๊ฐ ๋ฐ์ํ๋ฉด CPU ํ์ดํ๋ผ์ธ์ด ๋๊ธฐ ์ํ(Stall)์ ๋น ์ง๋๋ค. ์ด๋ LVGL ๋ ๋๋ง ๋ฃจํ์ ์ ์ฒด ์ฒ๋ฆฌ ์๊ฐ์ ์ง์ฐ์ํต๋๋ค.
- ๋ฉ๋ชจ๋ฆฌ ๋ฒ์ค ์ ์ ๊ฒฝํฉ(Memory Bus Contention): GDMA ์ปจํ ์คํธ๊ฐ PSRAM์์ ํฝ์ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด ๋์คํ๋ ์ด๋ก ์ก์ ํ๋ ๋์, CPU๋ LVGL ์์ ฏ์ ๋ค์ ํ๋ ์์ PSRAM์ ์ฐ๋ ค๊ณ ์๋ํฉ๋๋ค. ๋์ผํ SPI/OPI ๋ฒ์ค๋ฅผ ๋ ์ฃผ์ฒด๊ฐ ๋์์ ์ฌ์ฉํ๋ ค ํ๋ฉด์ ๋ณ๋ชฉ์ด ๊ทน๋ํ๋ฉ๋๋ค.
๊ธฐ์กด ๋ฐฉ์(Partial Render Buffer)์ ํ๊ณ
LVGL์ ๊ธฐ๋ณธ ๋์ ๋ชจ๋์ธ ๋ถ๋ถ ๋ ๋๋ง(Partial Rendering) ๋ชจ๋๋ ํ๋ฉด ํด์๋์ 1/10 ํฌ๊ธฐ ๋ฒํผ 1~2๊ฐ๋ฅผ SRAM์ ๋๊ณ ๋ณ๊ฒฝ๋ ์์ญ๋ง ๊ทธ๋ฆฌ์ง๋ง, ์ ์ฒด ํ๋ฉด์ด ์ง์์ ์ผ๋ก ๋ฐ๋๋ ์ ๋๋ฉ์ด์ ์ด๋ ๊ณ ํด์๋ ์ ํ ์ ์ฆ์ Flush Callback ํธ์ถ๊ณผ ์์ญ ๊ณ์ฐ ์ค๋ฒํค๋๋ก ์ธํด ์ฌ๊ฐํ ๋ณ๋ชฉ์ ์ ๋ฐํฉ๋๋ค.
2. LVGL Direct Mode ์ด์ค ๋ฒํผ๋ง ๋ชจ๋ ์ ํ ๋ฐ ๋ฉ์ปค๋์ฆ
ํ๋ ์ ๋๋กญ๊ณผ ํ๋ฉด ์ฐข์ด์ง์ ์๋ฒฝํ ๋ฐฉ์งํ๊ธฐ ์ํ ๊ฐ์ฅ ํจ๊ณผ์ ์ธ ๊ตฌ๋ ๋ฐฉ์์ Direct Mode(์ง์ ๋ชจ๋) ๊ธฐ๋ฐ์ ์ ์ฒด ํ๋ ์ ์ด์ค ๋ฒํผ๋ง(Full Frame Double Buffering)์ ๋๋ค.
๐ก LVGL Direct Mode ํต์ฌ ๊ฐ๋
Direct Mode์์๋ 2๊ฐ์ ์ ์ฒด ํด์๋ ํ๋ ์ ๋ฒํผ(FB1, FB2)๋ฅผ PSRAM์ ํ ๋นํฉ๋๋ค. ๋์คํ๋ ์ด ์ปจํธ๋กค๋ฌ(LCD Driver)๊ฐ FB1์ DMA๋ก ๋น๊ฒจ์ ํ๋ฉด์ ์ถ๋ ฅํ๋ ๋์, CPU ๋ฐ LVGL์ ์์ ํ ๋ ๋ฆฝ๋ FB2์ ๋ค์ ํ๋ ์์ ๋ณ๊ฒฝ ์ฌํญ์ ์ง์ ๋ ๋๋งํฉ๋๋ค. ๋ ๋๋ง์ด ์๋ฃ๋๋ฉด ํฌ์ธํฐ๋ง ๊ต์ฒด(Pointer Swapping)ํฉ๋๋ค.
LVGL v8 / v9 ์ค์ ์ฝ๋ ๊ตฌํ
๋ค์์ ESP-IDF ๋ฐ LVGL ํ๊ฒฝ์์ Direct Mode ์ด์ค ๋ฒํผ๋ฅผ ์ฌ๋ฐ๋ฅด๊ฒ ๊ตฌ์ฑํ๋ C์ธ์ด ์ค์ ์์์ ๋๋ค.
// LVGL Display Driver ๋ฐ Buffer ์ค์ ์์ (LVGL v8 ๊ธฐ์ค)
static lv_color_t *buf1 = NULL;
static lv_color_t *buf2 = NULL;
void init_lvgl_direct_mode(void) {
// 1. PSRAM ๋ฉ๋ชจ๋ฆฌ ํ ๋น (4byte alignment ์ง์ )
size_t buffer_size = DISP_HOR_RES * DISP_VER_RES * sizeof(lv_color_t);
buf1 = (lv_color_t *)heap_caps_malloc(buffer_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
buf2 = (lv_color_t *)heap_caps_malloc(buffer_size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT);
assert(buf1 != NULL && buf2 != NULL);
// 2. LVGL ๋ฒํผ ๊ตฌ์กฐ์ฒด ์ด๊ธฐํ
static lv_disp_draw_buf_t draw_buf;
lv_disp_draw_buf_init(&draw_buf, buf1, buf2, DISP_HOR_RES * DISP_VER_RES);
// 3. ๋์คํ๋ ์ด ๋๋ผ์ด๋ฒ ์ค์
static lv_disp_drv_t disp_drv;
lv_disp_drv_init(&disp_drv);
disp_drv.hor_res = DISP_HOR_RES;
disp_drv.ver_res = DISP_VER_RES;
disp_drv.flush_cb = my_lcd_flush_cb;
disp_drv.draw_buf = &draw_buf;
// โ
Direct Mode ํ์ฑํ โ
disp_drv.direct_mode = 1;
disp_drv.full_refresh = 0; // Direct Mode ์ฌ์ฉ ์ full_refresh๋ 0์ผ๋ก ์ค์
lv_disp_drv_register(&disp_drv);
}
Direct Mode๋ฅผ ํ์ฑํํ๋ฉด LVGL์ ํฝ์
๋ฐ์ดํฐ๋ฅผ ์์ ๋ฒํผ์์ ํ๋ ์ ๋ฒํผ๋ก ๋ณต์ฌํ๋ memcpy ๋จ๊ณ๋ฅผ ์์ ํ ์๋ตํ๊ฒ ๋์ด ๋ํญ์ ์ธ CPU ์ ์ ์จ ๊ฐ์ ํจ๊ณผ๋ฅผ ์ป๊ฒ ๋ฉ๋๋ค.
3. GDMA ๋น๋๊ธฐ ์ ์ก ์ต์ ํ ๋ฐ ์บ์ ์ผ๊ด์ฑ(Cache Coherence) ํด๊ฒฐ
Direct Mode ์ ์ฉ ํ์๋ ํ๋ฉด ์ฐ๊ทธ๋ฌ์ง์ด๋ ๋ฌด์์ ๋ ธ์ด์ฆ ํฝ์ ์ด ๋ฐ์ํ๋ ๊ฒฝ์ฐ๊ฐ ์์ต๋๋ค. ์ด๋ ESP32-S3์ GDMA(General Direct Memory Access) ์์ง๊ณผ CPU ์บ์ ์ฌ์ด์ ์บ์ ์ผ๊ด์ฑ(Cache Coherence) ๋ถ์ผ์น ๋ฐ ์ ์ก ๋๊ธฐํ ์คํจ๋ก ์ธํด ๋ฐ์ํฉ๋๋ค.
1) esp_lcd ๋๋ผ์ด๋ฒ์ DMA ๋น๋๊ธฐ Flush ๊ตฌํ
LVGL์ flush_cb ๋ด๋ถ์์ blocking ๋ฐฉ์์ผ๋ก ์ ์ก ์๋ฃ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉด ํ๋ ์์จ์ด ๊ทน๋๋ก ํ๋ฝํฉ๋๋ค. ๋ฐ๋์ ๋น๋๊ธฐ ์ฝ๋ฐฑ(Asynchronous Interrupt Callback) ๋ฐฉ์์ผ๋ก ์ ์ก ์๋ฃ ์์ ์ ์ ์ดํด์ผ ํฉ๋๋ค.
// LCD ์ ์ก ์๋ฃ ISR ์ฝ๋ฐฑ ํจ์
static bool notify_lvgl_flush_ready(esp_lcd_panel_io_handle_t panel_io, esp_lcd_panel_io_event_data_t *edata, void *user_ctx) {
lv_disp_drv_t *disp_driver = (lv_disp_drv_t *)user_ctx;
// LVGL์ DMA ์ ์ก์ด ์๋ฃ๋์์์ ๋น๋๊ธฐ๋ก ์๋ฆผ
lv_disp_flush_ready(disp_driver);
return false;
}
// Flush ์ฝ๋ฐฑ ๊ตฌํ
static void my_lcd_flush_cb(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *color_p) {
esp_lcd_panel_handle_t panel_handle = (esp_lcd_panel_handle_t) drv->user_data;
// Direct Mode์์๋ color_p๊ฐ ์ ์ฒด ํ๋ ์ ๋ฒํผ์ ์์ ์ฃผ์๋ฅผ ๊ฐ๋ฆฌํต๋๋ค.
// ๋น๋๊ธฐ๋ก DMA ์ ์ก ์์
esp_lcd_panel_draw_bitmap(panel_handle, area->x1, area->y1, area->x2 + 1, area->y2 + 1, color_p);
}
2) PSRAM Cache Write-back ๋ฐ Invalidate ํธ๋ฌ๋ธ์ํ
ESP32-S3 CPU๊ฐ PSRAM์ ๋ฐ์ดํฐ๋ฅผ ๊ธฐ๋กํ ๋, ๋ฐ์ดํฐ๋ ์ฆ๊ฐ PSRAM ์ค์ฒด์ ์จ์ง์ง ์๊ณ L1 Cache์ ๋จธ๋ฌผ๋ฌ ์์ ์ ์์ต๋๋ค(Write-back Cache). ์ด ์ํ์์ GDMA๊ฐ PSRAM ๋ฉ์ธ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ฐ๋ก ์ฝ์ด ๋์คํ๋ ์ด๋ก ์ ์กํ๋ฉด ์ด์ ํ๋ ์์ ์์์ด๋ ๊ทธ๋ํฝ ๊นจ์ง์ด ๋ฐ์ํฉ๋๋ค.
์ด๋ฅผ ๋ฐฉ์งํ๊ธฐ ์ํด esp_lcd ๋๋ผ์ด๋ฒ ์ค์ ์ DMA ๋ด๋ถ ํ๋ฌ์ ์ต์
์ ํ์ฑํํ๊ฑฐ๋, ํ๋ ์ ์ ์ก ์ง์ ์ ์บ์ ๋ผ์ธ ํ๋ฌ์ APIs(esp_cache_msync)๋ฅผ ํธ์ถํด์ผ ํฉ๋๋ค.
- ESP-IDF ๊ตฌ์ฑ ์ค์ (sdkconfig):
CONFIG_SPIRAM_TRY_ALLOCATE_SET_MEM_ON_FAIL=y๋ฐCONFIG_CACHE_L1_CACHE_SIZE์ต์ ํ ์ค์ . - SRAM ๋ฐ์ด๋ฉ line buffer ์ฌ์ฉ: RGB ์ธํฐํ์ด์ค(RGB LCD)๋ฅผ ์ฌ์ฉํ ๊ฒฝ์ฐ, Framebuffer๋ PSRAM์ ๋๋ bounce_buffer_size๋ฅผ SRAM ๋ด๋ถ ๋ฉ๋ชจ๋ฆฌ์ ์ต์ 10~20 ๋ผ์ธ ๋ถ๋์ ํ ๋นํ์ฌ DMA ๋ฒ์ค ์ ์ ์จ ํ์์์์ ๋ฐฉ์งํฉ๋๋ค.
4. ์ค๋ฌด ์ฃ์ง ์ผ์ด์ค ๋ฐ ์ฑ๋ฅ ๊ทน๋ํ ์ฒดํฌ๋ฆฌ์คํธ
ํ๋์จ์ด ๋ฐ ๋ฉํฐํ์คํน ํ๊ฒฝ์์ ํ๋ ์ ๋๋กญ์ ๋ฐฉ์งํ๊ธฐ ์ํด ๋ฐ๋์ ์ ๊ฒํด์ผ ํ 3๊ฐ์ง ์ฃ์ง ์ผ์ด์ค ์ต์ ํ ๊ธฐ๋ฒ์ ๋๋ค.
1) FreeRTOS ๋ฉํฐ์ฝ์ด ํ์คํฌ ๋ถ๋ฆฌ (Core Pinning)
ESP32-S3๋ 2๊ฐ์ ์ฝ์ด(Core 0, Core 1)๋ฅผ ๊ฐ์ง๊ณ ์์ต๋๋ค. LVGL GUI ํ์ด๋จธ ์ฒ๋ฆฌ ๋ฃจํด๊ณผ Wi-Fi/Bluetooth, ์ฌ์ฉ์ ์ ํ๋ฆฌ์ผ์ด์ ๋ก์ง์ด ๋์ผํ ์ฝ์ด์์ ์คํ๋๋ฉด ๋ ๋๋ง ์ฃผ๊ธฐ๊ฐ ๋ถ๊ท์นํด์ง๋๋ค.
- Core 0: Wi-Fi / Bluetooth ์คํ, ์์คํ ๋ฐฑ๊ทธ๋ผ์ด๋ ์์ , Protocol Task
- Core 1: LVGL ๋ ๋๋ง ์ ์ฉ ํ์คํฌ (
lv_timer_handler()์คํ), Touch Driver ์ธํฐ๋ฝํธ ์ฒ๋ฆฌ
// Core 1์ LVGL ์ ์ฉ ํ์คํฌ ํ ๋น
xTaskCreatePinnedToCore(
gui_task, /* ํ์คํฌ ํจ์ */
"LVGL Task", /* ํ์คํฌ ์ด๋ฆ */
1024 * 8, /* ์คํ ํฌ๊ธฐ */
NULL, /* ๋งค๊ฐ๋ณ์ */
5, /* ์ฐ์ ์์ (๋๊ฒ ์ค์ ) */
NULL, /* ํ์คํฌ ํธ๋ค */
1 /* Core 1์ ๊ณ ์ */
);
2) Octal PSRAM Clocks (80MHz vs 120MHz DDR) ์ค์
ESP32-S3 N16R8 ๋๋ N8R8 ๋ชจ๋๊ณผ ๊ฐ์ด Octal SPI PSRAM์ ํ์ฌํ ๋ชจ๋์ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ, sdkconfig์์ PSRAM Clock์ 80MHz OPI ๋ชจ๋๋ก ์ค์ ํด์ผ๋ง ์ด๋น 80MB/s ์ด์์ ์ฝ๊ธฐ/์ฐ๊ธฐ ์๋๊ฐ ํ๋ณด๋ฉ๋๋ค. Quad SPI PSRAM ๋ชจ๋ ์ฌ์ฉ ์์๋ 480x480 ์ด์์ ํด์๋์์ 30fps ๋ฌ์ฑ์ด ๊ตฌ์กฐ์ ์ผ๋ก ์ด๋ ค์ฐ๋ฏ๋ก ์ค๋ฒํด๋ก ๋ฐ ํํฐ์
๋ ๋๋ง ์กฐํฉ์ ์๊ฒฉํ ๊ฒํ ํด์ผ ํฉ๋๋ค.
3) LVGL ๋ ๋๋ง ์ต์ ์กฐ์ (lv_conf.h)
๋ถํ์ํ GPU/SW ์ฐ์ฐ ๋ถ๋ด์ ์ค์ด๊ธฐ ์ํ ์ฃผ์ lv_conf.h ๋งคํฌ๋ก ์ค์ ๊ฐ์
๋๋ค.
LV_COLOR_DEPTH 16: 16๋นํธ(RGB565) ์ปฌ๋ฌ ๋ชจ๋ ์ฌ์ฉ (๋ฉ๋ชจ๋ฆฌ ๋์ญํญ 33% ์ ๊ฐ)LV_DISP_DEF_REFR_PERIOD 16: ๋ฆฌํ๋ ์ ์ฃผ๊ธฐ๋ฅผ 16ms(์ฝ 60Hz)๋ก ์ค์ ํ์ฌ ๋ถํ์ํ ์ฐ์ฐ ๋ฐฉ์งLV_USE_SHADOW 0: ๋ ๋๋ง ์ฝ์คํธ๊ฐ ๋งค์ฐ ๋์ ์๋์ฐ(๊ทธ๋ฆผ์) ํจ๊ณผ ์ ํ
๊ฒฐ๋ก : ์ต์ ํ ๊ตฌ์กฐ ์ข ํฉ ๋ฐ ์ฑ๊ณผ ์ธก์
ESP32-S3 ๊ธฐ๋ฐ์ ๊ณ ํด์๋ ๋์คํ๋ ์ด ๊ฐ๋ฐ์์ ํ๋ ์ ๋๋กญ ๋ฌธ์ ๋ ๋จ์ํ MCU ์ฑ๋ฅ์ ํ๊ณ๊ฐ ์๋, ๋ฉ๋ชจ๋ฆฌ ์ํคํ ์ฒ ๋ฐ ๋์ญํญ ์ ์ด์ ๋ฌธ์ ์ ๋๋ค.
| ๊ตฌ๋ถ | ๊ธฐ์กด ๋ฐฉ์ (SRAM Partial Buffer) | ์ต์ ํ ๋ฐฉ์ (PSRAM Direct Mode + DMA) |
|---|---|---|
| ํ๊ท ํ๋ ์(FPS) | 12 ~ 18 FPS (์คํํฐ๋ง ๋ฐ์) | 45 ~ 60 FPS (๋งค์ฐ ๋ถ๋๋ฌ์) |
| CPU ์ฌ์ฉ๋ฅ | 85% ~ 98% (๋ฉ๋ชจ๋ฆฌ ๋ณต์ฌ ๋ณ๋ชฉ) | 25% ~ 40% (Zero-Copy ๋ฌ์ฑ) |
| ํฐ์ด๋ง(Tearing) | ํ๋ฉด ์ฐข์ด์ง ์์ฃผ ๋ฐ์ | ์๋ฒฝํ ์ ๊ฑฐ๋จ |
์ ๋ฆฌํ์๋ฉด, 1) PSRAM 80MHz OPI ํ์ฑํ, 2) LVGL Direct Mode ๊ธฐ๋ฐ์ Double Buffering ๊ตฌํ, 3) FreeRTOS Core 1 ์ ์ฉ ํ์คํฌ ํ ๋น ๋ฐ GDMA ๋น๋๊ธฐ ์ธํฐ๋ฝํธ ํต์ง ์์คํ ์ ๊ตฌ์ถํ๋ฉด ESP32-S3 ํ๊ฒฝ์์๋ ์์ฉ ์ ํ ์์ค์ ์ ๋ คํ๊ณ ์๋ฒฝํ GUI ์ฑ๋ฅ์ ์ด๋์ด๋ผ ์ ์์ต๋๋ค.