feat(mspi): split dma and mspi alignment

This commit is contained in:
Chen Jichang
2026-09-03 19:09:30 +08:00
committed by Chen Ji Chang
parent ef4387144e
commit 305d434bda
54 changed files with 668 additions and 420 deletions
@@ -95,9 +95,12 @@ extern void example_lvgl_demo_ui(lv_display_t *disp);
#if CONFIG_EXAMPLE_USE_DMA2D_COPY_FRAME
void example_rounder_flush_area_cb(lv_event_t * event)
{
// Under flash encryption, DMA2D access to PSRAM must satisfy MSPI encryption
// alignment (typically 16 bytes) for both the buffer address and transfer size.
// Round the LVGL invalidate area so the flush region width meets that requirement.
lv_area_t * area = lv_event_get_invalidated_area(event);
area->x1 = ALIGN_DOWN(area->x1, 16);
area->x2 = ALIGN_UP(area->x2, 16) - 1;
area->x2 = ALIGN_UP(area->x2 + 1, 16) - 1;
}
#endif
@@ -108,7 +111,7 @@ static void example_lvgl_flush_cb(lv_display_t *disp, const lv_area_t *area, uin
int offsetx2 = area->x2;
int offsety1 = area->y1;
int offsety2 = area->y2;
// pass the draw buffer to the driver
// LVGL area coordinates are inclusive; panel draw_bitmap expects [start, end).
esp_lcd_panel_draw_bitmap(panel_handle, offsetx1, offsety1, offsetx2 + 1, offsety2 + 1, px_map);
}
@@ -298,23 +301,14 @@ void app_main(void)
void *buf2 = NULL;
ESP_LOGI(TAG, "Allocate separate LVGL draw buffers");
size_t alignment = 1;
#if CONFIG_EXAMPLE_USE_DMA2D_COPY_FRAME
if (esp_efuse_is_flash_encryption_enabled()) {
alignment = SOC_GDMA_EXT_MEM_ENC_ALIGNMENT;
if (EXAMPLE_MIPI_DSI_LCD_H_RES % alignment != 0) {
ESP_LOGW(TAG, "EXAMPLE_MIPI_DSI_LCD_H_RES is not aligned to %d, may cause MSPI error", alignment);
}
}
#endif
size_t draw_buffer_sz = EXAMPLE_MIPI_DSI_LCD_H_RES * EXAMPLE_LVGL_DRAW_BUF_LINES * sizeof(lv_color_t);
// Note:
// Keep the display buffer in **internal** RAM can speed up the UI because LVGL uses it a lot and it should have a fast access time
// This example allocate the buffer from PSRAM mainly because we want to save the internal RAM
buf1 = heap_caps_aligned_calloc(alignment, 1, draw_buffer_sz, MALLOC_CAP_SPIRAM);
buf1 = heap_caps_aligned_calloc(16, 1, draw_buffer_sz, MALLOC_CAP_SPIRAM);
assert(buf1);
buf2 = heap_caps_aligned_calloc(alignment, 1, draw_buffer_sz, MALLOC_CAP_SPIRAM);
buf2 = heap_caps_aligned_calloc(16, 1, draw_buffer_sz, MALLOC_CAP_SPIRAM);
assert(buf2);
// initialize LVGL draw buffers
lv_display_set_buffers(display, buf1, buf2, draw_buffer_sz, LV_DISPLAY_RENDER_MODE_PARTIAL);
@@ -322,9 +316,13 @@ void app_main(void)
lv_display_set_flush_cb(display, example_lvgl_flush_cb);
#if CONFIG_EXAMPLE_USE_DMA2D_COPY_FRAME
// If flash encryption is enabled, DMA2D requires the flush buffer address and size to be aligned to 16 bytes.
// We need to round the flush area to the multiple of 16.
if (esp_efuse_is_flash_encryption_enabled()) {
// If Flash Encryption/ PSRAM ECC is enabled, DMA2D requires the flush buffer address and size to be aligned.
// Round the LVGL invalidate area accordingly (this is an LVGL integration hook, not a panel API).
bool need_rounder = esp_efuse_is_flash_encryption_enabled();
#if CONFIG_SPIRAM_ECC_ENABLE
need_rounder = true;
#endif
if (need_rounder) {
ESP_LOGI(TAG, "Register event callback for LVGL flush area rounding");
lv_display_add_event_cb(display, example_rounder_flush_area_cb, LV_EVENT_INVALIDATE_AREA, NULL);
}