2023-01-12 09:29 AM
I am using FMC LCD interface to power my TFT LCD controlled by SSD1963. FMC data width is 16-bit, and below is a workable code using pixel-by-pixel transmission.
void lcd_fill_pixels(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey,
uint16_t *pixels)
{
uint16_t xlen = ex - sx + 1;
Set_Column(sx, ex);
Set_Page(sy, ey);
SSD1963__write_memory_start();
for (int i = sy; i <= ey; i++) {
for (int j = sx; j <= ex; j++) {
TFT_RAM = *pixels;
pixels++;
}
}
}
I want to convert the code in the lines 8-13 into DMA. I first tried to use MDMA since the core running on is Cortex-M7. I also tried DMA MemToMem. below is my MDMA and DMA configuration.
I checked from the build analyzer that the buffer is placed in the .bss region of RAM_D1. Also, I disable both D-Cache and I-Cache for testing. However, I still cannot see my LCD filling with pixels.
Could someone familiar with DMA on STM32H7 devices help me with it? Really appreciate it! Below is my attempt using HAL.
void lcd_fill_pixels_dma(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey,
uint16_t *pixels)
{
uint16_t xlen = ex - sx + 1;
uint16_t ylen = ey - sy + 1;
Set_Column(sx, ex);
Set_Page(sy, ey);
SSD1963__write_memory_start();
extern DMA_HandleTypeDef hdma_memtomem_dma1_stream7;
SCB_CleanInvalidateDCache();
HAL_DMA_Start(&hdma_memtomem_dma1_stream7, (uintptr_t)pixels,
(uintptr_t)&TFT_RAM, xlen * ylen * 2);
HAL_DMA_PollForTransfer(&hdma_memtomem_dma1_stream7, HAL_DMA_FULL_TRANSFER,
100);
}
void lcd_fill_pixels_mdma(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey,
uint16_t *pixels)
{
uint16_t xlen = ex - sx + 1;
uint16_t ylen = ey - sy + 1;
Set_Column(sx, ex);
Set_Page(sy, ey);
SSD1963__write_memory_start();
extern MDMA_HandleTypeDef hmdma_mdma_channel41_sw_0;
SCB_CleanInvalidateDCache();
HAL_MDMA_Start(&hmdma_mdma_channel41_sw_0, (uintptr_t)pixels,
(uintptr_t)&TFT_RAM, xlen * ylen * 2, 1);
HAL_MDMA_PollForTransfer(&hmdma_mdma_channel41_sw_0, HAL_MDMA_FULL_TRANSFER,
100);
}
Solved! Go to Solution.
2023-01-12 10:03 AM
It seems that I find out the solution by myself. Somehow in HAL_MDMA_Start, I cannot transmit data of more than 65535 bytes, even though the parameter BlockDataLength is defined in uint32_t.
Below is my workable code using MDMA with D-Cache and I-Cache enabled
void lcd_fill_pixels_mdma(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey,
uint16_t *pixels)
{
uint32_t xlen = ex - sx + 1;
uint32_t ylen = ey - sy + 1;
Set_Column(sx, ex);
Set_Page(sy, ey);
SSD1963__write_memory_start();
extern MDMA_HandleTypeDef hmdma_mdma_channel40_sw_0;
SCB_CleanInvalidateDCache();
for (int i = 0; i < ylen; i++) {
HAL_MDMA_Start(&hmdma_mdma_channel40_sw_0, (uintptr_t)pixels,
(uintptr_t)&TFT_RAM, xlen * 2, 1);
HAL_MDMA_PollForTransfer(&hmdma_mdma_channel40_sw_0, HAL_MDMA_FULL_TRANSFER,
100);
pixels += xlen;
}
}
2023-01-12 10:03 AM
It seems that I find out the solution by myself. Somehow in HAL_MDMA_Start, I cannot transmit data of more than 65535 bytes, even though the parameter BlockDataLength is defined in uint32_t.
Below is my workable code using MDMA with D-Cache and I-Cache enabled
void lcd_fill_pixels_mdma(uint16_t sx, uint16_t sy, uint16_t ex, uint16_t ey,
uint16_t *pixels)
{
uint32_t xlen = ex - sx + 1;
uint32_t ylen = ey - sy + 1;
Set_Column(sx, ex);
Set_Page(sy, ey);
SSD1963__write_memory_start();
extern MDMA_HandleTypeDef hmdma_mdma_channel40_sw_0;
SCB_CleanInvalidateDCache();
for (int i = 0; i < ylen; i++) {
HAL_MDMA_Start(&hmdma_mdma_channel40_sw_0, (uintptr_t)pixels,
(uintptr_t)&TFT_RAM, xlen * 2, 1);
HAL_MDMA_PollForTransfer(&hmdma_mdma_channel40_sw_0, HAL_MDMA_FULL_TRANSFER,
100);
pixels += xlen;
}
}
2023-01-13 01:11 AM
Hello @TKuo.1 ,
Indeed, the programmable number of data to be transferred via DMA is 0 to 2^16 - 1
Thank you for your contribution!
To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.
2023-06-20 12:58 PM
@TKuo.1 which address line did you use as your register select for the LCD? I'm using A0 and having a lot of issues getting it working with 16 bit data width