From e21f5f8c1f9050b407ac4fabd25156411995a739 Mon Sep 17 00:00:00 2001 From: Stanislav N Mikhailov Date: Fri, 27 Mar 2026 22:27:44 +0300 Subject: [PATCH] display: simplify safe buffer contract and update Thermometr example --- Examples/Thermometr/src/main.c | 11 +++++------ include/display/display.h | 23 +++++++++++++++++------ src/core/display.c | 29 ++++++++++++++++++++++++++--- 3 files changed, 48 insertions(+), 15 deletions(-) diff --git a/Examples/Thermometr/src/main.c b/Examples/Thermometr/src/main.c index 3e883c2..4e4fcd1 100644 --- a/Examples/Thermometr/src/main.c +++ b/Examples/Thermometr/src/main.c @@ -109,12 +109,11 @@ int main() } frame_tick_due = false; // Сбрасываем флаг и разрешаем обработать ровно один кадр на этот тик. - if (!display_ready()) // Если прошлый кадр все еще передается DMA на дисплей. - { - continue; // Пропускаем этот кадр, не накапливая задержку. - } - - uint16_t* buf = display_get_draw_buffer(); // Получаем буфер, в который разрешено рисовать текущий кадр. + uint16_t* buf = display_try_acquire_draw_buffer(); // Пытаемся неблокирующе получить draw-буфер. + if (buf == NULL) // Если в SAFE+1 DMA еще занят, просто пропускаем тик кадра. + { + continue; + } render_begin(&rc, buf, WIDTH, HEIGHT); // Привязываем контекст рендера к буферу и размерам экрана. render_clear(&rc, RGB16(9,19,9)); // Очищаем кадр темно-зеленым фоном. diff --git a/include/display/display.h b/include/display/display.h index 0972a6d..776a2a0 100644 --- a/include/display/display.h +++ b/include/display/display.h @@ -100,13 +100,24 @@ void display_init(const display_config_t* cfg); ============================================================ */ /* - * Буфер для рисования. + * Неблокирующая попытка получить буфер для рисования. * - * SAFE + 1 буфер: - * может блокировать пока DMA активен. - * - * RAW: - * никогда не блокирует. + * Возвращает NULL если буфер сейчас недоступен + * (например, SAFE + 1 буфер и DMA активен). + */ +uint16_t* display_try_acquire_draw_buffer(void); + + +/* + * Блокирующее получение буфера для рисования. + */ +uint16_t* display_acquire_draw_buffer_blocking(void); + + +/* + * Совместимость со старым API. + * Начиная с текущей версии работает как non-blocking alias: + * эквивалентно display_try_acquire_draw_buffer(). */ uint16_t* display_get_draw_buffer(void); diff --git a/src/core/display.c b/src/core/display.c index ed57d98..49f0193 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -286,14 +286,14 @@ void display_init(const display_config_t* cfg) /* ------------------------------------------------------------ */ -uint16_t* display_get_draw_buffer(void) +uint16_t* display_try_acquire_draw_buffer(void) { if (ctx.mode == DISPLAY_MODE_SAFE && ctx.buffer_count == 1) { - while (ctx.dma_busy) + if (ctx.dma_busy) { - /* активное ожидание */ + return NULL; } } @@ -301,6 +301,29 @@ uint16_t* display_get_draw_buffer(void) } +/* ------------------------------------------------------------ */ + +uint16_t* display_acquire_draw_buffer_blocking(void) +{ + uint16_t* buf = NULL; + + while (buf == NULL) + { + buf = display_try_acquire_draw_buffer(); + } + + return buf; +} + + +/* ------------------------------------------------------------ */ + +uint16_t* display_get_draw_buffer(void) +{ + return display_try_acquire_draw_buffer(); +} + + /* ------------------------------------------------------------ */ uint16_t* display_get_scanout_buffer(void)