Skip to main content
Version: 4.16

8. Hardware acceleration

Motivation#

The Chrom-ART (DMA2D) graphics accelerator is capable of transferring parts of image data from memory and drawing it into or composing it onto the framebuffer. Chrom-ART can read data from internal or external memory. Similarly it writes to internal or external memory. This can be utilized when doing graphics, and has the possibility of drastically improving the graphical performance and at the same time significantly lowering the MCU usage of your application.

Many STM32 controllers contain the Chrom-ART accelerator, but not all. Check your datasheet. DMA2D is the code name for Chrom-ART and is used in the code and documentation.

Note
Skip this step if hardware acceleration using Chrom-ART is not relevant for your board bring up.

Goal#

The goal of this step is to enable Chrom-ART and read and write data using it. The goal is not to examine the functionality of the Chrom-ART chip, but to verify that memory interfaces are functional from a Chrom-ART perspective.

Verification#

Here are the verification points for this section:

Verification PointRationale
Chrom-ART is configuredChrom-ART can be used for drawing the desired graphics
Chrom-ART can read memoryChrom-ART can be used for drawing graphics (M2M)
Chrom-ART can write memoryChrom-ART can be used for drawing graphics (M2M and R2M)
Chrom-ART performanceChrom-ART yields the desired performance for graphics

Prerequisites#

The following are the prerequisites for this step:

  • MCU with Chrom-ART.

Do#

The Chrom-ART is configured in CubeMX under the Multimedia -> DMA2D category. Activate DMA2D and configure Transfer mode and Color mode according to your display.

In the figure below DMA2D is activated and configured for Memory to Memory transfer mode and RGB565 Color Mode. Select the color mode that matches your display.

Configuring Chrom-ART

The DMA2D global interrupt is important for the syncronization of framebuffer access in a TouchGFX application. Ensure that the global interupt is enabled (NVIC tab) and that code generation for interrupt handlers is enabled (Code Generation tab) in the CubeMX NVIC settings as shown below. The priority is not important at this stage.

Enabling the Chrom-ART interrupt

Enabling the Chrom-ART interrupt handler code generation

Write to Framebuffer Memory#

Here is an overview of code that fills a specific color in a rectangle in target memory (register to memory). Check Cube Firmware packs for a concrete project for your MCU.

main.c
#include "stm32f7xx_hal.h"
#include "stm32f7xx_hal_dma2d.h"
...
uint32_t color = 0xF800; //Red in RGB565
hdma2d.Init.Mode = DMA2D_R2M;
hdma2d.Init.ColorMode = DMA2D_RGB565;
MODIFY_REG(hdma2d.Instance->CR, DMA2D_CR_MODE, DMA2D_R2M);
MODIFY_REG(hdma2d.Instance->OPFCCR, DMA2D_OPFCCR_CM, DMA2D_RGB565);
MODIFY_REG(hdma2d.Instance->OOR, DMA2D_OOR_LO, displayWidth - rectangleWidth);
hdma2d.LayerCfg[1].InputColorMode = CM_RGB565;
hdma2d.LayerCfg[1].InputOffset = 0;
HAL_DMA2D_ConfigLayer(&hdma2d, 1);
HAL_DMA2D_Start_IT(&hdma2d, color, (unsigned int)dstPtr, rectangleWidth, rectangleHeight);

If the Transfer Completed setup is configured correctly in CubeMX, a custom handler can be assigned to handle this event:

hdma2d.XferCpltCallback = DMA2D_XferCpltCallback;

And the handler can be defined as follows to verify the Transfer Completed interrupt configuration:

extern "C" {
static void DMA2D_XferCpltCallback(DMA2D_HandleTypeDef* handle)
{
//Ensure that you this callback is called
}
}

Memory-to-Memory can be tested by supplying a pointer to memory with pixel data.

HAL_DMA2D_Start_IT(&hdma2d,
(unsigned int)srcPtr,
(unsigned int)dstPtr,
displayWidth - nrOfPixels);

Performance is as expected#

Compare the performance of the Chrom-ART with the performance results from previous steps of reading and writing memory. It is expected that the code utilizing Chrom-ART will be more performant than the previous CPU read/write operations.

Tip
Use the value of the `CCSTEP` clock cycle register to get a more precise measurement of clock cycles spent between breakpoints than the millisecond counting sysTick.