硬汉嵌入式论坛

 找回密码
 立即注册
查看: 1934|回复: 5
收起左侧

[LVGL] LVGL 8.4 使用 DMA2D 并开启LV_USE_GPU_STM32_DMA2D后报错

[复制链接]

15

主题

65

回帖

110

积分

初级会员

积分
110
发表于 2024-10-22 21:09:00 | 显示全部楼层 |阅读模式
本帖最后由 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文件增加了很多功能




回复

使用道具 举报

6

主题

153

回帖

171

积分

初级会员

积分
171
发表于 2024-10-23 08:39:55 | 显示全部楼层
应该是开启 LV_USE_GPU_STM32_DMA2D 后,lvgl 8.4内已经集成了DMA2D处理,disp_flush不要自己操作DMA2D
回复

使用道具 举报

15

主题

65

回帖

110

积分

初级会员

积分
110
 楼主| 发表于 2024-10-23 09:00:29 | 显示全部楼层
无关风月 发表于 2024-10-23 08:39
应该是开启 LV_USE_GPU_STM32_DMA2D 后,lvgl 8.4内已经集成了DMA2D处理,disp_flush不要自己操作DMA2D

那lv_disp_port这里的disp_flush该如何处理呢?直接跳出还是用软件memcpy?
回复

使用道具 举报

6

主题

153

回帖

171

积分

初级会员

积分
171
发表于 2024-10-23 09:24:29 | 显示全部楼层
Superusrss 发表于 2024-10-23 09:00
那lv_disp_port这里的disp_flush该如何处理呢?直接跳出还是用软件memcpy?

用软件cpy或者普通的dma
回复

使用道具 举报

15

主题

65

回帖

110

积分

初级会员

积分
110
 楼主| 发表于 2024-10-23 10:23:57 | 显示全部楼层
本帖最后由 Superusrss 于 2024-10-23 10:26 编辑
无关风月 发表于 2024-10-23 09:24
用软件cpy或者普通的dma

github 上有F7使用LVGL的,也开启了DMA2D, 使用DMA2D做flush,我这边没有F7,不知道能不能跑起来
https://github.com/tdjastrzebski/STM32F769I-DISCO-LVGL

这里例子中有这么一句
[C] 纯文本查看 复制代码
// while((DMA2D->CR & DMA2D_CR_START) != 0U); // wait for the previous transfer to finish

被注释掉了,不知道是不是这个原因
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117520
QQ
发表于 2024-10-23 10:29:26 | 显示全部楼层
这个我有用,开启后效果没什么区别,最大优势是节省CPU。

基于V5,V6和V7的LVGL模板,驱动支持单缓冲,双缓冲和配合硬件消隐的双缓冲,以及电容和电阻触摸全支持(2023-07-19)
https://forum.anfulai.cn/forum.php?mod=viewthread&tid=120161




回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-12 09:42 , Processed in 0.041469 second(s), 25 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表