cancel
Showing results for 
Search instead for 
Did you mean: 

Hardfault when call setTypedText

PPres
Associate II

Hi,

I'm developing on a custom hardware, trying to run a simple touchgfx project.

Single screen with an image an a text over.

Following the example and the strusture of a STM32F746G-Disco demo board, I makemy hardware functioning, any image, even big goes on the 800x480 LCD.

But any time I try to put on the screen a text the system faut to Hrdfault handler.

it seem that the function trying to call a protected area ( 0x5xxxxxx) .

I get that problem every time I try to call "setTypedText" funcion.

I don't understand if some memory settings in my app is wrong. I did try to put the text into external or internal memory, using wildcards or not. It's impossible to show any text.

I use freertos, the project is created with CubeMX + Touchgfx Designer.

I did encrease the heap and the stack.

Nothing. several images at the same time pass the test, but no text even if I use a single font and try printing a single word.

Please point me in some direction to search.

Thanks.

Paolo

17 REPLIES 17
PPres
Associate II

Hi Alexandre,

Yes I'm sure that all data in quadspi are correct. My external bootloader verify that and I did try to show on lcd some raw data from quadspy configuring the framebuffer to get data from 0x90000000 location memory.

After some test with

It seems something wrong on interrrupt priority or that the system load can't be managed correctly.

The simple project was not so simple because include a fade-in interaction on the start screen, so it was not so obvious if images and text was loaded or not.

Then I create a very simple project ( just one image on the screen), and it run even inside or outside into quadspi.

That is the good part. So I 'm sure to have all periferals correctly configured and running. ( quadspi, SDRAM, Rtos, touchgfx, timer, LCD) .

Now go to the bad part: If I introduce some transition ( fade in or out) the system load the first screen and stop ticking ( Model::tick() is no more called ), so the fade stops. If I try to move a big colored box ( so it's not an image but is generated on the fly by touchgfx) the same problem (tick freezing) happens.

If the transition or some movements involve a little colored box all goes well.

It seems that some heavy work freeze the process, but a light one not.

Those are the irq settings for my peripherals:

LCD irq 5

DMA2 irq 5

SDRAM irq 5

QSPI irq 4 ( I did try to rise the irq but it functions only with 4 or lower irq priority)

TIM( tick using TIM14) irq 0

RCC irq 5

no other peripherals are configured.

linker file:

_Min_Heap_Size = 0x1000 ;   

_Min_Stack_Size = 0x1000 ;   

FreeRTOSv2 task:

.stack_size = 1024 of touchgfxTask

ExtFlashSection + FontFlashSection + TextFlashSection all on Quadspi.

The display is 800x480 so not so small, but I tink that if some issue on performance happens I should see flickering the images( during the animations), but with all the touchgfxTask running .

I try to enable the overrun interrupt on LCD configuration but nothing happens.

Is it possible that with an heavy load touchgfx generate some overrun handler who stop anything?

How can I verify that?

Thanks

PPres
Associate II

Finally I found what was the problem.

The fact was that into quadspi the data war all right as my reading procedure at the very beginning of main() demostrate, but the procedure I did use to read and write the memory was wrong.

After every command sent to the quadspi I did check the internal status flag register to be sure that the operation was finished, but the function ( copyed from other project) did tests a bit that on my MT25Q doesn't exists. So the result was unpredictable. That generates random errors also if the internal data was corrects.

Now I have a project with a lot of iumages, text and animations and all functioning very well.

Thanks for support.

What was your solution to this problem? I am having a similar issue where I can place images/icons in the external flash and everything works fine, but if I put text in the external flash, it causes the system to have a hard fault.

AMiro.5
Associate II

Whilst my cause of Hardfault inside setTypedText was different from that of TS, I will write it here anyway. Hope it will help somebody.

In my project I was creating TextAreas in runtime, on the fly. All worked smoothly for several months. And suddenly transferring to that specific screen caused long time hanging and then hardfault. Now I know the reason - setTypedText has a side effect of calling resizeToCurrentText() which in turn calculates size if text, including contents of wildcards. It has happend that I was filling the wildcard buffer AFTER I called the setTypedText, so it calculated size of garbage text, reading memory starting from wildcard buffer till the first zero encountered. All these months before it was a kind of miracle that zeroes were not far away from wildcard buffers.

Hi @Community member​ ,

"I was creating TextAreas in runtime"

Could you share your technique of doing this please ?

Are allocating GFX widget on a Heap in e.g. in GFX::View constructor or GFX::View::setupScreen () and adding pointer to eg Container::add () ?

I am asking because I saw in few places that this is not recommended to do eg comment by @Yoann KLEIN​  here:

0693W00000aJ2jyQAC.pngI am not sure wherher to go new/delete path as implementation of GFX could change and cause application crash later in the project.

I work in Qt/emWin. Not being able to new/delete widgets is quite a change in a design paradigm/way of thinking - this is not a complaint, just a statement.

Thanks

class FastEditScreenView: public FastEditScreenViewBase {
      ...
   private:
         touchgfx::MoveAnimator<touchgfx::TextAreaWithOneWildcard> 
 letter_boxes[LETTER_COUNT];
         touchgfx::Unicode::UnicodeChar letter_buffers[LETTER_COUNT][LETTER_BUF_SIZE];
}
 
void FastEditScreenView::setupScreen() {
	FastEditScreenViewBase::setupScreen();
 
	int16_t temp_width, temp_height;
	temp_width = 20;
	temp_height = 20;
	for (uint8_t i = 0; i < LETTER_COUNT; i++) {
		letter_boxes[i].setXY(18 + i * 14, 88 + 3 * i);
		letter_boxes[i].setHeight(temp_height); //  before setTypedText ! 
		letter_boxes[i].setWidth(temp_width);
		letter_boxes[i].setColor(touchgfx::Color::getColorFromRGB(255, 255, 255));
		letter_boxes[i].setLinespacing(0);
		Unicode::snprintf(letter_buffers[i], 2, "%s", "W"); // before  setTypedText !
		letter_boxes[i].setWildcard(letter_buffers[i]);	     
                letter_boxes[i].setTypedText(touchgfx::TypedText( T_RESOURCELETTERWC));
		letter_boxes[i].resizeToCurrentText();
		add(letter_boxes[i]);
		letter_boxes[i].invalidate();
	}
}

It is really more comfortable to create controls in Designer and hide/show them as needed. But if you really-really eager such strange things, you can look in your ...ViewBase.cpp file and do more or less the same - new controls should be fields of your view. See also this discussion: https://community.st.com/s/question/0D53W00000ttGs7SAE/creating-textarea-programmatically-with-wildcard-and-buffer

Hi @Community member​ 

Thanks for this. When you said:

" I was creating TextAreas in runtime, on the fly"

I thought you create widgets with new/delete. I am aware of the technique you described.

I understand now what you said:

"It has happend that I was filling the wildcard buffer AFTER I called the setTypedText, so it calculated size of garbage text, reading memory starting from wildcard buffer till the first zero encountered. All these months before it was a kind of miracle that zeroes were not far away from wildcard buffers. "

I looked at your code and noticed you do not initialise letter_buffers at any point. It is not a good practice.

Initialise your buffers like this:

touchgfx::Unicode::UnicodeChar
letter_buffers[COUNT][BUF_SIZE] = {};
// = {};  zero initialised at moment of object creation
 
static constexpr int SCSizeBytes =
            sizeof (UnicodeChar) * (COUNT*BUF_SIZE );

And before using buffers like this:

std::memset ( letter_buffers, 0, SCSizeBytes );

or

#include <algorithm>
 
std::fill
(
         (int8_t*)letter_buffers,
         ( (int8_t*)letter_buffers ) + SCSizeBytes,
         0
);

I thought that

Unicode::snprintf(letter_buffers[i], 2, "%s", "W");

is good enough as initialization. At least it worked for me.