mirror of
https://github.com/lvgl/lvgl.git
synced 2026-05-23 07:46:36 +08:00
fix(LTDC): add cache cleaning (#9192)
Co-authored-by: cubic-dev-ai[bot] <191113872+cubic-dev-ai[bot]@users.noreply.github.com>
This commit is contained in:
@@ -65,8 +65,9 @@ LTDC layer to create the display for.
|
||||
|
||||
For the best visial results, ``optional_other_full_size_buffer`` should be used
|
||||
if enough memory is available. Single-buffered mode is what you should use
|
||||
if memory is very scarce. If there is almost enough memory for double-buffered
|
||||
direct mode, but not quite, then use partial render mode.
|
||||
if memory is very scarce. Chips with a CPU data cache have unavoidable visual
|
||||
artifacts when using single-buffered direct mode. If there is almost enough
|
||||
memory for double-buffered direct mode, but not quite, then use partial render mode.
|
||||
|
||||
To clarify what ``my_ltdc_framebuffer_address`` exactly is, it's the value of
|
||||
``pLayerCfg.FBStartAdress`` when the LTDC layer is configured using the STM32 HAL,
|
||||
@@ -118,6 +119,26 @@ the display width is 800, the display height is 480, and ``1K`` means 1024 bytes
|
||||
FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 4096K
|
||||
}
|
||||
|
||||
If the framebuffer is not reserved in the linker script or the framebuffer is not set during
|
||||
board initialization, you may absolutely set it at runtime before creating the LVGL display.
|
||||
|
||||
.. code-block:: c
|
||||
|
||||
/* like this */
|
||||
HAL_LTDC_SetAddress(&hltdc, (uint32_t)my_ltdc_framebuffer_address, my_ltdc_layer_index);
|
||||
|
||||
/* and then... */
|
||||
|
||||
lv_display_t * disp;
|
||||
disp = lv_st_ltdc_create_direct(my_ltdc_framebuffer_address,
|
||||
optional_other_full_size_buffer,
|
||||
my_ltdc_layer_index);
|
||||
/* or */
|
||||
disp = lv_st_ltdc_create_partial(partial_buf1,
|
||||
optional_partial_buf2,
|
||||
partial_buf_size,
|
||||
my_ltdc_layer_index);
|
||||
|
||||
|
||||
Display Rotation
|
||||
****************
|
||||
|
||||
@@ -49,6 +49,7 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
|
||||
static void flush_wait_cb(lv_display_t * disp);
|
||||
static lv_color_format_t get_lv_cf_from_layer_cf(uint32_t cf);
|
||||
static void reload_event_callback(LTDC_HandleTypeDef * hltdc);
|
||||
static void clean_dcache(void);
|
||||
|
||||
#if LV_ST_LTDC_USE_DMA2D_FLUSH
|
||||
static void transfer_complete_callback(DMA2D_HandleTypeDef * hdma2d);
|
||||
@@ -144,7 +145,15 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
|
||||
g_data.disp_flushed_in_flush_cb[layer_idx] = false;
|
||||
|
||||
if(disp->render_mode == LV_DISPLAY_RENDER_MODE_DIRECT) {
|
||||
if(lv_display_is_double_buffered(disp) && lv_display_flush_is_last(disp)) {
|
||||
bool flush_is_last = lv_display_flush_is_last(disp);
|
||||
if(flush_is_last) {
|
||||
/* there is no ideal time to clean the cache (if present)
|
||||
for **single-buffered** direct mode because the active buffer is drawn to
|
||||
while LTDC is scanning it. Clean it in the last flush, at least,
|
||||
but not every flush because it's expensive for not much visual improvement. */
|
||||
clean_dcache();
|
||||
}
|
||||
if(flush_is_last && lv_display_is_double_buffered(disp)) {
|
||||
HAL_LTDC_SetAddress_NoReload(&hltdc, (uint32_t)px_map, layer_idx);
|
||||
g_data.layer_interrupt_is_owned[layer_idx] = true;
|
||||
HAL_LTDC_Reload(&hltdc, LTDC_RELOAD_VERTICAL_BLANKING);
|
||||
@@ -172,6 +181,8 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
|
||||
lv_display_rotation_t rotation = lv_display_get_rotation(disp);
|
||||
if(rotation == LV_DISPLAY_ROTATION_0) {
|
||||
#if LV_ST_LTDC_USE_DMA2D_FLUSH
|
||||
clean_dcache();
|
||||
|
||||
uint32_t dma2d_input_cf = get_dma2d_input_cf_from_lv_cf(cf);
|
||||
uint32_t dma2d_output_cf = get_dma2d_output_cf_from_layer_cf(layer_cfg->PixelFormat);
|
||||
|
||||
@@ -194,12 +205,14 @@ static void flush_cb(lv_display_t * disp, const lv_area_t * area, uint8_t * px_m
|
||||
fb_p += fb_stride;
|
||||
px_map_p += area_stride;
|
||||
}
|
||||
clean_dcache();
|
||||
g_data.disp_flushed_in_flush_cb[layer_idx] = true;
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
uint32_t area_stride = px_size * area_width;
|
||||
lv_draw_sw_rotate(px_map, first_pixel, area_width, area_height, area_stride, fb_stride, rotation, cf);
|
||||
clean_dcache();
|
||||
g_data.disp_flushed_in_flush_cb[layer_idx] = true;
|
||||
}
|
||||
}
|
||||
@@ -242,6 +255,15 @@ static void reload_event_callback(LTDC_HandleTypeDef * hltdc)
|
||||
}
|
||||
}
|
||||
|
||||
static void clean_dcache(void)
|
||||
{
|
||||
#if defined(__CORTEX_M) && __CORTEX_M == 7
|
||||
SCB_CleanDCache();
|
||||
#elif defined(__CORTEX_A) && __CORTEX_A == 7
|
||||
L1C_CleanDCacheAll();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if LV_ST_LTDC_USE_DMA2D_FLUSH
|
||||
static void transfer_complete_callback(DMA2D_HandleTypeDef * hdma2d)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user