From 0d897136c9758cec6f22e1c7d2a8cc2eacc65183 Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 5 Jun 2020 11:10:11 +0100 Subject: [PATCH 1/6] Added LV_BLEND_BUF_ATTR as blend_buf MUST be in DMA accessible RAM --- src/lv_draw/lv_draw_blend.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lv_draw/lv_draw_blend.c b/src/lv_draw/lv_draw_blend.c index f87ca5733..ea446c765 100644 --- a/src/lv_draw/lv_draw_blend.c +++ b/src/lv_draw/lv_draw_blend.c @@ -338,7 +338,7 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co else { #if LV_USE_GPU if(disp->driver.gpu_blend_cb && lv_area_get_size(draw_area) > GPU_SIZE_LIMIT) { - static lv_color_t blend_buf[LV_HOR_RES_MAX]; + LV_BLEND_BUF_ATTR static lv_color_t blend_buf[LV_HOR_RES_MAX]; for(x = 0; x < draw_area_w ; x++) blend_buf[x].full = color.full; for(y = draw_area->y1; y <= draw_area->y2; y++) { @@ -352,7 +352,8 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co #if LV_USE_GPU_STM32_DMA2D if(lv_area_get_size(draw_area) >= 240) { - static lv_color_t blend_buf[LV_HOR_RES_MAX] = {0}; + /* blend_buf MUST be in DMA accessible RAM (depending on linker this isn't always the case - CCMRAM) */ + LV_BLEND_BUF_ATTR static lv_color_t blend_buf[LV_HOR_RES_MAX] = {0}; if(blend_buf[0].full != color.full) lv_color_fill(blend_buf, color, LV_HOR_RES_MAX); lv_coord_t line_h = LV_HOR_RES_MAX / draw_area_w; From cd9f34076e9c850accce52abf92a28df2db4afee Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 5 Jun 2020 11:10:51 +0100 Subject: [PATCH 2/6] Modified DMA2D fill, copy and blend functions to use direct register writes --- src/lv_gpu/lv_gpu_stm32_dma2d.c | 111 ++++++++++++++++---------------- src/lv_gpu/lv_gpu_stm32_dma2d.h | 6 ++ 2 files changed, 60 insertions(+), 57 deletions(-) diff --git a/src/lv_gpu/lv_gpu_stm32_dma2d.c b/src/lv_gpu/lv_gpu_stm32_dma2d.c index b1a52b1a3..a756e3af5 100644 --- a/src/lv_gpu/lv_gpu_stm32_dma2d.c +++ b/src/lv_gpu/lv_gpu_stm32_dma2d.c @@ -11,19 +11,14 @@ #if LV_USE_GPU_STM32_DMA2D -#if defined(STM32F4) - #include "stm32f4xx_hal.h" -#elif defined(STM32F7) - #include "stm32f7xx_hal.h" -#else - #error "Not supported STM32 family to use DMA2D" -#endif +#include "stm32f429xx.h" /********************* * DEFINES *********************/ #if LV_COLOR_16_SWAP + // TODO: F7 has red blue swap bit in control register for all layers and output #error "Can't use DMA2D with LV_COLOR_16_SWAP 1" #endif @@ -32,11 +27,9 @@ #endif #if LV_COLOR_DEPTH == 16 - #define DMA2D_OUTPUT_FORMAT DMA2D_OUTPUT_RGB565 - #define DMA2D_INPUT_FORMAT DMA2D_INPUT_RGB565 + #define DMA2D_COLOR_FORMAT DMA2D_RGB565 #elif LV_COLOR_DEPTH == 32 - #define DMA2D_OUTPUT_FORMAT DMA2D_OUTPUT_ARGB8888 - #define DMA2D_INPUT_FORMAT DMA2D_INPUT_ARGB8888 + #define DMA2D_COLOR_FORMAT DMA2D_ARGB8888 #else /*Can't use GPU with other formats*/ #endif @@ -54,7 +47,6 @@ static void dma2d_wait(void); /********************** * STATIC VARIABLES **********************/ -static DMA2D_HandleTypeDef hdma2d; /********************** * MACROS @@ -64,6 +56,18 @@ static DMA2D_HandleTypeDef hdma2d; * GLOBAL FUNCTIONS **********************/ +/** + * Turn on the peripheral and set output color mode, this only needs to be done once + */ +void lv_gpu_stm32_dma2d_init(void) +{ + /* Enable DMA2D clock */ + RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN; + + /* set output colour mode */ + DMA2D->OPFCCR = DMA2D_COLOR_FORMAT; +} + /** * Fill an area in the buffer with a color * @param buf a buffer which should be filled @@ -77,18 +81,16 @@ void lv_gpu_stm32_dma2d_fill(lv_color_t * buf, lv_coord_t buf_w, lv_color_t colo { invalidate_cache(); - hdma2d.Instance = DMA2D; - hdma2d.Init.Mode = DMA2D_R2M; - hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT; - hdma2d.Init.OutputOffset = buf_w - fill_w; - hdma2d.LayerCfg[1].InputAlpha = DMA2D_NO_MODIF_ALPHA; - hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_FORMAT; - hdma2d.LayerCfg[1].InputOffset = 0; + DMA2D->CR = 0x30000; + DMA2D->OMAR = (uint32_t)buf; + /* as input color mode is same as output we don't need to convert here do we? */ + DMA2D->OCOLR = color.full; + DMA2D->OOR = buf_w - fill_w; + DMA2D->NLR = (fill_w << DMA2D_NLR_PL_Pos) | (fill_h << DMA2D_NLR_NL_Pos); + + /* start transfer */ + DMA2D->CR |= DMA2D_CR_START_Msk; - /* DMA2D Initialization */ - HAL_DMA2D_Init(&hdma2d); - HAL_DMA2D_ConfigLayer(&hdma2d, 1); - HAL_DMA2D_Start(&hdma2d, (uint32_t)lv_color_to32(color), (uint32_t)buf, fill_w, fill_h); dma2d_wait(); } @@ -106,6 +108,7 @@ void lv_gpu_stm32_dma2d_fill(lv_color_t * buf, lv_coord_t buf_w, lv_color_t colo void lv_gpu_stm32_dma2d_fill_mask(lv_color_t * buf, lv_coord_t buf_w, lv_color_t color, const lv_opa_t * mask, lv_opa_t opa, lv_coord_t fill_w, lv_coord_t fill_h) { +#if 0 invalidate_cache(); /* Configure the DMA2D Mode, Color Mode and line output offset */ @@ -134,6 +137,7 @@ void lv_gpu_stm32_dma2d_fill_mask(lv_color_t * buf, lv_coord_t buf_w, lv_color_t HAL_DMA2D_ConfigLayer(&hdma2d, 1); HAL_DMA2D_BlendingStart(&hdma2d, (uint32_t) mask, (uint32_t) buf, (uint32_t)buf, fill_w, fill_h); dma2d_wait(); +#endif } /** @@ -151,22 +155,17 @@ void lv_gpu_stm32_dma2d_copy(lv_color_t * buf, lv_coord_t buf_w, const lv_color_ { invalidate_cache(); - hdma2d.Instance = DMA2D; - hdma2d.Init.Mode = DMA2D_M2M; - hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT; - hdma2d.Init.OutputOffset = buf_w - copy_w; + DMA2D->CR = 0; + /* copy output colour mode, this register controls both input and output colour format */ + DMA2D->FGPFCCR = DMA2D_COLOR_FORMAT; + DMA2D->FGMAR = (uint32_t)map; + DMA2D->FGOR = map_w - copy_w; + DMA2D->OMAR = (uint32_t)buf; + DMA2D->OOR = buf_w - copy_w; + DMA2D->NLR = (copy_w << DMA2D_NLR_PL_Pos) | (copy_h << DMA2D_NLR_NL_Pos); - /* Foreground layer */ - hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA; - hdma2d.LayerCfg[1].InputAlpha = 0xFF; - hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_FORMAT; - hdma2d.LayerCfg[1].InputOffset = map_w - copy_w; - - /* DMA2D Initialization */ - HAL_DMA2D_Init(&hdma2d); - HAL_DMA2D_ConfigLayer(&hdma2d, 0); - HAL_DMA2D_ConfigLayer(&hdma2d, 1); - HAL_DMA2D_Start(&hdma2d, (uint32_t)map, (uint32_t)buf, copy_w, copy_h); + /* start transfer */ + DMA2D->CR |= DMA2D_CR_START_Msk; dma2d_wait(); } @@ -185,28 +184,26 @@ void lv_gpu_stm32_dma2d_blend(lv_color_t * buf, lv_coord_t buf_w, const lv_color lv_coord_t map_w, lv_coord_t copy_w, lv_coord_t copy_h) { invalidate_cache(); + DMA2D->CR = 0x20000; - hdma2d.Instance = DMA2D; - hdma2d.Init.Mode = DMA2D_M2M_BLEND; - hdma2d.Init.ColorMode = DMA2D_OUTPUT_FORMAT; - hdma2d.Init.OutputOffset = buf_w - copy_w; + DMA2D->BGPFCCR = DMA2D_COLOR_FORMAT; + DMA2D->BGMAR = (uint32_t)buf; + DMA2D->BGOR = buf_w - copy_w; - /* Background layer */ - hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA; - hdma2d.LayerCfg[0].InputColorMode = DMA2D_INPUT_FORMAT; - hdma2d.LayerCfg[0].InputOffset = buf_w - copy_w; + DMA2D->FGPFCCR = (uint32_t)DMA2D_COLOR_FORMAT + /* alpha mode 2, replace with foreground * alpha value */ + | (2 << DMA2D_FGPFCCR_AM_Pos) + /* alpha value */ + | (opa << DMA2D_FGPFCCR_ALPHA_Pos); + DMA2D->FGMAR = (uint32_t)map; + DMA2D->FGOR = map_w - copy_w; - /* Foreground layer */ - hdma2d.LayerCfg[1].AlphaMode = DMA2D_COMBINE_ALPHA; - hdma2d.LayerCfg[1].InputAlpha = opa; - hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_FORMAT; - hdma2d.LayerCfg[1].InputOffset = map_w - copy_w; + DMA2D->OMAR = (uint32_t)buf; + DMA2D->OOR = buf_w - copy_w; + DMA2D->NLR = (copy_w << DMA2D_NLR_PL_Pos) | (copy_h << DMA2D_NLR_NL_Pos); - /* DMA2D Initialization */ - HAL_DMA2D_Init(&hdma2d); - HAL_DMA2D_ConfigLayer(&hdma2d, 0); - HAL_DMA2D_ConfigLayer(&hdma2d, 1); - HAL_DMA2D_BlendingStart(&hdma2d, (uint32_t)map, (uint32_t)buf, (uint32_t)buf, copy_w, copy_h); + /* start transfer */ + DMA2D->CR |= DMA2D_CR_START_Msk; dma2d_wait(); } @@ -226,7 +223,7 @@ static void invalidate_cache(void) static void dma2d_wait(void) { lv_disp_t * disp = _lv_refr_get_disp_refreshing(); - while(HAL_DMA2D_PollForTransfer(&hdma2d, 0) == HAL_TIMEOUT) { + while(DMA2D->CR & DMA2D_CR_START_Msk) { if(disp->driver.wait_cb) disp->driver.wait_cb(&disp->driver); } } diff --git a/src/lv_gpu/lv_gpu_stm32_dma2d.h b/src/lv_gpu/lv_gpu_stm32_dma2d.h index 9f757d8ff..52e4b2fe4 100644 --- a/src/lv_gpu/lv_gpu_stm32_dma2d.h +++ b/src/lv_gpu/lv_gpu_stm32_dma2d.h @@ -20,6 +20,12 @@ extern "C" { * DEFINES *********************/ +#define DMA2D_ARGB8888 0 +#define DMA2D_RGB888 1 +#define DMA2D_RGB565 2 +#define DMA2D_ARGB1555 3 +#define DMA2D_ARGB4444 4 + /********************** * TYPEDEFS **********************/ From bb5c6437fff58d11622fd68b4bc868ee2bc44c90 Mon Sep 17 00:00:00 2001 From: andrew Date: Fri, 5 Jun 2020 14:04:52 +0100 Subject: [PATCH 3/6] Added GPU init to lv_init Changed blend buffer attr to more general LV_DMA_ATTR Added define for CMSIS header Fixed bug with turning on peripheral clock --- src/lv_core/lv_obj.c | 9 +++++++++ src/lv_draw/lv_draw_blend.c | 4 ++-- src/lv_gpu/lv_gpu_stm32_dma2d.c | 5 ++++- src/lv_gpu/lv_gpu_stm32_dma2d.h | 5 +++++ 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/lv_core/lv_obj.c b/src/lv_core/lv_obj.c index fa0ad53ac..dbc630928 100644 --- a/src/lv_core/lv_obj.c +++ b/src/lv_core/lv_obj.c @@ -38,6 +38,10 @@ #include LV_THEME_DEFAULT_INCLUDE +#if LV_USE_GPU_STM32_DMA2D +#include "../lv_gpu/lv_gpu_stm32_dma2d.h" +#endif + /********************* * DEFINES *********************/ @@ -139,6 +143,11 @@ void lv_init(void) _lv_group_init(); #endif +#if LV_USE_GPU_STM32_DMA2D + /*Initialize DMA2D GPU*/ + lv_gpu_stm32_dma2d_init(); +#endif + _lv_ll_init(&LV_GC_ROOT(_lv_obj_style_trans_ll), sizeof(lv_style_trans_t)); _lv_ll_init(&LV_GC_ROOT(_lv_disp_ll), sizeof(lv_disp_t)); diff --git a/src/lv_draw/lv_draw_blend.c b/src/lv_draw/lv_draw_blend.c index ea446c765..3bdd7e0d7 100644 --- a/src/lv_draw/lv_draw_blend.c +++ b/src/lv_draw/lv_draw_blend.c @@ -338,7 +338,7 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co else { #if LV_USE_GPU if(disp->driver.gpu_blend_cb && lv_area_get_size(draw_area) > GPU_SIZE_LIMIT) { - LV_BLEND_BUF_ATTR static lv_color_t blend_buf[LV_HOR_RES_MAX]; + LV_DMA_ATTR static lv_color_t blend_buf[LV_HOR_RES_MAX]; for(x = 0; x < draw_area_w ; x++) blend_buf[x].full = color.full; for(y = draw_area->y1; y <= draw_area->y2; y++) { @@ -353,7 +353,7 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co #if LV_USE_GPU_STM32_DMA2D if(lv_area_get_size(draw_area) >= 240) { /* blend_buf MUST be in DMA accessible RAM (depending on linker this isn't always the case - CCMRAM) */ - LV_BLEND_BUF_ATTR static lv_color_t blend_buf[LV_HOR_RES_MAX] = {0}; + LV_DMA_ATTR static lv_color_t blend_buf[LV_HOR_RES_MAX] = {0}; if(blend_buf[0].full != color.full) lv_color_fill(blend_buf, color, LV_HOR_RES_MAX); lv_coord_t line_h = LV_HOR_RES_MAX / draw_area_w; diff --git a/src/lv_gpu/lv_gpu_stm32_dma2d.c b/src/lv_gpu/lv_gpu_stm32_dma2d.c index a756e3af5..7e7367331 100644 --- a/src/lv_gpu/lv_gpu_stm32_dma2d.c +++ b/src/lv_gpu/lv_gpu_stm32_dma2d.c @@ -11,7 +11,7 @@ #if LV_USE_GPU_STM32_DMA2D -#include "stm32f429xx.h" +#include LV_CPU_DMA2D_CMSIS_INCLUDE /********************* * DEFINES @@ -64,6 +64,9 @@ void lv_gpu_stm32_dma2d_init(void) /* Enable DMA2D clock */ RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN; + /* Delay after setting peripheral clock */ + volatile uint32_t temp = RCC->AHB1ENR; + /* set output colour mode */ DMA2D->OPFCCR = DMA2D_COLOR_FORMAT; } diff --git a/src/lv_gpu/lv_gpu_stm32_dma2d.h b/src/lv_gpu/lv_gpu_stm32_dma2d.h index 52e4b2fe4..035647199 100644 --- a/src/lv_gpu/lv_gpu_stm32_dma2d.h +++ b/src/lv_gpu/lv_gpu_stm32_dma2d.h @@ -34,6 +34,11 @@ extern "C" { * GLOBAL PROTOTYPES **********************/ +/** + * Turn on the peripheral and set output color mode, this only needs to be done once + */ +void lv_gpu_stm32_dma2d_init(void); + /** * Fill an area in the buffer with a color * @param buf a buffer which should be filled From 0867f72cb94b37607e93227c4cba5637d783561d Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 8 Jun 2020 08:40:50 +0100 Subject: [PATCH 4/6] Rename attribute define to match existing options style Moved static array declaration to top of file Added attribute define to template and checker headers --- lv_conf_template.h | 4 ++++ src/lv_conf_internal.h | 6 ++++++ src/lv_draw/lv_draw_blend.c | 7 ++++--- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index d6a9c4543..5335c3ef2 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -249,6 +249,10 @@ typedef void * lv_img_decoder_user_data_t; */ #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning +/* Prefix variables that are used in GPU accelerated operations, often these need to be + * placed in RAM sections that are DMA accessible */ +#define LV_ATTRIBUTE_DMA + /*=================== * HAL settings *==================*/ diff --git a/src/lv_conf_internal.h b/src/lv_conf_internal.h index 42cf547ba..08f3be42f 100644 --- a/src/lv_conf_internal.h +++ b/src/lv_conf_internal.h @@ -363,6 +363,12 @@ #define LV_EXPORT_CONST_INT(int_value) struct _silence_gcc_warning #endif +/* Prefix variables that are used in GPU accelerated operations, often these need to be + * placed in RAM sections that are DMA accessible */ +#ifndef LV_ATTRIBUTE_DMA +#define LV_ATTRIBUTE_DMA +#endif + /*=================== * HAL settings *==================*/ diff --git a/src/lv_draw/lv_draw_blend.c b/src/lv_draw/lv_draw_blend.c index 3bdd7e0d7..6a2bb1915 100644 --- a/src/lv_draw/lv_draw_blend.c +++ b/src/lv_draw/lv_draw_blend.c @@ -60,6 +60,10 @@ static inline lv_color_t color_blend_true_color_subtractive(lv_color_t fg, lv_co * STATIC VARIABLES **********************/ +#if LV_USE_GPU || LV_USE_GPU_STM32_DMA2D +LV_ATTRIBUTE_DMA static lv_color_t blend_buf[LV_HOR_RES_MAX]; +#endif + /********************** * MACROS **********************/ @@ -338,7 +342,6 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co else { #if LV_USE_GPU if(disp->driver.gpu_blend_cb && lv_area_get_size(draw_area) > GPU_SIZE_LIMIT) { - LV_DMA_ATTR static lv_color_t blend_buf[LV_HOR_RES_MAX]; for(x = 0; x < draw_area_w ; x++) blend_buf[x].full = color.full; for(y = draw_area->y1; y <= draw_area->y2; y++) { @@ -352,8 +355,6 @@ LV_ATTRIBUTE_FAST_MEM static void fill_normal(const lv_area_t * disp_area, lv_co #if LV_USE_GPU_STM32_DMA2D if(lv_area_get_size(draw_area) >= 240) { - /* blend_buf MUST be in DMA accessible RAM (depending on linker this isn't always the case - CCMRAM) */ - LV_DMA_ATTR static lv_color_t blend_buf[LV_HOR_RES_MAX] = {0}; if(blend_buf[0].full != color.full) lv_color_fill(blend_buf, color, LV_HOR_RES_MAX); lv_coord_t line_h = LV_HOR_RES_MAX / draw_area_w; From 3c70a1b5a2c4846ecd20d5dc2fb2a43a38718d11 Mon Sep 17 00:00:00 2001 From: andrew Date: Mon, 8 Jun 2020 18:36:30 +0100 Subject: [PATCH 5/6] Fixed typo in include define Added help in lv_conf_template.h --- lv_conf_template.h | 2 ++ src/lv_gpu/lv_gpu_stm32_dma2d.c | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index 5335c3ef2..c02b6a428 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -178,6 +178,8 @@ typedef void * lv_group_user_data_t; /* 1: Enable GPU interface*/ #define LV_USE_GPU 1 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */ #define LV_USE_GPU_STM32_DMA2D 0 +/*If enabling LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include path of CMSIS header of target processor */ +#define LV_GPU_DMA2D_CMSIS_INCLUDE /* 1: Enable file system (might be required for images */ #define LV_USE_FILESYSTEM 1 diff --git a/src/lv_gpu/lv_gpu_stm32_dma2d.c b/src/lv_gpu/lv_gpu_stm32_dma2d.c index 7e7367331..5d51b0920 100644 --- a/src/lv_gpu/lv_gpu_stm32_dma2d.c +++ b/src/lv_gpu/lv_gpu_stm32_dma2d.c @@ -11,7 +11,7 @@ #if LV_USE_GPU_STM32_DMA2D -#include LV_CPU_DMA2D_CMSIS_INCLUDE +#include LV_GPU_DMA2D_CMSIS_INCLUDE /********************* * DEFINES From 71e23c4e1394e43afb00dff02116735181323b76 Mon Sep 17 00:00:00 2001 From: microwavesafe Date: Tue, 9 Jun 2020 09:45:12 +0100 Subject: [PATCH 6/6] Added example include defines --- lv_conf_template.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lv_conf_template.h b/lv_conf_template.h index c02b6a428..b95000cac 100644 --- a/lv_conf_template.h +++ b/lv_conf_template.h @@ -178,7 +178,8 @@ typedef void * lv_group_user_data_t; /* 1: Enable GPU interface*/ #define LV_USE_GPU 1 /*Only enables `gpu_fill_cb` and `gpu_blend_cb` in the disp. drv- */ #define LV_USE_GPU_STM32_DMA2D 0 -/*If enabling LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include path of CMSIS header of target processor */ +/*If enabling LV_USE_GPU_STM32_DMA2D, LV_GPU_DMA2D_CMSIS_INCLUDE must be defined to include path of CMSIS header of target processor +e.g. "stm32f769xx.h" or "stm32f429xx.h" */ #define LV_GPU_DMA2D_CMSIS_INCLUDE /* 1: Enable file system (might be required for images */