cancel
Showing results for 
Search instead for 
Did you mean: 

Bare metal DMA2D

DCarr.1
Senior

Hello all

I have a custom STM32L496RGTx-based board onto which I'm migrating a legacy rendering engine. I'd really like to accelerate text rendering and I'm looking into DMA2D for a4 format font data.

I have a little test setup which attempts to populate a buffer from supplied a4 test data like this:

static void draw_a4(const uint8_t* a4) { 
	uint16_t w=24;
	uint16_t h=24;
 
	uint16_t buf[w * h];  // rgb565 raster buffer
	uint32_t back = (uint32_t)&buf;
	uint32_t data = (uint32_t)a4;
 
    __HAL_RCC_DMA2D_CLK_ENABLE();
 
	/* constant bg configuration */
 
	DMA2D->BGPFCCR = 	(DMA2D->BGPFCCR & 0x00fc00c0) |					/* DMA2D Background PFC Control Register reserved bits */
						(0b11111111 << 24) |							/* alpha value (0xff) */
						(0 << 16) |										/* alpha mode */
						(0 << 8) |										/* clut size */
						(0 << 5 ) |										/* start clut loading */
						(0 << 4) |										/* clut color mode */
						(0b1010 << 0);									/* color mode argb8888 */
	DMA2D->BGCOLR = 0xff00ffff;											/* DMA2D Background Color Register */
	DMA2D->BGMAR = 0;													/* DMA2D Background Memory Address Register  */
	DMA2D->BGOR = 0;          											/* DMA2D Background Offset Register */
 
	/* constant fg configuration */
 
	DMA2D->FGPFCCR = 	(DMA2D->FGPFCCR & 0x00fc00c0) |					/* DMA2D Foreground PFC Control Register */
						(0b11111111 << 24) |							/* alpha value  */
						(0 << 16) |										/* alpha mode */
						(0 << 8) |										/* clut size */
						(0 << 5 ) |										/* start clut loading */
						(0 << 4) |										/* clut color mode */
						(0b1010 << 0);									/* color mode a4 */
	DMA2D->FGCOLR = 0xffffff00;											/* DMA2D Foreground Color Register */
	DMA2D->FGMAR = data;												/* DMA2D Foreground Memory Address Register */
	DMA2D->FGOR = 0;          											/* DMA2D Foreground Offset Register */
 
	/* output configuration */
 
	DMA2D->OPFCCR = (DMA2D->OPFCCR & 0xfffffff8) | (0b010 << 0);		/* DMA2D output PFC control register (rgb565) */
	DMA2D->OOR = 0;       												/* DMA2D Output Offset Register */
	DMA2D->OMAR = back;													/* output buffer */
	DMA2D->NLR = 	(DMA2D->NLR & 0xc0000000) |							/* DMA2D Number of Line Register */
					(w << 16) |											/* number of pixels per line */
					(h);												/* Number of lines */
	DMA2D->CR = (DMA2D->CR & 0xfffcc0f8) |								/* DMA2D control register */
				(0b10 << 16) |											/* mode (FG and BG fetch with PFC and blending) */
				(0 << 13) |												/* Configuration Error Interrupt Enable */
				(0 << 12) |												/* CLUT transfer complete interrupt enable */
				(0 << 11) |												/* CLUT access error interrupt enable */
				(0 << 10) |												/* Transfer watermark interrupt enable */
				(0 << 9) |												/* Transfer complete interrupt enable */
				(0 << 8) |												/* Transfer error interrupt enable */
				(0 << 2) |												/* abort */
				(0 << 1) |												/* suspend */
				(0 << 0);												/* transfer */
 
	DMA2D->CR = DMA2D->CR | DMA2D_CR_START;								/* set start bit to start the transfer */
	while(DMA2D->CR & DMA2D_CR_START) { }								// wait for chromart idle

As soon as I kick-off the transfer on line 58, the TEIF bit in DMA2D->ISR gets set, indicating a transfer error and the data, but I can't for the life of me work out what would cause something like that. I've tried a few different combinations for the parameters but always with the same result.

Is there anything forehead slappingly obviously wrong my code or some sort of other configuration required ?

5 REPLIES 5

Read out and check/post DMA2D registers content.

The prime suspects are the address registers - the memories have to be accessible by the DMA2D (see the very first figure in RM for routing availability from AHB bus matrix masters to slaves), and probably there are alignment requirements, too.

JW

The thought had occurred to me.

In this instance, the output buffer buf1 is a local variable on the stack and, as reported by the debugger, at 0x2004f678, the source buffer a4 is an initialised static array at 0x8045418. Other than one address being in RAM and the other in program flash there doesn't seem to be anything unusual about them and they're both aligned to four byte boundaries.

DMA2D	DMA2D_TypeDef *	0x4002b000	
	CR	volatile uint32_t	0x20000 (Hex)	
	ISR	volatile uint32_t	0x1 (Hex)	
	IFCR	volatile uint32_t	0	
	FGMAR	volatile uint32_t	0x8045418 (Hex)	
	FGOR	volatile uint32_t	0	
	BGMAR	volatile uint32_t	0	
	BGOR	volatile uint32_t	0	
	FGPFCCR	volatile uint32_t	4278190090	
	FGCOLR	volatile uint32_t	16776960	
	BGPFCCR	volatile uint32_t	4278190090	
	BGCOLR	volatile uint32_t	65535	
	FGCMAR	volatile uint32_t	0	
	BGCMAR	volatile uint32_t	0	
	OPFCCR	volatile uint32_t	2	
	OCOLR	volatile uint32_t	0	
	OMAR	volatile uint32_t	537196152	
	OOR	volatile uint32_t	0	
	NLR	volatile uint32_t	1572888	
	LWR	volatile uint32_t	0	
	AMTCR	volatile uint32_t	0	
	RESERVED	uint32_t [236]	0x4002b050	
	FGCLUT	volatile uint32_t [256]	0x4002b400	
	BGCLUT	volatile uint32_t [256]	0x4002b800	
DMA2D->CR	volatile uint32_t	0x20000 (Hex)	

What debugger are you using, folks, which displays registers content in decimal? I see it so often here...

Try to move the source to RAM, just as a test whether the FLASH address is a problem. Shouldn't be, but...

JW

I dumped the source into a local stack-based buffer, but I get the exactly the same symptom :(

The debugger is just the regular STM32CubeIDE and I'm looking at the variables in the expression window; it's certainly possible to change the number format to hex but I guess the default must be decimal.

CR	volatile uint32_t	0x20000 (Hex)	
ISR	volatile uint32_t	0x1 (Hex)	
IFCR	volatile uint32_t	0x0 (Hex)	
FGMAR	volatile uint32_t	0x2004f420 (Hex)	
FGOR	volatile uint32_t	0x0 (Hex)	
BGMAR	volatile uint32_t	0x0 (Hex)	
BGOR	volatile uint32_t	0x0 (Hex)	
FGPFCCR	volatile uint32_t	0xff00000a (Hex)	
FGCOLR	volatile uint32_t	0xffff00 (Hex)	
BGPFCCR	volatile uint32_t	0xff00000a (Hex)	
BGCOLR	volatile uint32_t	0xffff (Hex)	
FGCMAR	volatile uint32_t	0x0 (Hex)	
BGCMAR	volatile uint32_t	0x0 (Hex)	
OPFCCR	volatile uint32_t	0x2 (Hex)	
OCOLR	volatile uint32_t	0x0 (Hex)	
OMAR	volatile uint32_t	0x2004f660 (Hex)	
OOR	volatile uint32_t	0x0 (Hex)	
NLR	volatile uint32_t	0x180018 (Hex)	
LWR	volatile uint32_t	0x0 (Hex)	
AMTCR	volatile uint32_t	0x0 (Hex)	
RESERVED	uint32_t [236]	0x4002b050	
FGCLUT	volatile uint32_t [256]	0x4002b400	
BGCLUT	volatile uint32_t [256]	0x4002b800

 Actually, looking at that in hex I just noticed that I have this in code:

DMA2D->BGCOLR = 0xff00ffff;

but stepping over that line, the debugger is showing me 0xffff.

I just changed to

DMA2D->BGCOLR = 0x12345678;

and the debugger is showing me 0x345678; for some reason attempting to write anything except zero for the alpha channel is ignored.

DCarr.1
Senior

slight update.

if I set

DMA2D->BGPFCCR = 	(DMA2D->BGPFCCR & 0x00fc00c0) |					/* DMA2D Background PFC Control Register reserved bits */
						(0b11111111 << 24) |							/* alpha value (0xff) */
						(0 << 16) |										/* alpha mode */
						(0 << 8) |										/* clut size */
						(0 << 5 ) |										/* start clut loading */
						(0 << 4) |										/* clut color mode */
						(0b1010 << 0);									/* color mode a4 */
	DMA2D->BGCOLR = 0xff0000ff;											/* DMA2D Background Color Register */

and

DMA2D->FGPFCCR = 	(DMA2D->FGPFCCR & 0x00fc00c0) |					/* DMA2D Foreground PFC Control Register */
						(0b11111111 << 24) |							/* alpha value  */
						(0 << 16) |										/* alpha mode */
						(0 << 8) |										/* clut size */
						(0 << 5 ) |										/* start clut loading */
						(0 << 4) |										/* clut color mode (ignored in a4 mode) */
						(0b1010 << 0);									/* color mode a4 */
	DMA2D->FGCOLR = 0xffff0000;											/* DMA2D Foreground Color Register */
	DMA2D->FGMAR = data;												/* DMA2D Foreground Memory Address Register */

so the a4 data and a4 mode on both fg and bg, fgcolor red, bgcolor blue I get a very plausible rendering of the test pattern. there still seems to be some glitches, but definite progress.

The glitches are

The pixels seem to come out with what appears to be a big-endian vs little endian type problem presumably explained by the in-memory data ordering shown in the datasheet.

The fg and bg colors are being basically respected but there seems to be some white slipping in and even if I set both fg and bg to 0x000000, a 0 in the a4 data always results in a pure white output pixel.