How to Cache Bitmaps Stored on an SD Card with TouchGFX
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-25 08:00 AM - last edited on 2024-11-26 01:44 AM by SofLit
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?
Solved! Go to Solution.
- Labels:
-
SDIO-SDMMC
-
STM32H7 Series
-
TouchGFX
Accepted Solutions
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-12-18 03:59 AM
You can keep noload, but then you will have to edit the linker file and build twice to be able to extract your assets .bin.
What I meant is removing noload from the linker script, creating the .bin and then setting extflashsection to noload or removing it altogether using objcopy as I described earlier. You can automate this via post-build commands in CubeIDE:
The command I have set is:
arm-none-eabi-objcopy.exe --dump-section ExtFlashSection=images.bin STM32H7S78-DK_Appli.elf&arm-none-eabi-objcopy.exe --set-section-flags ExtFlashSection=noload STM32H7S78-DK_Appli.elf
which should mark the section as noload after dumping the images. Again, I have not tried to flash a board, but the .bin is created for me.
You may also be able to use the normal debug and load profiles, since the file is modified as part of the build step.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-25 08:04 AM
Hello @Leo_Berna99 ,
The video is using TouchGFX. So are you using it for this purpose?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-25 10:54 PM
I forgot to tell that I'm using an STM32H7S78-DK.
Yes, I'm using SD card for TouchGFX images
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-26 01:30 AM
@GaetanGodart may help.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-26 03:27 AM
Good morning, yes I also followed that tutorial as well as the video but it still gives problems.
Following the video a virtual memory area is allocated for my SDCARD at address 0xA0000000. Perfect, so far so good. Then still in the ld file I go to insert the contents of the ExtFlashSection zone into SDCARD using (NOLOAD).
Having done this step in the video and in the tutorial it runs arm-none-eabi-objcopy --dump-section ExtFlashSection=images.bin STM32H7S78-DK_Appli.elf but since the address is virtual the ELF rightly cannot create the binary file. I don't understand how the colleague in the video created the binary file with a virtual address and the command (NOLOAD).
To get around this to create the .bin file I momentarily allocated the SDCARD zone in an external flash part, once the .bin was created I put the virtual zone back into the ld file.
At this point the code runs and everything seems to be OK but the images still do not show.
I am using the latest version of touchGFX with a project created using the STM32H7S78-DK 24bpp board template as recommended by @GaetanGodart
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-27 12:19 AM
Have you tried to run your project with images in flash? You can allocate a few of the images to internal flash for a quick test in the image tab in TouchGFX designer.
Have you implemented a custom blockcopy function for the address space in question as described in Using Non-Memory Mapped Flash for Storing Images | TouchGFX Documentation?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-27 07:22 AM
Hello @mathiasmarkussen ,
bool TouchGFXHAL::blockCopy(void* RESTRICT dest, const void* RESTRICT src, uint32_t numBytes)
{
if(FatFSInit == 0)
{
res = f_mount(&SDFatFS, (TCHAR const*)SDPath, 0);
res = f_open(&SDFile, "images3.bin", FA_READ);
FatFSInit = 1; //mount and open the file only once
}
if((uint32_t)src >= (uint32_t)0xA0000000 && (uint32_t)src < (uint32_t)0xA0740C00)
{
uint32_t dataOffset = (uint32_t)src - (uint32_t)0xA0000000;
res = f_lseek(&SDFile, dataOffset);
res = f_read(&SDFile, dest, numBytes, (UINT*)&bytesread); //dest è un indirizzo nella SDRAM
return true;
}
else
{
return TouchGFXGeneratedHAL::blockCopy(dest, src, numBytes); // else we use the default implementation
}
}
This is my implementation of the block copy function. The function seems to work. Every function return FR_OK and after the reading of the image watching the thread I can see that the program execute BitmpatToCache(), cacheInternal(), chacheAll() etc... until it goes here:
void evaluatePendingScreenTransition()
{
if (pendingScreenTransitionCallback && pendingScreenTransitionCallback->isValid())
{
pendingScreenTransitionCallback->execute();
pendingScreenTransitionCallback = 0;
}
}
I tried making a new project, using the same template shown in the vide without adding my own code, so just open the project, “generate code” and program.
With the images in the internal flash ok, everything shows, with the files in the external flash the screen appears on but blank.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-27 07:30 AM
If I use CubeIDE for programming it'ok in both way
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-28 01:54 AM
So the new project works with images in internal flash only in the designer, but with CubeIDE it works with images in both internal and external flash?
Have you modified any of your linker files to link the assets to the SD card in this project?
What happens if you move just some of you images to internal flash, do they show up correctly, or does the board crash?
And in you old project, what happens when you get to evaluatePendingScreenTransition()?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
2024-11-28 06:23 AM
In my new project doing what you said the board crash.
In my old project after running for a bit, after reading correctly the SD card without showing the images it goes here
void vPortExitCritical( void )
{
configASSERT( uxCriticalNesting );
uxCriticalNesting--;
if( uxCriticalNesting == 0 )
{
portENABLE_INTERRUPTS();
}
}
and here :
void vApplicationIdleHook( void )
{
/* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set
to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle
task. It is essential that code added to this hook function never attempts
to block in any way (for example, call xQueueReceive() with a block time
specified, or call vTaskDelay()). If the application makes use of the
vTaskDelete() API function (as this demo application does) then it is also
important that vApplicationIdleHook() is permitted to return to its calling
function, because it is the responsibility of the idle task to clean up
memory allocated by the kernel to any task that has since been deleted. */
vTaskSetApplicationTaskTag(NULL, IdleTaskHook);
}
without any error