Fix the STM32LTDC driver DMA2D accelerated bitblit on STM32F7 platforms.
This commit is contained in:
parent
cd4c389e48
commit
7ef1fa156c
@ -62,7 +62,7 @@ NOTE: Alpha support in RGB888 requies an alpha capable display (STM32LTDC 2nd d
|
|||||||
NOTE: Alpha support in RGB888 is NOT the standard ARGB8888 format. Only use AHTML2COLOR() and ARGB2COLOR() to create alpha colors.
|
NOTE: Alpha support in RGB888 is NOT the standard ARGB8888 format. Only use AHTML2COLOR() and ARGB2COLOR() to create alpha colors.
|
||||||
FEATURE: Added nullpointer checks to GDISP image functions (with new error code GDISP_IMAGE_ERR_NULLPOINTER)
|
FEATURE: Added nullpointer checks to GDISP image functions (with new error code GDISP_IMAGE_ERR_NULLPOINTER)
|
||||||
FIX: Add cache flushing to the ChibiOS FATFS/PETITFS block drivers. Needed for STM32F7 chips. This should really be in the ChibiOS DMA routines.
|
FIX: Add cache flushing to the ChibiOS FATFS/PETITFS block drivers. Needed for STM32F7 chips. This should really be in the ChibiOS DMA routines.
|
||||||
|
FIX: Add cache flushing to enable DMA2D accelerated bitblits in the STM32LTDC driver on the STM32F7 cpu.
|
||||||
|
|
||||||
*** Release 2.7 ***
|
*** Release 2.7 ***
|
||||||
FEATURE: Added EXC7200 driver
|
FEATURE: Added EXC7200 driver
|
||||||
|
@ -29,13 +29,22 @@
|
|||||||
#ifndef LTDC_NO_CLOCK_INIT
|
#ifndef LTDC_NO_CLOCK_INIT
|
||||||
#define LTDC_NO_CLOCK_INIT FALSE
|
#define LTDC_NO_CLOCK_INIT FALSE
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef LTDC_DMA_CACHE_FLUSH
|
||||||
|
#define LTDC_DMA_CACHE_FLUSH FALSE
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "stm32_ltdc.h"
|
#include "stm32_ltdc.h"
|
||||||
|
|
||||||
#if LTDC_USE_DMA2D
|
#if LTDC_USE_DMA2D
|
||||||
#include "stm32_dma2d.h"
|
#include "stm32_dma2d.h"
|
||||||
|
|
||||||
|
#if defined(STM32F7) || defined(STM32F746xx)
|
||||||
|
#undef LTDC_DMA_CACHE_FLUSH
|
||||||
|
#define LTDC_DMA_CACHE_FLUSH TRUE
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
typedef struct ltdcLayerConfig {
|
typedef struct ltdcLayerConfig {
|
||||||
// Frame
|
// Frame
|
||||||
LLDCOLOR_TYPE* frame; // Frame buffer address
|
LLDCOLOR_TYPE* frame; // Frame buffer address
|
||||||
@ -406,6 +415,15 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if LTDC_USE_DMA2D
|
#if LTDC_USE_DMA2D
|
||||||
|
#if LTDC_DMA_CACHE_FLUSH
|
||||||
|
#if defined(__CC_ARM)
|
||||||
|
#define __DSB() __dsb(0xF)
|
||||||
|
#else // GCC like
|
||||||
|
#define __DSB() __ASM volatile ("dsb 0xF":::"memory")
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
static void dma2d_init(void) {
|
static void dma2d_init(void) {
|
||||||
// Enable DMA2D clock
|
// Enable DMA2D clock
|
||||||
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;
|
RCC->AHB1ENR |= RCC_AHB1ENR_DMA2DEN;
|
||||||
@ -462,6 +480,27 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
|
|||||||
shape = (g->p.cx << 16) | (g->p.cy);
|
shape = (g->p.cx << 16) | (g->p.cy);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LTDC_DMA_CACHE_FLUSH
|
||||||
|
{
|
||||||
|
// This is slightly less than optimal as we flush the whole line in the source and destination image
|
||||||
|
// instead of just the cx portion but this saves us having to iterate over each line.
|
||||||
|
uint32_t f, e;
|
||||||
|
|
||||||
|
// Data memory barrier
|
||||||
|
__DSB();
|
||||||
|
|
||||||
|
// Flush then invalidate the destination area
|
||||||
|
e = pos + (g->p.cy > 1 ? ((uint32_t)((ltdcLayerConfig *)g->priv)->pitch*(shape & 0xFFFF)) : ((shape>>16)*LTDC_PIXELBYTES));
|
||||||
|
for(f=(pos & ~31); f < e; f += 32) {
|
||||||
|
SCB->DCCIMVAC = f;
|
||||||
|
SCB->DCIMVAC = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data memory barrier
|
||||||
|
__DSB();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Wait until DMA2D is ready
|
// Wait until DMA2D is ready
|
||||||
while(DMA2D->CR & DMA2D_CR_START);
|
while(DMA2D->CR & DMA2D_CR_START);
|
||||||
|
|
||||||
@ -501,15 +540,46 @@ LLDSPEC color_t gdisp_lld_get_pixel_color(GDisplay* g) {
|
|||||||
#if GDISP_HARDWARE_BITFILLS
|
#if GDISP_HARDWARE_BITFILLS
|
||||||
// Uses p.x,p.y p.cx,p.cy p.x1,p.y1 (=srcx,srcy) p.x2 (=srccx), p.ptr (=buffer)
|
// Uses p.x,p.y p.cx,p.cy p.x1,p.y1 (=srcx,srcy) p.x2 (=srccx), p.ptr (=buffer)
|
||||||
LLDSPEC void gdisp_lld_blit_area(GDisplay* g) {
|
LLDSPEC void gdisp_lld_blit_area(GDisplay* g) {
|
||||||
|
uint32_t srcstart, dststart;
|
||||||
|
|
||||||
|
srcstart = LTDC_PIXELBYTES * ((uint32_t)g->p.x2 * g->p.y1 * + g->p.x1) + (uint32_t)g->p.ptr;
|
||||||
|
dststart = (uint32_t)PIXEL_ADDR(g, PIXIL_POS(g, g->p.x, g->p.y));
|
||||||
|
|
||||||
|
#if LTDC_DMA_CACHE_FLUSH
|
||||||
|
{
|
||||||
|
// This is slightly less than optimal as we flush the whole line in the source and destination image
|
||||||
|
// instead of just the cx portion but this saves us having to iterate over each line.
|
||||||
|
uint32_t f, e;
|
||||||
|
|
||||||
|
// Data memory barrier
|
||||||
|
__DSB();
|
||||||
|
|
||||||
|
// Flush the source area
|
||||||
|
e = srcstart + (g->p.cy > 1 ? ((uint32_t)g->p.x2*g->p.cy) : (uint32_t)g->p.cx)*LTDC_PIXELBYTES;
|
||||||
|
for(f=(srcstart & ~31); f < e; f += 32)
|
||||||
|
SCB->DCCIMVAC = f;
|
||||||
|
|
||||||
|
// Flush then invalidate the destination area
|
||||||
|
e = dststart + (g->p.cy > 1 ? ((uint32_t)((ltdcLayerConfig *)g->priv)->pitch*g->p.cy) : ((uint32_t)g->p.cx*LTDC_PIXELBYTES));
|
||||||
|
for(f=(dststart & ~31); f < e; f += 32) {
|
||||||
|
SCB->DCCIMVAC = f;
|
||||||
|
SCB->DCIMVAC = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data memory barrier
|
||||||
|
__DSB();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Wait until DMA2D is ready
|
// Wait until DMA2D is ready
|
||||||
while(DMA2D->CR & DMA2D_CR_START);
|
while(DMA2D->CR & DMA2D_CR_START);
|
||||||
|
|
||||||
// Source setup
|
// Source setup
|
||||||
DMA2D->FGMAR = LTDC_PIXELBYTES * (g->p.y1 * g->p.x2 + g->p.x1) + (uint32_t)g->p.ptr;
|
DMA2D->FGMAR = srcstart;
|
||||||
DMA2D->FGOR = g->p.x2 - g->p.cx;
|
DMA2D->FGOR = g->p.x2 - g->p.cx;
|
||||||
|
|
||||||
// Output setup
|
// Output setup
|
||||||
DMA2D->OMAR = (uint32_t)PIXEL_ADDR(g, PIXIL_POS(g, g->p.x, g->p.y));
|
DMA2D->OMAR = dststart;
|
||||||
DMA2D->OOR = g->g.Width - g->p.cx;
|
DMA2D->OOR = g->g.Width - g->p.cx;
|
||||||
DMA2D->NLR = (g->p.cx << 16) | (g->p.cy);
|
DMA2D->NLR = (g->p.cx << 16) | (g->p.cy);
|
||||||
|
|
||||||
|
@ -42,12 +42,9 @@
|
|||||||
|
|
||||||
// Accelerated bitfills are also possible but only for GDISP_ROTATE_0
|
// Accelerated bitfills are also possible but only for GDISP_ROTATE_0
|
||||||
// and if no color translation is required (for now)
|
// and if no color translation is required (for now)
|
||||||
// Oops - this is not working and adds little performance benefit
|
#if !GDISP_NEED_CONTROL && !defined(GDISP_PIXELFORMAT)
|
||||||
// so we will just disable it for the near future.
|
#define GDISP_HARDWARE_BITFILLS TRUE
|
||||||
// #if !GDISP_NEED_CONTROL && !defined(GDISP_PIXELFORMAT)
|
#endif
|
||||||
// #define GDISP_HARDWARE_BITFILLS TRUE
|
|
||||||
// #endif
|
|
||||||
|
|
||||||
#endif /* GDISP_USE_DMA2D */
|
#endif /* GDISP_USE_DMA2D */
|
||||||
|
|
||||||
#endif /* GFX_USE_GDISP */
|
#endif /* GFX_USE_GDISP */
|
||||||
|
Loading…
Reference in New Issue
Block a user