Hard fault on KE02 caused by write to static variable

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Hard fault on KE02 caused by write to static variable

Jump to solution
1,789 Views
paulrobinson
Contributor II

I am trying to implement the I2C bootloader (AN4775) on the KE02 and get a hard fault interrupt.  I have tracked it down to the line that causes it using methods described in other posts which worked as when I remove the offending line I do not get the hard fault interrupt.  The problem is that I don't understand why it is causing the interrupt.

in the FC_protocol.c module there are some variables declared:

static uint8_t u8MCU_ID_InfoBuff[64];

static uint8_t u8DataBuff[WRITE_BLOCK_SIZE];

static uint8_t u8MCU_ID_InfoLength;

and the line that causes the interrupt is the last line in a function within that module

void MCU_ID_Package( void )

{

  ADDRESS_TYPE *pTempAddress;

    uint32_t *pRxFrameLenth;

  uint32_t u32Index;

    uint32_t i;

  uint8_t Sum;

  u8MCU_ID_InfoBuff[4] = sMCU_Info.Version;

  u8MCU_ID_InfoBuff[5] = (unsigned char)sMCU_Info.Sdid>>8;

  u8MCU_ID_InfoBuff[6] = (unsigned char)sMCU_Info.Sdid;

  u32Index = 7;

     -     -     -     -     -     -

     -     -     -     -     -     -

  u8MCU_ID_InfoLength = u32Index;

}

I have made the problem go away in two ways:

1. Make u8MCU_ID_InfoLength non-static

2. Make u8MCU_ID_InfoLength a uint32_t

neither of which make any sense to me.

From map file in original state:

.bss.u8MCU_ID_InfoLength

                0x1ffffe68        0x1 ./FC_protocol/FC_protocol.o

.bss.u8DataBuff

                0x1ffffe69       0x40 ./FC_protocol/FC_protocol.o

.bss.u8MCU_ID_InfoBuff

                0x1ffffea9       0x40 ./FC_protocol/FC_protocol.o

If I change u8MCU_ID_InfoLength to uint32_t it stays in same place and u8DataBuff is shifted by 3 bytes as expected, but why should this work?

.bss.u8MCU_ID_InfoLength

                0x1ffffe68        0x4 ./FC_protocol/FC_protocol.o

.bss.u8DataBuff

                0x1ffffe6c       0x40 ./FC_protocol/FC_protocol.o

.bss.u8MCU_ID_InfoBuff

                0x1ffffeac       0x40 ./FC_protocol/FC_protocol.o

0 Kudos
1 Solution
1,500 Views
paulrobinson
Contributor II

Have been over this again and discovered that while removing a line of code was making the problem go away, it was not the cause of the hard fault.  The variable was being optimized out which was shifting an array which aligned it hence stopping the hard fault.  Problem was actually occurring when a uint32 pointer was being pointed to the misaligned array.  

Making sure the array is aligned  :static uint8_t u8DataBuff[WRITE_BLOCK_SIZE]  __attribute((aligned (4))) solves it.

View solution in original post

0 Kudos
11 Replies
1,500 Views
bobpaddock
Senior Contributor III

Which compiler are you using? It should be warning that at 32 bit wide value is being written to an 8 bit wide space: u8XX = u32XX;

0 Kudos
1,500 Views
paulrobinson
Contributor II

Using GCC in Codewarrior.  It doesn't produce a warning but I'm sure there are options available where it would.  Shouldn't cause a hard fault interrupt though and casting to a u8 doesn't help

0 Kudos
1,500 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Paul Robinson:

Another cause of hardfault is an unaligned memory access. The ARM Cortex M0+ in the KE02 requires memory accesses to be word aligned (32-bit).

For this kind of issue it is useful to debug at the assembly code level, to see what is triggering the fault. If possible please share your project so I can replicate the issue and try to find the root cause.

Regards!

Jorge Gonzalez

1,500 Views
paulrobinson
Contributor II

Sorry Jorge, the project I attached is actually working as I had been experimenting with some of the settings.  Data sections (-fdata-sections) needs to be selected under optimizations for the problem to occur (this was set by default and recommended by Freescale).  Hope this helps you identify the problem.

0 Kudos
1,501 Views
paulrobinson
Contributor II

Have been over this again and discovered that while removing a line of code was making the problem go away, it was not the cause of the hard fault.  The variable was being optimized out which was shifting an array which aligned it hence stopping the hard fault.  Problem was actually occurring when a uint32 pointer was being pointed to the misaligned array.  

Making sure the array is aligned  :static uint8_t u8DataBuff[WRITE_BLOCK_SIZE]  __attribute((aligned (4))) solves it.

0 Kudos
1,500 Views
mjbcswitzerland
Specialist V

Paul

Note that misaligned accesses lead to a hard fault on Cortex M0+. The same code will however run on a Cortex M4 Kintetis since this supports misaligned access - therefore it is possible that projects developed on a Kinetis K part will suddenly fail when tried on a KE part if alignment was not fully considered.

Another technique to ensure alignment (when 32 bit content access is to be used) is to do

static unsigned long u8DataBuff[WRITE_BLOCK_SIZE/sizeof(unsigned long)];

- this assumes that WRITE_BLOCK_SIZE is divisible by 4, which would probably be the case when 32 bit pointers are used to access its content.

- it may need a casting when using the buffer content as bytes but has the advantage that the attribute is not required. The advantage of avoiding the attribute is because it is non-portable due to the fact that different compilers do it different ways and so if you needed to move code to a different environement (or someone else needs to do it in the future) it will avoid possible complications trying to find out why it won't build and then how to solve it in the other environment.

Regards

Mark

1,500 Views
paulrobinson
Contributor II

Thanks Mark, that's a good suggestion

0 Kudos
1,500 Views
paulrobinson
Contributor II

Hi Jorge

Yes, this has been suggested to me and changing to Optimization level from 0s to 02 appears to fix the issue and I the memory map shows that there are fill bytes inserted after the problem variable (u8MCU_ID_InfoLength).  I don't know why I am only seeing this problem now though and need to optimize for size to keep code size down as this is a bootloader.

Have attached codewarrior project, hope you can make some sense of it.

0 Kudos
1,500 Views
bobpaddock
Senior Contributor III

I've had problems with using -Os that optimizes for size as it has caused me alignment issues therefore always use -O2. In some processors, notably AVR-LibC, library functions don't work correctly unless optimization is enabled. -O3 can be to aggressive.  I've seen it generate bad code on other processors.

0 Kudos
1,500 Views
paulrobinson
Contributor II

I have always used -Os and not come across this problem before so its interesting to hear that you have had alignment issues in the past.  Its not really an option for me to switch to -O2 though in this project as it is a bootloader and to protect it I will need to sacrifice half of my 16K flash which won't leave enough room for my application.

0 Kudos
1,500 Views
bobpaddock
Senior Contributor III

Add -Wall and -Wextra to the compiler flags. Also look at the map file to see if running out of RAM space or a stack overflow.  Frequent causes for problems like this that make no sense, in that the problem is actually someplace else but the symptoms show up here.

0 Kudos