本帖最后由 Superusrss 于 2024-10-22 21:19 编辑
使用LVGL8.4开启DMA2D加速后花屏并报错,芯片为stm32h750, 屏幕为RGB屏幕
若在lv_conf.h中使能如下片段
[C] 纯文本查看 复制代码 /*Use STM32's DMA2D (aka Chrom Art) GPU*/
#define LV_USE_GPU_STM32_DMA2D 1
#if LV_USE_GPU_STM32_DMA2D
/*Must be defined to include path of CMSIS header of target processor
e.g. "stm32f7xx.h" or "stm32f4xx.h"*/
#define LV_GPU_DMA2D_CMSIS_INCLUDE "stm32h7xx_hal.h"
#endif
串口报错如下,屏幕显示花屏
[C] 纯文本查看 复制代码 [Error] (5.894, +106) _lv_gpu_stm32_dma2d_await_dma_transfer_finish: DMA2D transfer error (in lv_gpu_stm32_dma2d.c line #652)
若使用DMA2D搬运但是不使能 LV_USE_GPU_STM32_DMA2D 就正常
主程序中有初始化DMA2D
[C] 纯文本查看 复制代码 void MX_DMA2D_Init(void)
{
/* USER CODE BEGIN DMA2D_Init 0 */
/* USER CODE END DMA2D_Init 0 */
/* USER CODE BEGIN DMA2D_Init 1 */
/* USER CODE END DMA2D_Init 1 */
hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_R2M;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB565;
hdma2d.Init.OutputOffset = 0;
if (HAL_DMA2D_Init(&hdma2d) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN DMA2D_Init 2 */
/* USER CODE END DMA2D_Init 2 */
}
void HAL_DMA2D_MspInit(DMA2D_HandleTypeDef* dma2dHandle)
{
if(dma2dHandle->Instance==DMA2D)
{
/* USER CODE BEGIN DMA2D_MspInit 0 */
/* USER CODE END DMA2D_MspInit 0 */
/* DMA2D clock enable */
__HAL_RCC_DMA2D_CLK_ENABLE();
/* DMA2D interrupt Init */
HAL_NVIC_SetPriority(DMA2D_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(DMA2D_IRQn);
/* USER CODE BEGIN DMA2D_MspInit 1 */
/* USER CODE END DMA2D_MspInit 1 */
}
}
然后我的lv_disp_port.c中是这么写的,这段代码没问题(不开启LV_USE_GPU_STM32_DMA2D的话)
[C] 纯文本查看 复制代码 uint16_t gram[480 * 282] __attribute__((section(".ARM.__at_0x24030000")));
static lv_disp_drv_t disp_drv; /*Descriptor of a display driver*/
extern DMA2D_HandleTypeDef hdma2d;
static void disp_flush(lv_disp_drv_t *disp_drv, const lv_area_t *area, lv_color_t *color_p);
static void FlushBufferComplete(DMA2D_HandleTypeDef *hdma2d)
{
lv_disp_flush_ready(&disp_drv);
}
void lv_port_disp_init(void)
{
/*Initialize the display*/
static lv_disp_draw_buf_t draw_buf_dsc_1;
ALIGN_32BYTES(__attribute__((section(".RAM_D1"))) static lv_color_t buf_1[MY_DISP_HOR_RES * 10]); /*A buffer for 10 rows*/
lv_disp_draw_buf_init(&draw_buf_dsc_1, buf_1, NULL, MY_DISP_HOR_RES * 10); /*Initialize the display buffer*/
lv_disp_drv_init(&disp_drv); /*Basic initialization*/
/*Set the resolution of the display*/
disp_drv.hor_res = MY_DISP_HOR_RES;
disp_drv.ver_res = MY_DISP_VER_RES;
/*Used to copy the buffer's content to the display*/
disp_drv.flush_cb = disp_flush;
/*Set a display buffer*/
disp_drv.draw_buf = &draw_buf_dsc_1;
disp_drv.sw_rotate = 1;
disp_drv.rotated = LV_DISP_ROT_180;
/*Finally register the driver*/
lv_disp_drv_register(&disp_drv);
/* link DMA2D handle to lv_disp_drv_t */
hdma2d.XferCpltCallback = FlushBufferComplete;
}
static void disp_flush(lv_disp_drv_t *drv, const lv_area_t *area, lv_color_t *buffer)
{
#if 1
lv_coord_t width = lv_area_get_width(area);
lv_coord_t height = lv_area_get_height(area);
#if !(LV_USE_GPU_STM32_DMA2D) || LV_COLOR_DEPTH == 16
// Not needed if dma2d is used - dma2d does not use L1 cache so cache does not need to be flushed.
// In 16B color mode is mixed (dma2d/non-dma2d) mode, hence buffer must be flushed
uint32_t bufferLength = width * height * 2;
SCB_CleanDCache_by_Addr((uint32_t *)buffer, bufferLength); // flush d-cache to SRAM before starting DMA transfer
#endif
// while((DMA2D->CR & DMA2D_CR_START) != 0U); // wait for the previous transfer to finish
#if LV_COLOR_DEPTH == 16
DMA2D->CR = 0x00U << DMA2D_CR_MODE_Pos; // Memory-to-memory
DMA2D->FGPFCCR = DMA2D_OUTPUT_RGB565;
#elif LV_COLOR_DEPTH == 32
DMA2D->CR = 0x0U << DMA2D_CR_MODE_Pos; // Memory-to-memory (FG fetch only)
DMA2D->FGPFCCR = DMA2D_INPUT_ARGB8888;
#else
#error "Only LV_COLOR_DEPTH 16 and 32 are supported"
#endif
DMA2D->FGMAR = (uint32_t)buffer;
DMA2D->FGOR = 0;
DMA2D->OPFCCR = DMA2D_OUTPUT_RGB565;
// DMA2D->OPFCCR |= (0x1U << DMA2D_OPFCCR_RBS_Pos); // emulate R/B color swap
DMA2D->OMAR = GRAM_BUFFER_ADDR + 2 * (area->y1 * MY_DISP_HOR_RES + area->x1);
DMA2D->OOR = MY_DISP_HOR_RES - width;
DMA2D->NLR = (width << DMA2D_NLR_PL_Pos) | (height << DMA2D_NLR_NL_Pos);
DMA2D->IFCR = 0x3FU; // trigger ISR flags reset
DMA2D->CR |= DMA2D_CR_TCIE; // enable transfer complete interrupt
DMA2D->CR |= DMA2D_CR_START;
}
卡这里好久了,还发现若使用lvgl 8.3.0就没有这个问题,8.4版本的lv_gpu_stm32_dma2d.c文件增加了很多功能
|