cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 HardFault_Handle

rthorstensson
Associate II
Posted on August 07, 2014 at 16:13

I have a problem in STMF103C8T7 and I can't find the solution.

The STM32 reads corrupt data in array and when reaching a certain memory adress it crashes.

The array look like this:

typedef struct

{

int32_t v1;

int32_t v2;

uint32_t v3;

short v4;

}V_Data;

&sharpdefine DATA_LENGTH 850

V_Data data[DATA_LENGTH];

Reading index 670 to 696 results in corrupt data. When writing to index 697 HardFault Exception occures. Variables after the array can be read witthout problems

The .map file looks like:

0x20001268 other variable

0x2000126c data array

0x2000478c other variable, can be ead and written

0x20004790 other variable, can be ead and written

0x20004858 other variable, can be ead and written

0x2000485c other variable, can be ead and written

The corrupt data starts at

0x2000126c + 670 * 16 = 15436 => 0x20003C4C

The crash address is at

0x2000126c + 697 * 16 = 15868 => 0x20003DFC

The STM32 has 20 kB SRAM and SRAM starts at adress 0x20000000 with size 0x00005000.

I have put protection around pointeras and arrays which could access the data array.Since Hardfault exception occurs I suspects that there is something wrong in the memory mapping.

Heap and stack are located on:

.heap 0x20004a04 0x0

0x20004a04 __end__ = .

0x20004a04 _end = __end__

0x20004a04 end = __end__

*(.heap*)

0x20004a04 __HeapLimit = .

.co_stack 0x20004a04 0x404 load address 0x0801377c

0x20004a08 . = ALIGN (0x8)

*fill* 0x20004a04 0x4 

*(.co_stack .co_stack.*)

.co_stack 0x20004a08 0x400 ..\obj\startup_stm32f10x_md.o

0x20004a08 pulStack

0x20005000 __StackTop = (ORIGIN (ram) + 0x5000)

0x20004bfc __StackLimit = (__StackTop - SIZEOF (.co_stack))

0x20005000 PROVIDE (__stack, __StackTop)

0x00000001 ASSERT ((__StackLimit >= __HeapLimit), region ram overflowed with stack)

I am using GCC 4.8.2 and CooCox 1.7.6

#stm32
16 REPLIES 16
schauer
Associate II
Posted on August 07, 2014 at 16:37

You could use the content of SCB_HFSR and SCB_CFSR registers when in Hardfault to further track the issue down (see PM0056 for details). Anyway it might be good to know the contents of the SCB registers to see more clear (in the best case).

Posted on August 07, 2014 at 18:02

Evaluate what amount of auto/local variable you're using and if your stack size is adequate. The kind of failure you describe sounds like a statics/heap/stack collision.

Get a Joseph Yiu style Hard Fault handler set up, look at the registers and assembler code at the fault, and try to understand how it got into that state.
Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
rthorstensson
Associate II
Posted on August 08, 2014 at 12:00

I have tested to write a debugloop which is run in main loop before ''real application'' starts. In this I can read/write into any index in the array and I still get the same problems with corrupt values and hard fault

To find the stack pointer I tested

volatile int stack = 0;

printf (''%X\n\r'', (long) &stack);

Which resulted in

20003EFC

Which is inside my array

0x20001268 other variable

0x2000126c data array

0x2000478c other variable, can be ead and written

0x20004790 other variable, can be ead and written

0x20004858 other variable, can be ead and written

0x2000485c other variable, can be ead and written

Thus something messas up the stack pointer.

At the start of mani as soon as I have init RCC and UART I get the following address 20003F24

heap and stack are located at.

.heap 0x20004a04 0x0

0x20004a04 __end__ = .

0x20004a04 _end = __end__

0x20004a04 end = __end__

*(.heap*)

0x20004a04 __HeapLimit = .

.co_stack 0x20004a04 0x404 load address 0x08013a1c

0x20004a08 . = ALIGN (0x8)

*fill* 0x20004a04 0x4 

*(.co_stack .co_stack.*)

.co_stack 0x20004a08 0x400 ..\obj\startup_stm32f10x_md.o

0x20004a08 pulStack

0x20005000 __StackTop = (ORIGIN (ram) + 0x5000)

0x20004bfc __StackLimit = (__StackTop - SIZEOF (.co_stack))

0x20005000 PROVIDE (__stack, __StackTop)

0x00000001 ASSERT ((__StackLimit >= __HeapLimit), region ram 

I am now guessing that the stackpointer is not correctly set when I jump from my own written bootlaoder to my application.

Just when I jump from bootloader to applicatoin the following code is run:

#define BL_FLASH_START 0x08000000

#define BL_FLASH_SIZE 0x3400 // 13 kB

#define FLASH_START BL_FLASH_START + BL_FLASH_SIZE

uint32_t FLASH_SIZE = 0xCC00; // 51 kB

JumpAddress = *(uint32_t*) (FLASH_START + 4);

Jump_To_Application = (pFunction) JumpAddress;

sprintf(string, ''Address %X\r\n'', *(uint32_t*)JumpAddress);

Print(string);

/* Initialize user application's Stack Pointer */

__set_MSP(*(uint32_t*) FLASH_START);

Jump_To_Application();

The stack in application is set to

/**

  *@brief The minimal vector table for a Cortex M3.  Note that the proper constructs

  *       must be placed on this to ensure that it ends up at physical address

  *       0x00000000.  

  */

__attribute__ ((used,section(''.isr_vector'')))

void (* const g_pfnVectors[])(void) =

{       

  /*----------Core Exceptions-------------------------------------------------*/

  (void *)&pulStack[STACK_SIZE],     /*!< The initial stack pointer         */

  Reset_Handler,                /*!< Reset Handler                            */

  NMI_Handler,                  /*!< NMI Handler                              */

  HardFault_Handler,            /*!< Hard Fault Handler                       */

  MemManage_Handler,            /*!< MPU Fault Handler                        */

  BusFault_Handler,             /*!< Bus Fault Handl

I can't find where the stack is initiated in the application.

chen
Associate II
Posted on August 08, 2014 at 13:02

Hi

''I am now guessing that the stackpointer is not correctly set when I jump from my own written bootlaoder to my application.''

''I can't find where the stack is initiated in the application.''

The very first thing in the binary of the application should be a vector table.

The starting stack address is provided in the vector table as the first item.

The 2nd item is the start address of the application.

rthorstensson
Associate II
Posted on August 08, 2014 at 13:50

 Thanks.

The following code  

for(c = 0; c < 50; c++)

{

sprintf(string, ''%X\r\n'', (unsigned int)*(uint32_t*)(0x08003400 + c *4));

Print(string);

}

returns the following:

20004E08

800502D

80079AD

80079B9

80079D1

80079E9

8007A01

0

0

0

SP should then be set to 20004E08, which looks correct. Right?

chen
Associate II
Posted on August 08, 2014 at 15:36

''SP should then be set to 20004E08, which looks correct. Right?''

0x20004e08 is a valid RAM address (from the reference manual).

I do not know if that is the correct stack pointer.

I think the location of the application program looks suspect :

''#define BL_FLASH_START 0x08000000

#define BL_FLASH_SIZE 0x3400 // 13 kB

#define FLASH_START BL_FLASH_START + BL_FLASH_SIZE''

The vector table of the application must be on a  'minimum alignment is 32 words'

Does the application change the vector table address/offset using the VTOR register?

rthorstensson
Associate II
Posted on August 08, 2014 at 16:02

Vector table is aligned to 32 bytes:

0x3400/32 = 416

Or have I missunderstodd the alignment requirement?

System init where VTOR is set is executed before jump to main:

void SystemInit (void)

{

  /* Reset the RCC clock configuration to the default reset state(for debug purpose) */

  /* Set HSION bit */

  RCC->CR |= (uint32_t)0x00000001;

  /* Reset SW, HPRE, PPRE1, PPRE2, ADCPRE and MCO bits */

#ifndef STM32F10X_CL

  RCC->CFGR &= (uint32_t)0xF8FF0000;

#else

  RCC->CFGR &= (uint32_t)0xF0FF0000;

#endif /* STM32F10X_CL */   

  

  /* Reset HSEON, CSSON and PLLON bits */

  RCC->CR &= (uint32_t)0xFEF6FFFF;

  /* Reset HSEBYP bit */

  RCC->CR &= (uint32_t)0xFFFBFFFF;

  /* Reset PLLSRC, PLLXTPRE, PLLMUL and USBPRE/OTGFSPRE bits */

  RCC->CFGR &= (uint32_t)0xFF80FFFF;

#ifdef STM32F10X_CL

  /* Reset PLL2ON and PLL3ON bits */

  RCC->CR &= (uint32_t)0xEBFFFFFF;

  /* Disable all interrupts and clear pending bits  */

  RCC->CIR = 0x00FF0000;

  /* Reset CFGR2 register */

  RCC->CFGR2 = 0x00000000;

#elif defined (STM32F10X_LD_VL) || defined (STM32F10X_MD_VL) || (defined STM32F10X_HD_VL)

  /* Disable all interrupts and clear pending bits  */

  RCC->CIR = 0x009F0000;

  /* Reset CFGR2 register */

  RCC->CFGR2 = 0x00000000;      

#else

  /* Disable all interrupts and clear pending bits  */

  RCC->CIR = 0x009F0000;

#endif /* STM32F10X_CL */

    

#if defined (STM32F10X_HD) || (defined STM32F10X_XL) || (defined STM32F10X_HD_VL)

  #ifdef DATA_IN_ExtSRAM

    SystemInit_ExtMemCtl(); 

  #endif /* DATA_IN_ExtSRAM */

#endif 

  /* Configure the System clock frequency, HCLK, PCLK2 and PCLK1 prescalers */

  /* Configure the Flash Latency cycles and enable prefetch buffer */

  SetSysClock();

#ifdef VECT_TAB_SRAM

  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM. */

#else

  SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH. */

#endif 

}

I set up Vector table in NVIC:

#define NVIC_VectTab_RAM             ((uint32_t)0x20000000)

#define NVIC_VectTab_FLASH           ((uint32_t)0x08000000)

#define USE_BOOTLOADER

#define BOOT_LOADER_SIZE 0x3400

void NVIC_Configuration(void)

{

#ifdef USE_BOOTLOADER

NVIC_SetVectorTable(NVIC_VectTab_FLASH, BOOT_LOADER_SIZE);

#else

NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0);

....

}

I think I will save stack pointer at different locations in the code, before UART is setup so I can output them on UART. How can I access the SP as a C-variable?

chen
Associate II
Posted on August 08, 2014 at 16:13

''Vector table is aligned to 32 bytes:

0x3400/32 = 416

Or have I missunderstodd the alignment requirement?''

OK, I was just too lazy to work it out (a point clive1 always picks up on!).

''System init where VTOR is set is executed before jump to main:''

OK, just checking.

''How can I access the SP as a C-variable?''

This is very dependant on the system you are working with.

With the CMSYS that ST provide try :

__get_MSP()

found in core_cmFunc.h

rthorstensson
Associate II
Posted on August 08, 2014 at 17:14

I get 

undefined reference to `__get_MSP when I try to call it

and if i try to #include core_cmFunc.h

I get the following errors:

error: unknown type name '__STATIC_INLINE'

       [cc]  __attribute__( ( always_inline ) ) __STATIC_INLINE uint32_t __get_BASEPRI(void)

       [cc]  ^

 expected '=', ',', ';', 'asm' or '__attribute__' before '__get_BASEPRI'