Skip to main content
Amilton Rogério da Silva
Associate III
August 26, 2020
Solved

STM32H7 - SRAM issues - LOCAL VARIABLE ALLOCATED OVER GLOBAL VARIABLE ADDRESS

  • August 26, 2020
  • 13 replies
  • 8133 views

Hi,

 I am facing an problems that I have never seen before with local variables being allocated at the same addresses of global ones. In the attached image I show an example of a local variable with the address of another variable in the STEmwin library (WM_aCHWinLast). 

The same has already occurred with other global variables, not only with STEmwin. I managed to find some and I was able to solve it by replacing vectors with pointers and allocating their size through customized malloc functions. All STemWin routines work perfectly, only generating the fault in specific executions sequences. The problem seems to be very localized in specific routines, but I don't understand the relationship since the variables are local and should only concern to HEAP memory, which is quite large 0xA000. Other global variables, besides STEwin also appeared with an overlapping address, but these did not generate hardfault.

After going through these routines, with overlapping variables, when executing GUI_Exec () the Hardfault is generated:

Bus, memory management or usage fault (FORCED)

Attempt to switch to invalid state (INVSTATE).

Any ideas or someone already had similar problems?

STM32H750  - Atollic TrueSTUDIO 9.3.0

Thank you in advance.

This topic has been closed for replies.
Best answer by Amilton Rogério da Silva

Solved. Many thanks to all.

  Using the calloc it was possible to see that the function needed more HEAP memory, being necessary to allocate 70kB (0x110000) for the calloc not to return NULL, checking the function I estimated the consumption of 35kB in addition to the previous one with 25kB more. I expected the compiler to indicate a lack of memory in the original version, with a fixed size in the local variables and without any use of malloc or calloc, but the lack of HEAP generated the overflow. Even using mymalloc, the need for HEAP was greater than expected.

I thank you all very much for the tips and attention.

0693W000002lamXQAQ.png

13 replies

KnarfB
Super User
August 26, 2020

Could that be a stack overflow? Local variable = placed on stack, accessed relative to SP. Stack is decreasing while top of heap (sbrk) is increasing. The INVSTATE bit in the fault may indicate that the stack was overwritten, i.e. an even value was found where a return address (with thumb bit set in LSB) was expected. The fault analyzer can show where the fault happened, and you can jump to that place.

Tesla DeLorean
Guru
August 26, 2020

Screens aren't telling me much.

Need to look at the code disassembly and registers where it faults.

The highlighted values don't have word aligned addresses, the CM7 will fault on LDRD/STRD on these.

If you're blowing the scope on the local/auto variables you can easily break the return address on the stack, but the stack trace at least seems to indicate it can follow what's being going on.

Make sure the stack is adequate, place markers, and determine depth/usage

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Amilton Rogério da Silva
Associate III
August 26, 2020

Hello, and thank you very much for the quick response.

  I increased the minimum STACK, it was 0x400 and now it is 0x4000

_Min_Heap_Size = 0xA000;

_Min_Stack_Size = 0x4000;

 But the result is still the same.

 I compiled without using mymalloc, just to show more examples of the overlapping addresses, and under these conditions the contents of several of the global variables are changed.

  

  I have doubts if it is a STACK problem since the routine works and does not generate a fault depending on what is executed before. To contextualize in the first pass two routines are called, image capture and then another for comparison, this does not generate hardfault. But when I call only the comparison routine, several of the addresses appear overlapping and generate the hardfault in the next passage through GUI_Exec. As I said other variables are changed, but the content is not critical to generate the fault.

  I executed the code step by step in disassembly to the point of the GUI_Exec that generates the fault, luckily occurs in the first instructions. The address in R7 appears to be the variable GUI_pFTimerExec in 0x2000fa98, in operation REV R3, R7. In the next step, jump to the Hardfault (see images)

Amilton Rogério da Silva
Associate III
August 26, 2020

Hi,

Here are some more screens.

The execution generates the fault in the instruction BLX R4. It is possible to see that R4 has an invalid value for the jump 2883592 = 0x2C0008.

In normal execution, the value of register R4 is 0 and the address jumps to WM_Exec. (_no_fault image)

Tesla DeLorean
Guru
August 26, 2020

Jumping to an EVEN address will definitely fault.

Check you've initialized the structures properly. Use calloc()

Tips, Buy me a coffee, or three.. PayPal Venmo (See Profile) Up vote any posts that you find helpful, it shows what's working..
Amilton Rogério da Silva
Associate III
August 26, 2020

"Check you've initialized the structures properly"

I will review the structures, they were not made by me. It is difficult to imagine what kind of errors in a structure could mess with the allocation of the starting address of the heap memory at the entrance of this function.

Amilton Rogério da Silva
Associate III
August 26, 2020

Hi,

I'm sending it to the screens in the attached file.

TDK
August 27, 2020

Does malloc hand out addresses in the heap space? In order for stack variables and heap variables to be in the same location, either you overflowed the stack or malloc is handing out bogus addresses.

"If you feel a post has answered your question, please click ""Accept as Solution""."
Amilton Rogério da Silva
Associate III
August 27, 2020

Thanks for the tip.

  I will try to use the native malloc to see the effect. I used a customized malloc that, at first, seemed to have resolved since address overrides did not appear in this function, but this "mymalloc" uses SRAM_D1 and not the DTCM that is the source of HEAP. The algorithm was more stable, but returned to generate hardfault when trying to access the functions in different sequences as I mentioned.

KnarfB
Super User
August 27, 2020

No solution, but few remarks:

  • it still smells like overwritten stack, either by a stack overflow or by writing to a local variable out of its array bounds
  • increasing _Min_Stack_Size and _Min_Heap_Size is a good idea, but it does not increase or change something at runtime. It only assures (during linking) that sizeof(all global variables) + _Min_Stack_Size + _Min_Heap_Size fits into RAM.
  • in one screen dump above (re_arrange_point) there are arrays defined as local variables. Try to make them all static to reduce stack "breathing". Unless you have recursive function calls or multi-threading, I would allocate as much as possible as static (global) data. This also prevents heap fragmentation.
  • gcc has a nice options -fstack-usage & -Wstack-usage= to warn about functions with excessive stack usage (at compile time), see https://interrupt.memfault.com/blog/best-and-worst-gcc-clang-compiler-flags. This may help to find memory hogs.
Amilton Rogério da Silva
Associate III
August 27, 2020

Thanks for the tips, I'll check.

I started looking for overflow that are the most common error for this type of hardfault and it was running step by step, and checking the limits I noticed the tag with the name of a global variable, which in this case was used by the STEmwin library, USB among others. I did the test declaring the vectors as static that even seemed to partially solve the problem but unfortunately I can't give up memory, the structures have vectors with significant sizes, the project does image manipulation and I still have to enable lwip and some more buffers for UART, CAN, TCP communication.

 But it's a good tip, test them as global, so I don't have to pass the strange structures as an argument in these functions and see what happens.

Amilton Rogério da Silva
Amilton Rogério da SilvaAuthorBest answer
Associate III
August 27, 2020

Solved. Many thanks to all.

  Using the calloc it was possible to see that the function needed more HEAP memory, being necessary to allocate 70kB (0x110000) for the calloc not to return NULL, checking the function I estimated the consumption of 35kB in addition to the previous one with 25kB more. I expected the compiler to indicate a lack of memory in the original version, with a fixed size in the local variables and without any use of malloc or calloc, but the lack of HEAP generated the overflow. Even using mymalloc, the need for HEAP was greater than expected.

I thank you all very much for the tips and attention.

0693W000002lamXQAQ.png