2025-01-15 10:10 AM
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
Solved! Go to Solution.
2025-01-21 06:42 AM
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
2025-01-21 06:42 AM
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
2025-01-27 08:17 AM
2025-01-27 08:34 AM
Also here is contents of memory at locations in the registers (FGMAR and OMAR)
FGMAR is 3225354240 (0xC03F0000), OMAR is 3225518080 (0xC0418000)
Since this is configured as M2M, copying should go from FGMAR location (foreground layer) to output (OMAR), I think
I filled the memory with ones beforehand just to confirm that it is indeed writing zeroes instead of simply not copying data, that is why every value except the first is 0xFFFFFFFF
2025-01-27 12:11 PM
I have fixed it. For anyone else having the same problem, the CR register was set to 196608 (0x30000), which corresponds to the flag DMA2D_CR_MODE, which according to this this website corresponds to DMA2D_R2M or transfer from register to memory mode. Despite initializing DMA2D in M2M mode, I think that certain BSP_LCD_X functions override this mode themselves. Removing the DMA2D_CR_MODE flag from the CR register solved the problem. Thank you for your help!
hdma2d.Instance->CR &= ~DMA2D_CR_MODE;
@Flemming Gram CHRISTENSEN wrote:Please post a picture when it works!
I have attached the image and a video. For anyone interested, scaling with DMA like this takes ~30 milliseconds, scaling with a CPU takes ~200 milliseconds. Ultimately it is still not fast enough for 30 or 60 FPS, but it works on 20FPS so the game is now somewhat playable in full screen
2025-01-29 02:25 AM
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.