cancel
Showing results for 
Search instead for 
Did you mean: 

How to Cache Bitmaps Stored on an SD Card with TouchGFX

Leo_Berna99
Associate III

Hello, everyone,

I am following the following youtube video posted by ST: https://www.youtube.com/watch?v=jE_nL1GObmA.

My intention is to use an SD card to go and insert images due to a lack of space in flash or external ram.

I followed the video, creating a bitmap cache in a portion of external RAM away from frame buffers and other important resources.

In the LD file, I then added a virtual section called SDCARD into which I went to place all the contents of the ExtFlashSection.

Then following the video I am right at the point where from the .elf file I should have created the .bin file through the command arm-none-eabi-objcopy.exe --dump-section ExtFlashSection=images.bin STM32H7S78-DK_24bpp_Appli.elf.

However, I unfortunately get the following error: STM32H7S78-DK_24bpp_Appli.elf[ExtFlashSection]: can't dump section - it has no contents: File in wrong format
C:\TouchGFX\4.24.1\env\MinGW\msys\1.0\gnu-arm-gcc\bin\arm-none-eabi-objcopy.exe: unable to rename 'STM32H7S78-DK_24bpp_Appli.elf'; reason: File exists

Has anyone been through this before and has a possible solution to the problem?

31 REPLIES 31

As a result of these problems, I tried to go deeper into the problem and take a step back.
I opened the project for my DK STM32H7S78-Dk “Animation TextureMapper Exemple” on TouchGFX version 4.24.1.
Generate the code and program the flash with CubeIDE.
Up to which all is OK, the image1 below attached appears on the screen of my board.
Next I go slightly further and add just the SDMMC1, with the basic configurations and the fat, without changing anything from before (without adding my code!!!, just adding from the .ioc)
I re-compile the code and end up with the one in figure 2. I can't explain it. I tried diff merging the folders before and after the addition but I can't find anything that could have caused this huge change in the display.

Debugging the code I came across the init of SDMMC1 which looops endlessly here :

 

while ((HAL_GetTick() - tickstart) < wait)
{
}

 


Probably because if RTOS is on, the tick handling is passed to the scheduler, and this is triggered after the call to the SDMMC init.

Have you modified the linker script in the new project?

 

In the new project, check that your timebase under SYS in CubeMX is set to a timer and not systick. Also make sure that the interrupt for that timer is set to a higher priority (lower number) than 5.

The problem with the HAL delay should be fixable by setting the time base timer to a higher priority. FreeRTOS intercepts the usual SysTick interrupt, but setting a timer as time base and setting the priority of that high enough allows the timer to drive the HAL ticks. 

I was not aware you were running an H7S78. I think your original problem is probably related to MPU settings. For that template project, a base region is set up to allow no access to all areas, and regions are then set up on top of that to allow acces to specific regions. You should create a region for your SD address space with the settings used for region 1.

I believe we are almost here. Thanks.

So I changed the priority of the Timer and the SDMMC1 init now is ok.

I tried to also add a new address space for my SD (Region 8) according to the next image :

Leo_Berna99_0-1732810065171.png

I can't see any image on the screen yet. The program is running without error.

void TouchGFXHAL::initialize()
{
    // Calling parent implementation of initialize().
    //
    // To overwrite the generated implementation, omit call to parent function
    // and implemented needed functionality here.
    // Please note, HAL::initialize() must be called to initialize the framework.


 	uint16_t* cacheStartAddr = (uint16_t*)0x9180000C;
	uint32_t cacheSize = 0x800000;

    TouchGFXGeneratedHAL::initialize();
    touchgfx::Bitmap::removeCache();
    touchgfx::Bitmap::setCache(cacheStartAddr, cacheSize,128); // dopo cache size c'era 128
    instrumentation.init();
    setMCUInstrumentation(&instrumentation);
    enableMCULoadCalculation(true);

    /* The LCD instance is set as auxiliary LCD */
    setAuxiliaryLCD(&lcd16);
    lcd16.enableTextureMapperAll();
    activateNeoChrom(true);
    enableDMAAcceleration(false);
}

 I forgot to tell you that I have a Bitmap cache in that portion of SDRAM. Could be this a problem?

This is also my linker file :

Leo_Berna99_1-1732810508386.png

Thanks for your help @mathiasmarkussen 

 

mathiasmarkussen
ST Employee

Does your .map file suggest the images are in the SD card address range?

And you BitmapDatabase.cpp?

I might suggest creating a linker section for your image buffer, so you are sure you do not overwrite anything useful. It should be uninitialized (like the frame buffers), since the SDRAM is not available at boot time.

I might suggest setting an image or two to be in internal flash in the images tab in TouchGFX designer, and see if they show up.

You could try to put a single image of a solid colour (on the SD card) in your project and draw only that image. Then break at the end of your block copy function and see if the memory contents match your expectation.

Finally, I can see that your image cache is the same size as your SD card region. You could also try the suggested procedure at the bottom here: Using Non-Memory Mapped Flash for Storing Images | TouchGFX Documentation

Yes, my .map file suggest that the images are in the SDcard Address range.

Leo_Berna99_0-1733148443990.png

This is my BitmapDatabase.cpp file.

Thanks, I'll try your options. 

In the video I can see that your colleague is using the (NOLOAD) option for the ld file, and then he use the command dump section on that section. How is it possible? that region should be empty so no dump could be possible. Am I wrong?

@Leo_Berna99 ,


Leo_Berna99_0-1733148443990.png


Please avoid code screen shots of your code and please use </> button to paste it instead.
Thank you for your understanding.

To give better visibility on the answered topics, please click on "Accept as Solution" on the reply which solved your issue or answered your question.

I'm sorry.

// 4.24.1 0x06525b0a
// Generated by imageconverter. Please, do not edit!

#include <images/BitmapDatabase.hpp>
#include <touchgfx/Bitmap.hpp>

extern const unsigned char image_bg[]; // BITMAP_BG_ID = 0, Size: 480x272 pixels
extern const unsigned char image_image00[]; // BITMAP_IMAGE00_ID = 1, Size: 100x100 pixels

const touchgfx::Bitmap::BitmapData bitmap_database[] = {
    { image_bg, 0, 480, 272, 0, 0, 480, ((uint8_t)touchgfx::Bitmap::RGB565) >> 3, 272, ((uint8_t)touchgfx::Bitmap::RGB565) & 0x7 },
    { image_image00, 0, 100, 100, 0, 0, 100, ((uint8_t)touchgfx::Bitmap::RGB565) >> 3, 100, ((uint8_t)touchgfx::Bitmap::RGB565) & 0x7 }
};

namespace BitmapDatabase
{
const touchgfx::Bitmap::BitmapData* getInstance()
{
    return bitmap_database;
}

uint16_t getInstanceSize()
{
    return (uint16_t)(sizeof(bitmap_database) / sizeof(touchgfx::Bitmap::BitmapData));
}
} // namespace BitmapDatabase

This is my BitmapDatabase.cpp

I believe sections marked NOLOAD will still be present in the .elf file, but the programmer will not load and program it. This would also be why he is able to flash the board without errors, even though he has images at an address that can not be programmed.

Good morning everyone,

I come back here to write with some good news that I hope will be helpful to other people.
After a bit of work and more understanding of the subject, I managed to get the application working properly. I can now correctly read the binary file and display the image at run time. I recommend everyone to do this to create their own touchGFX application, the default ones may have blocking configurations. The one shown in the video for my microcontroller (STM32h7s78-dk) had some MPU settings that did not smoothly allow caching and reading in the virtual SD region. By changing from scratch design, with some modifications, everything went right.
Thank you @mathiasmarkussen for the help.

However, one last key point remains to be fixed to make this application 100% functional, which I have seen to be a topic addressed in other posts but never resolved.
As I wrote in the first post the creation of the binary file must be done from the .elf file and touchGFX because this goes to preserve references to the IDs defined by TouchGFX. That makes sense so far. To do this in the video mentioned several times ( I will put the link here for first time readers: https://www.youtube.com/watch?v=jE_nL1GObmA )
a virtual SDCARD zone is created in the ld file and eventually configured to move all ExtFlashSection resources there with the command (NOLOAD) mean not to include the contents of the corresponding section in the ELF file as loadable data.

If I proceed to do exactly the same thing that your colleague does in the video I find that obviously the --dump-section command gives me the result “can't dump section the file (.elf) has no content.” In that the virtual section, given the flag (NOLOAD), will only go to allocate the ExtFlashSection area, not add the data.
The solution I had impulsively thought of was to remove the (NOLOAD) flag and add via the FILL flag in the ld file dummy data to fill the zone.
This unfortunately returns me an error like, “Error message from debugger back end:
Load failed
Failed to execute MI command:
load “ this is because the debugger tries to allocate data (since I did not put the NOLOAD flag) in a virtual zone!
Could you help me in finding a solution? Is there any way to make the debugger exclude the ExtFlashSection zone?

Unfortunately, without this step the whole application becomes unusable since I have to allocate the section in a physically accessible zone.... and I think those who go to use the SD to upload images do so more because of a lack of space.

Thank you