Skip to main content
Associate
January 15, 2025
Solved

STM32F769I: DMA2D writes zeroes to memory instead of copying

  • January 15, 2025
  • 2 replies
  • 1875 views

I am making a game console on the aforementioned board. The game is loaded from an SD card and runs in user mode. As such I have a couple of system calls which allows the game to work properly. The game in question is already done, now I am just working on scaling it, since it operates on 256x160 resolution which is fairly small to see with naked eye. I would like to scale it to 768x480, or times 3 the original resolution. As such, I have this function which should scale the content using DMA2D. The code example is down below.

 

 

 

 

extern DMA2D_HandleTypeDef hdma2d;

void dma2d_scale_image(uint32_t src, uint32_t mid, uint32_t dst, uint32_t w, uint32_t h, uint8_t scaling_factor) {
	uint32_t dstW = w * scaling_factor, dstH = h * scaling_factor;

	/* columns */
	hdma2d.Instance->FGOR = w - 1;
	hdma2d.Instance->OOR = dstW - 1;
	for (int i=0; i<dstW; i++) {
		volatile uint32_t s = src + (i/scaling_factor) * 4;
		HAL_StatusTypeDef status = HAL_DMA2D_Start(&hdma2d, s, mid + i * 4, 1, h);
		HAL_DMA2D_PollForTransfer(&hdma2d, 0xFFFFFFFF);
	}
	/* rows */
	hdma2d.Instance->FGOR = 0;
	hdma2d.Instance->OOR = dstW * (scaling_factor - 1);
	for (int i=0; i<scaling_factor; i++) {
		HAL_DMA2D_Start(&hdma2d, mid, dst + (dstW * i * 4), dstW, h);
		HAL_DMA2D_PollForTransfer(&hdma2d, 0xFFFFFFFF);
	}
}

 

 

 

The scaling code using DMA2D is much faster than doing it through code directly, about 2.5x faster. It also uses a "mid" buffer to store partial scaling results, without corrupting the image in question.

 

I have tested this code on constant 2d array data and it worked fine. However, when using it inside the actual game, the DMA2D wrote zeroes to the target framebuffer instead of scaling the image. I have tried moving addresses around and initializing the framebuffer to 0xFF bytes to make sure it is actually writing and it really does appear like it is writing zeroes no matter the source. I tried disabling dcache, since I heard it can cause problems, but that didn't seem to help, unless I did it wrong. All of this is happening inside SDRAM, so memory region from 0xC0000000 to 0xC1000000. Since both the framebuffer, the mid buffer and the actual game are stored inside SDRAM. When I tested it however, I was took constant data, which I assume is written in flash and scaled it to RAM, and the mid buffer was also in RAM.

 

Does anyone know why this discrepancy happens and how I could go about fixing it? Thanks

Best answer by Flemming Gram CHRISTENSEN

Hello Markoz

Interesting. Please post a picture when it works!

Could you step into the HAL_DMA2D_Start function until just after the Start bit in CR register is set.

Then take a picture of the DMA2D registers (in CubeIDE or similar) and post it here.

We should check for errors.

Regards

 

2 replies

Flemming Gram CHRISTENSEN
ST Employee
January 21, 2025

Hello Markoz

Interesting. Please post a picture when it works!

Could you step into the HAL_DMA2D_Start function until just after the Start bit in CR register is set.

Then take a picture of the DMA2D registers (in CubeIDE or similar) and post it here.

We should check for errors.

Regards

 

markozzAuthor
Associate
January 27, 2025

Hello, sorry for late reply. I used step until I reached the expression after __HAL_DMA2D_ENABLE, which sets the CR register bit.

 

Flemming Gram CHRISTENSEN
ST Employee
January 29, 2025

Very nice. I think I recognize the game...

Can you fit the original buffer in SRAM?

Otherwise, try to put the final buffer in a separate SDRAM bank. Can help.

 

markozzAuthor
Associate
February 3, 2025

The original buffer can fit into SRAM, but the initial buffer and mid buffer together sadly cannot. I will give it a try with the original (source) buffer only, thanks!