Description
my LVGL official demo lv_demo_widgets() could display the first frame picture ONLY!
What MCU/Processor/Board and compiler are you using?
STM32H743IIT6 Keil-MDK compiler-v6.15
I have adapted the LTDC of stm32h743 successfully and verified OK.
I merged the LVGL 9.2.0 into my bare-metal
What do you want to achieve?
get the LVGL official demo work well in my board
What have you tried so far?
i have located the problem code but cannot get further.
the problem code is in “static void refr_invalid_areas(void)” >>> “if(disp_refr->inv_p == 0) return;”
Code to reproduce
Add the relevant code snippets here.
The code block(s) should be between ```c
and ```
tags:
/*You code here*/
/*Copy this file as "lv_port_disp.c" and set this value to "1" to enable content*/
#if 1 /* maple: LVGL 移植:lv_port_disp_templ.c:打开头文件设置1 */
/*********************
* INCLUDES
*********************/
#include "lv_port_lcd_stm32.h"
#include <stdbool.h>
#include "main.h"
#include "ST7262E43.h"
//#include "gImage_448x300.h" //ltdc_test
//#include "RGB565_320x240.h" //ltdc_test
//#include "192x50.h" //ltdc_test
#include "sdram_fb.h"
/*********************
* DEFINES
*********************/
#ifndef MY_DISP_HOR_RES
#warning Please define or replace the macro MY_DISP_HOR_RES with the actual screen width, default value 320 is used for now.
#define MY_DISP_HOR_RES 320
#endif
#ifndef MY_DISP_VER_RES
#warning Please define or replace the macro MY_DISP_VER_RES with the actual screen height, default value 240 is used for now.
#define MY_DISP_VER_RES 240
#endif
#define BYTE_PER_PIXEL (LV_COLOR_FORMAT_GET_SIZE(LV_COLOR_FORMAT_RGB888))
#define FRAME_BUFFER_DYNAMIC
/**********************
* LTDC 配置
**********************/
LTDC_HandleTypeDef hltdc;
DMA2D_HandleTypeDef hdma2d;
//-------- ltdc_test ----------
//__IO uint32_t ReloadFlag = 0;
//uint32_t LineEventNumber = 330;
//void ltdc_test(uint8_t test_mode);
//-------- ltdc_test ----------
/**********************
* STATIC PROTOTYPES
**********************/
static void MX_LTDC_Init(void);
static void MX_DMA2D_Init(void);
static void disp_init(void);
static void disp_flush(lv_display_t * disp, const lv_area_t * area, uint8_t * px_map);
/**********************
* STATIC VARIABLES
**********************/
#ifndef FRAME_BUFFER_DYNAMIC
LV_ATTRIBUTE_MEM_ALIGN // 在SRAM1/2 上分配渲染帧缓存区
__attribute__((section(".RAM_D1"))) static uint8_t buf_2_1[MY_DISP_HOR_RES * MY_DISP_DEPTH * BYTE_PER_PIXEL];
LV_ATTRIBUTE_MEM_ALIGN // 在AXI-SRAM上分配显示帧缓存区
__attribute__((section(".RAM_D2"))) static uint8_t buf_2_2[MY_DISP_HOR_RES * MY_DISP_DEPTH * BYTE_PER_PIXEL];
#else
static uint8_t* buf_2_1 = NULL;
static uint8_t* buf_2_2 = NULL;
#endif
static lv_display_t * disp = NULL;
/**********************
* MACROS
**********************/
/**********************
* GLOBAL FUNCTIONS
**********************/
void lv_port_disp_init(void)
{
disp_init(); //LTDC and DMA2D Init
disp = lv_display_create(MY_DISP_HOR_RES, MY_DISP_VER_RES);
lv_display_set_flush_cb(disp, disp_flush);
#ifndef FRAME_BUFFER_DYNAMIC
lv_display_set_buffers(disp, buf_2_1, buf_2_2, sizeof(buf_2_1), LV_DISPLAY_RENDER_MODE_PARTIAL);
#else
//注意:这里是缓冲区深度,而不是屏幕深度,只有全帧缓冲时,缓冲区深度才等于屏幕高度。
buf_2_1 = (uint8_t*) sdram_alloc_fb(MY_DISP_HOR_RES, MY_DISP_DEPTH, BYTE_PER_PIXEL);
buf_2_2 = (uint8_t*) sdram_alloc_fb(MY_DISP_HOR_RES, MY_DISP_DEPTH, BYTE_PER_PIXEL);
lv_display_set_buffers(disp, buf_2_1, buf_2_2,
(MY_DISP_HOR_RES * MY_DISP_DEPTH * BYTE_PER_PIXEL),
LV_DISPLAY_RENDER_MODE_PARTIAL);
// attention: when SDRAM lvgl buffer mode used, must REFRESH the real display buffer address!!!
HAL_LTDC_SetAddress_NoReload(&hltdc, (uint32_t)buf_2_2, LTDC_LAYER_1);
#endif
//attach optional call backs
lv_tick_set_cb(HAL_GetTick);
lv_delay_set_cb(HAL_Delay);
}
/**********************
* STATIC FUNCTIONS
**********************/
/*Initialize your display and the required peripherals.*/
static void disp_init(void)
{
/*You code here*/
MX_DMA2D_Init(); //must after SDRAM Init
MX_LTDC_Init();
}
volatile bool disp_flush_enabled = true;
/* Enable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_enable_update(void)
{
disp_flush_enabled = true;
}
/* Disable updating the screen (the flushing process) when disp_flush() is called by LVGL
*/
void disp_disable_update(void)
{
disp_flush_enabled = false;
}
/*Flush the content of the internal buffer the specific area on the display.
*`px_map` contains the rendered image as raw pixel map and it should be copied to `area` on the display.
*You can use DMA or any hardware acceleration to do this operation in the background but
*'lv_display_flush_ready()' has to be called when it's finished.*/
static void disp_flush(lv_display_t * disp_drv, const lv_area_t * area, uint8_t * px_map)
{
// resize the display frame factors
int32_t width = area->x2 - area->x1 + 1;
int32_t height = area->y2 - area->y1 + 1;
// IMPORTANT: 确保 DMA 获取的像素数据 = CPU 最新渲染数据 → 图片清晰度提升
// Attention: MUST get the two lines below configured! or messy display outcome!
SCB_CleanInvalidateDCache(); // 强制同步缓存与内存
SCB_InvalidateICache(); // 确保执行渲染代码最新版
// 配置DMA2D传输
HAL_DMA2D_Start_IT(&hdma2d,
(uint32_t)px_map, //DMA2D搬运的起始地址:LVGL需要显示帧的起始地址
(uint32_t)buf_2_2, //DMA2D搬运的目的地址:交接给LTDC的固定地址
width, height);
// 设置LTDC显示窗口
HAL_LTDC_SetWindowPosition_NoReload(&hltdc, area->x1, area->y1, LTDC_LAYER_1);
HAL_LTDC_SetWindowSize_NoReload(&hltdc, width, height, LTDC_LAYER_1);
/*IMPORTANT!!!
*Inform the graphics library that you are ready with the flushing */
//lv_display_flush_ready(disp_drv); // 在中断中完成图像显示的剩余操作
printf("#### LVGL disp_flush\n");
}
// LTDC重载中断回调函数
void HAL_LTDC_ReloadEventCallback(LTDC_HandleTypeDef *hltdc)
{
lv_display_flush_ready(disp);
printf("---- LTDC: Reload Finished onece more.\n");
}
// DMA2D传输完成中断回调
void HAL_DMA2D_TransferCpltCallback(DMA2D_HandleTypeDef *hdma2d)
{
// 配置垂直消隐期重载准备开始显示
HAL_LTDC_Reload(&hltdc, LTDC_RELOAD_VERTICAL_BLANKING);
// 在LTDC重载回调中继续处理
}
//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
int main(void)
{
/* 1. 基础模块配置 */
MPU_Config();
CPU_CACHE_Enable();
HAL_Init();
SystemClock_Config();
/* 2. 应用模块配置 */
MX_GPIO_Init();
MX_LPUART1_UART_Init();
SDRAM_Init();
//-----------LVGL-------------------
lv_init(); //lvgl core
lv_port_disp_init(); //lvgl display
//lv_port_indev_init(); //lvgl touch
/* lvgl demo */
lv_demo_widgets(); //LV_USE_DEMO_WIDGETS
//lv_demo_music(); //LV_USE_DEMO_MUSIC
//lv_demo_benchmark();
printf("initialization finished!\n");
while (1){
lv_timer_handler();
HAL_Delay(5);
}
}