Description
I’m making a simple custom TFT driver for F429 with dma2d only. But I’m getting a problem like this:
My functions to draw image, rectangles, fillscreen are working perfectly.
What MCU/Processor/Board and compiler are you using?
Custom STM32F429BIT6 with RGB888 (800x480) and SDRAM
What LVGL version are you using?
V8.0
What have you tried so far?
Change to internal/external RAM
Code to reproduce
My tft code is here
/**
* @file tft.c
*
*/
/*********************
* INCLUDES
*********************/
#include "lv_conf.h"
#include "lvgl/lvgl.h"
#include <string.h>
#include <stdlib.h>
#include "tft.h"
#include "stm32f4xx.h"
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p);
static lv_disp_drv_t display_drv; /*Descriptor of a display driver*/
void tft_init(void)
{
SDRAM_init(&hsdram1);
HAL_LTDC_SetAddress(&hltdc,(uint32_t) LCD_FRAME_BUFFER + BUFFER_OFFSET,0);
/*-----------------------------
* Create a buffer for drawing
*----------------------------*/
/* LittlevGL requires a buffer where it draws the objects. The buffer's has to be greater than 1 display row*/
#define SDRAM_START_ADDR ((uint32_t)0xD0000000)
#define FB_SIZE ((uint32_t)LV_HOR_RES_MAX * LV_VER_RES_MAX * 2)
/* Internal RAM */
#define valor 20
static lv_disp_buf_t disp_buf_2;
static lv_color_t buf2_1[LV_HOR_RES_MAX * valor]; /*A buffer for 10 rows*/
static lv_color_t buf2_2[LV_HOR_RES_MAX * valor]; /*An other buffer for 10 rows*/
lv_disp_buf_init(&disp_buf_2, buf2_1, buf2_2, LV_HOR_RES_MAX * valor); /*Initialize the display buffer*/
/* External RAM (SDRAM) */
// static lv_disp_buf_t disp_buf_2;
// static lv_color_t *buf2_1 = (lv_color_t *)(SDRAM_START_ADDR + FB_SIZE); /*A buffer for 10 rows*/
// static lv_color_t *buf2_2 = (lv_color_t *)(SDRAM_START_ADDR + FB_SIZE + (TFT_HOR_RES * 48)); /*A buffer for 10 rows*/
// lv_disp_buf_init(&disp_buf_2, buf2_1, buf2_2, LV_HOR_RES_MAX * 48); /*Initialize the display buffer*/
lv_disp_drv_init(&display_drv);
/*Set the resolution of the display*/
display_drv.hor_res = 800;
display_drv.ver_res = 480;
/*Used to copy the buffer's content to the display*/
display_drv.flush_cb = disp_flush;
/*Set a display buffer*/
display_drv.buffer = &disp_buf_2;
/*Finally register the driver*/
lv_disp_drv_register(&display_drv);
}
/**********************
* STATIC FUNCTIONS
**********************/
/* Flush the content of the internal buffer the specific area on the display
* You can use DMA or any hardware acceleration to do this operation in the background but
* 'lv_disp_flush_ready()' has to be called when finished. */
static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
DMA2D_DrawImage((uint32_t)color_p, area->x1, area->y1, (area->x2) - (area->x1), (area->y2) - (area->y1));
lv_disp_flush_ready(disp_drv);
}
FMC_SDRAM_CommandTypeDef command;
void SDRAM_init(SDRAM_HandleTypeDef *hsdram)
{
__IO uint32_t tmpr = 0;
command.CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
command.AutoRefreshNumber = 1;
command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(hsdram, &command, SDRAM_TIMEOUT);
HAL_Delay(10);
command.CommandMode = FMC_SDRAM_CMD_PALL;
command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
command.AutoRefreshNumber = 1;
command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(hsdram, &command, SDRAM_TIMEOUT);
HAL_Delay(10);
command.CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
command.AutoRefreshNumber = 4;
command.ModeRegisterDefinition = 0;
HAL_SDRAM_SendCommand(hsdram, &command, SDRAM_TIMEOUT);
HAL_Delay(10);
tmpr = (uint32_t) 0x01 | 0x00 | 0x30 | 0x00 | 0x200;
command.CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
command.CommandTarget = FMC_SDRAM_CMD_TARGET_BANK2;
command.AutoRefreshNumber = 1;
command.ModeRegisterDefinition = tmpr;
HAL_SDRAM_SendCommand(hsdram, &command, SDRAM_TIMEOUT);
HAL_Delay(10);
HAL_SDRAM_ProgramRefreshRate(hsdram, 1386);
}
void DMA2D_DrawImage(uint32_t data, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
{
//uint32_t destination = (LCD_FRAME_BUFFER + BUFFER_OFFSET) + (x + y * LV_HOR_RES_MAX) * 3;
hdma2d.Instance = DMA2D;
hdma2d.Init.Mode = DMA2D_M2M;
hdma2d.Init.ColorMode = DMA2D_OUTPUT_RGB888;
hdma2d.Init.OutputOffset = LV_HOR_RES_MAX - width;
// Foreground
hdma2d.LayerCfg[0].AlphaMode = DMA2D_NO_MODIF_ALPHA;
hdma2d.LayerCfg[0].InputColorMode = DMA2D_OUTPUT_RGB888;
hdma2d.LayerCfg[0].InputOffset = 0;//LV_HOR_RES_MAX - width;
hdma2d.LayerCfg[0].InputAlpha = 0x00;
HAL_DMA2D_Init(&hdma2d);
HAL_DMA2D_Start(&hdma2d, (uint32_t)data, (LCD_FRAME_BUFFER + BUFFER_OFFSET) + (x + y * LV_HOR_RES_MAX) * 3, width, height);
HAL_DMA2D_PollForTransfer(&hdma2d, 10);
}
void DMA2D_FillRect(uint32_t color, uint32_t x, uint32_t y, uint32_t width, uint32_t height)
{
hdma2d.Init.Mode = DMA2D_R2M;
hdma2d.Init.OutputOffset = LV_HOR_RES_MAX - width;
HAL_DMA2D_Init(&hdma2d);
HAL_DMA2D_Start(&hdma2d, color, (LCD_FRAME_BUFFER + BUFFER_OFFSET) + (x + y * LV_HOR_RES_MAX) * 3, width, height);
HAL_DMA2D_PollForTransfer(&hdma2d, 10);
}