cancel
Showing results for 
Search instead for 
Did you mean: 

Frame Buffer is allocated in both RAM and Flash

DSwea.1
Associate III

I'm working with a system built around the STM32F767 which has 512kB of internal RAM, and 2MB internal Flash. There is no external RAM or Flash, so the entire application has to live within those resources. We are using RBG565 format with a 480x272 LTDC, and a single framebuffer of 255kB. Since both all the code and all the graphic images must fit into the 2M Flash, we must be quite careful to ensure that we remain within these limits. In general, a full-screen image will require app. 255kB of Flash. We're using TouchGFX Designer 4.17.0, STM32CubeIDE 1.7.0, and TouchGFX Generator 4.17.0.

In the STM32CubeMX editor, a single buffer scheme is selected:

0693W00000Kau2LQAR.pngIn the resulting generated code, the frame buffer is declared in TouchGFXGeneratedHAL.cpp:

namespace
{
    // Use the section "TouchGFX_Framebuffer" in the linker to specify the placement of the buffer
    LOCATION_PRAGMA("TouchGFX_Framebuffer")
    uint32_t frameBuf[(480 * 272 * 2 + 3) / 4] LOCATION_ATTRIBUTE("TouchGFX_Framebuffer");
    static uint16_t lcd_int_active_line;
    static uint16_t lcd_int_porch_line;
}
 

When the project is built without adding a "TouchGFX_Framebuffer" section to the linker files (xx_RAM.ld and xx_Flash.ld), the result is that the buffer is allocated in both RAM and Internal Flash:

0693W00000Kau2bQAB.pngAdding a "TouchGFX_Framebuffer" section to the linker files seems to have no effect at all:

  TouchGFX_Framebuffer :
  {
    . = ALIGN(0x4);
    _tgfxbuf_start = .;
    *(TouchGFX_Framebuffer TouchGFX_Framebuffer.*)
    *(.gnu.linkonce.r.*)
    _tgfxbuf_end = .;
  } >RAM

The framebuffer is still allocated in both places. I first thought that the entry was simply being ignored, but when I added the tags _tgfxbuf_start and _tgfxbuf_end, they appeared in the .map file:

TouchGFX_Framebuffer
                0x0000000020061fd8        0x0 load address 0x00000000080f6010
                0x0000000020061fd8                . = ALIGN (0x4)
                0x0000000020061fd8                _tgfxbuf_start = .
 *(TouchGFX_Framebuffer TouchGFX_Framebuffer.*)
 *(.gnu.linkonce.r.*)
                0x0000000020061fd8                _tgfxbuf_end = .

so it's clear that the linker file entry was parsed.

The only work-around that I could determine was to eliminate the LOCATION_PRAGMA and LOCATION_ATTRIBUTE macros that surround the definition in TouchGFXGeneratedHAL.cpp:

namespace
{
    // Use the section "TouchGFX_Framebuffer" in the linker to specify the placement of the buffer
    uint32_t frameBuf[(480 * 272 * 2 + 3) / 4];
    static uint16_t lcd_int_active_line;
    static uint16_t lcd_int_porch_line;
}
 

which resulted in placement of the buffer in RAM only. The problem with this approach is that TouchGFXGeneratedHAL.cpp must be re-edited to remove the macros every time we generate new code in TouchGFX Generator, an extra step that must be carefully observed.

Any suggestions as to how to correct this issue are appreciated. It's possible that I've made some mistake in the section added to the .LD files; but I've edited these files on other projects with no problems.

1 ACCEPTED SOLUTION

Accepted Solutions

Thanks very much for the suggestion. I wasn't quite sure how to do so, but you're reply got me searching and I found this link:

https://mcuoneclipse.com/2014/04/19/gnu-linker-can-you-not-initialize-my-variable/

from which I was able to determine that the following syntax would solve my problem:

  TouchGFX_Framebuffer (NOLOAD) :
  {
    . = ALIGN(0x4);
    *(TouchGFX_Framebuffer TouchGFX_Framebuffer.*)
    _tgfxbuf_end = .;
  } >RAM
 

The NOLOAD statement is the key. This may not be the only or the best solution, but it works.

I'm indebted to you for helping me solve an issue that has taken up a good deal of my time. And, in the process, we've gained back about 12.5% of our available Flash.

View solution in original post

3 REPLIES 3
ktrofimo
Senior III

You buffer falls in "initialized variables" category and during startup firmware copies it (default value) from flash to ram. Make it "uninitialized variable"​.

Thanks very much for the suggestion. I wasn't quite sure how to do so, but you're reply got me searching and I found this link:

https://mcuoneclipse.com/2014/04/19/gnu-linker-can-you-not-initialize-my-variable/

from which I was able to determine that the following syntax would solve my problem:

  TouchGFX_Framebuffer (NOLOAD) :
  {
    . = ALIGN(0x4);
    *(TouchGFX_Framebuffer TouchGFX_Framebuffer.*)
    _tgfxbuf_end = .;
  } >RAM
 

The NOLOAD statement is the key. This may not be the only or the best solution, but it works.

I'm indebted to you for helping me solve an issue that has taken up a good deal of my time. And, in the process, we've gained back about 12.5% of our available Flash.

Glad I was able to help you. If your issue is closed you can click "select as best" to indicate working answer.​