cancel
Showing results for 
Search instead for 
Did you mean: 

How to solve HardFault exception loading L8 images from non memory mapped flash

PJEN
Associate III

I'm working on a STM32H7B3I-DK with a 565 format frame buffer.

In my design, the Serial Flash that contents the ExtFlashSection in a standard project will not be memory mapped because I need part of it to record other data.

I followed the topics about caching bitmaps (https://support.touchgfx.com/docs/development/ui-development/touchgfx-engine-features/caching-bitmaps and https://support.touchgfx.com/docs/development/ui-development/scenarios/using-non-memory-mapped-flash ) 

In TouchGFX Designer, if I put the ’section’ part of the image to ExtFlashSection and the ‘Extra Section’ (e.g. the CLUT) in IntFlashSection everything is fine.

But if I try to put the ‘Extra Section’ in the ExtFlashSection the engine crashes on a HardFault because the library code tries to access directly the extra section in a memory mapped fashion.

Here is the state when hitting the HardFault exception

EXEC_RETURN (LR):

lr      0xffffffed -19

xPSR      0x21000000

ReturnAddress 0x8026bbe

LR (R14)    0x8026edb

R12      0x0

R3       0x1fe00

R2       0x14

R1        0x9001fe00

R0       0x80363d8

Return instruction:

  0x8026bbe <_ZN8touchgfx6Bitmap15getSizeOfBitmapEt+198>: ldrb r0, [r1, #3]

LR instruction:

  0x8026edb <_ZN8touchgfx6Bitmap5cacheEt+62>: mov r9, r0

I keep the linker file to have the ExtFlashSection mapped to 0x90000000 addresses so the data is loaded on debugger start but these addresses are not directly available at run time because the OSPI flash is not memory mapped as in a default TouchGfx project.

I put in bold the offending intsr/data in cpu trace. As you see, the R1 register holds the address of where is linked the _black_extra_data[] array (the CLUT of an image called ‘black’).

This fault happens before my overloaded blockCopy function is called.

Using the working linker map (with extra_ data section in internal flash), I verified that all images were copied to the cache by tracking the calls to my overloaded blockCopy function after a call to Bitmap::cacheAll() (both pixels and clut's are effectively copied to cache but this happen after the offending code !! ) 

34 REPLIES 34

Hi PJEN,

​First of all, thank you very much for your response.

The problem I'm having is that the blockCopy() method is not called, and I don't know what the problem is, I'll list the changes, please help, thanks!

I modified the load file to fix the hardfault issue(I'm using KEIL).

0693W000001q4ReQAI.png

My image data are stored like in the screenshot below

0693W000001qAAxQAM.png

Here's what my image looks like in the .map file

0693W000001qABvQAM.png

According to the official doc about "Caching Bitmap", modify the code as follows

0693W000001qACjQAM.png

According to the official doc about "Using non memory mapped flash", modify the code as follows

0693W000001qAEpQAM.png

PJEN
Associate III

Hello,

I suspect that your problem is that the Bitmap::cacheAll() is called too early (before the initialisation process is done), you need to cache the Bitmap just before you use it .

First, in my case, the call to registerBitmapDatabase is done in the touchgfx_init() function found in target/generated/TouchGFXConfiguration.cpp (I'm not sure but I think that this call to registerBitmapDatabase is written by the Designer (without the parameters giving the bitmap cache memory !!) .Check this TouchGFXConfiguration.cpp file in your project and if the registerBitmapDatabase call is there, make the cache init there to not call registerBitmapDatabase() twice ).

Next, in my project the Bitmap::cacheAll() is called in the setupScreen() function of the start screen (it's called Splash in my project):

void SplashView::setupScreen()
{
    Bitmap::cacheAll();
    SplashViewBase::setupScreen();
}

I tried to move this 'cacheAll()' call in the initialisation code like you do and the program crashes !!

Cross the fingers 😉

Hi PJEN,

I modified it as you said and it now displays the image, but there are still some problems!

My current project is composed of two screens, the start screen shows normal, the second screen shows abnormal, the specific display is as follows

0693W000001qBFeQAM.jpg

A normal display screen should look like this

0693W000001qBFjQAM.png

0693W000001qBFoQAM.png

And now TouchGFX Designer will report an error when running the project!

0693W000001qBFyQAM.png

PJEN
Associate III

Hi,

For the simulator, the message seems clear ... there is no memory to cache the bitmaps.

The Simulator does not run exactly the same code as the target, you'll have to specify cache memory for the simulator run.

Modify the TouchGFX/simulator/main.cpp to something like that :

(See line 15 that declare a 4Mbytes cache area and line 36 that register this cache area )

#include <platform/hal/simulator/sdl2/HALSDL2.hpp>
#include <touchgfx/hal/NoDMA.hpp>
#include <common/TouchGFXInit.hpp>
#include <gui_generated/common/SimConstants.hpp>
#include <platform/driver/touch/SDL2TouchController.hpp>
#include <touchgfx/lcd/LCD.hpp>
#include <stdlib.h>
#include <simulator/mainBase.hpp>
 
#include <touchgfx/canvas_widget_renderer/CanvasWidgetRenderer.hpp>
#define CANVAS_BUFFER_SIZE (3600)
 
using namespace touchgfx;
 
uint16_t imageCache[4*1024*1024/2] ;
 
 
#ifdef __linux__
int main(int argc, char** argv)
{
#else
#include <shellapi.h>
#ifdef _UNICODE
#error Cannot run in unicode mode
#endif
int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    int argc;
    char** argv = touchgfx::HALSDL2::getArgv(&argc);
#endif
 
    touchgfx::NoDMA dma; //For windows/linux, DMA transfers are simulated
    LCD& lcd = setupLCD();
    touchgfx::SDL2TouchController tc;
 
    touchgfx::HAL& hal = touchgfx::touchgfx_generic_init<touchgfx::HALSDL2>(dma, lcd, tc, SIM_WIDTH, SIM_HEIGHT,imageCache,sizeof(imageCache),10);
 
    setupSimulator(argc, argv, hal);
 
    // Ensure there is a console window to print to using printf() or
    // std::cout, and read from using e.g. fgets or std::cin.
    // Alternatively, instead of using printf(), always use
    // touchgfx_printf() which will ensure there is a console to write
    // to.
    //touchgfx_enable_stdio();
 
    // Setup the CanvasWidgetRenderer. ONLY needed if you use CanvasWidgets
    // in your application. The CANVAS_BUFFER_SIZE can be adjusted to match
    // your needs in performance vs. RAM usage. Read more on this in the
    // TouchGFX Manual.
    static uint8_t canvasBuffer[CANVAS_BUFFER_SIZE];
    touchgfx::CanvasWidgetRenderer::setupBuffer(canvasBuffer, CANVAS_BUFFER_SIZE);
 
    touchgfx::HAL::getInstance()->taskEntry(); //Never returns
 
    return EXIT_SUCCESS;
}

On the target, it's like some bitmaps where not correctly cached ... Check the size of the RAM you allocated for the cache ... Check the function that copy the Flash to the cache during BlockCopy ... verify that the images have been correctly stored in the external flash ...

PJEN, Thank you very much for your patience in answering my questions.

I solved the simulator error problem with target board macros.

The image is not displaying fully, I checked the data reading interface and found that it's the spi reading that's having a slight problem.