cancel
Showing results for 
Search instead for 
Did you mean: 

Hard Fault only with Optimize More (-O2)

Bakin.Andrew
Associate
Posted on February 23, 2016 at 13:19

This is strange: I have an application that works perfectly on every optimize level except Optimize More (-O2). A hard fault occurs when a particular thread is running. I have read about various causes for hard faults with FreeRTOS but I can't find any information relating to optimization levels.

As my application works with -O0, -O1, -O3 and -Os I won't lose any sleep over this but would like to know why.

Does anyone have any ideas why? My understanding is that the optimize levels beyond -O2 include -O2 optimizations, so how can -O3 work?

Here's my set up:

STM32F407VGT6

CooCox version 1.7.8

Toolchain : GNU ARM 4.9 2015q3

#hard-fault-optimize-level
3 REPLIES 3
Posted on February 23, 2016 at 20:52

In most cases optimization issues just bring to the surface other bugs or language issues with marginal code.

With GNU/GCC 4.9 I've seen issues with it I can only attribute to a buggy optimizer. The 4.7.2 release was quite stable.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Bakin.Andrew
Associate
Posted on February 29, 2016 at 20:06

Hi clive1,

Thanks for the advice. I tried GNU/GCC 4.7 and the fault was exactly the same so there's something else going on if you believe 4.7 to be stable.

I did a stack dump and found that a certain line in memcpy was the last point of execution before the hard fault. There are only five places memcpy is called, two of which are in the USB driver which I disabled for testing. That leaves three calls all in queue.c of FreeRTOS. See attached jpg.

The hard fault happens after a call to osMessagePut() so I will need to dig into this further to find out what's going on. It may be something to do with copying the struct.

typedef struct {
uint16_t time_count;
uint8_t counting_up;
uint8_t stopwatch_hours_tens;
uint8_t stopwatch_hours_units;
uint8_t stopwatch_mins_tens;
uint8_t stopwatch_mins_units;
uint8_t stopwatch_secs_tens;
uint8_t stopwatch_secs_units;
}stopwatch_data_t;
stopwatch_data_t stopwatch_data;
...
if(osMessagePut(stopwatchMessageHandle, ((uint32_t)&stopwatch_data), 500) != osOK)
{
Error_Handler();
}

________________

Attachments :

2016-02-29_18-44-24.jpg : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006I17G&d=%2Fa%2F0X0000000bjh%2FEW2d.URVc9AUpPReM8O6SbBTvTBPiJxuLUyYj_ItDAc&asPdf=false
Posted on February 29, 2016 at 20:27

Ok, so something you're handing to memcpy? You'd need to look at the register at the fault to understand what address it is objecting too.

You could check the pointers before calling memcpy, not just for NULL, but for addresses that are outside normal RAM, FLASH, etc.

If the structure is on the stack, check that there is sufficient capacity there. The optimizer tends to move stack based variables into registers.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..