2014-08-07 07:13 AM
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 850V_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 problemsThe .map file looks like:0x20001268 other variable0x2000126c data array0x2000478c other variable, can be ead and written0x20004790 other variable, can be ead and written0x20004858 other variable, can be ead and written0x2000485c other variable, can be ead and writtenThe corrupt data starts at0x2000126c + 670 * 16 = 15436 => 0x20003C4CThe crash address is at0x2000126c + 697 * 16 = 15868 => 0x20003DFCThe 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 0x00x20004a04 __end__ = .0x20004a04 _end = __end__0x20004a04 end = __end__*(.heap*)0x20004a04 __HeapLimit = ..co_stack 0x20004a04 0x404 load address 0x0801377c0x20004a08 . = ALIGN (0x8)*fill* 0x20004a04 0x4 *(.co_stack .co_stack.*).co_stack 0x20004a08 0x400 ..\obj\startup_stm32f10x_md.o0x20004a08 pulStack0x20005000 __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 #stm322014-08-07 07:37 AM
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).
2014-08-07 09:02 AM
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.2014-08-08 03:00 AM
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 testedvolatile int stack = 0;printf (''%X\n\r'', (long) &stack);Which resulted in20003EFCWhich is inside my array0x20001268 other variable0x2000126c data array0x2000478c other variable, can be ead and written0x20004790 other variable, can be ead and written0x20004858 other variable, can be ead and written0x2000485c other variable, can be ead and writtenThus 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 20003F24heap and stack are located at..heap 0x20004a04 0x00x20004a04 __end__ = .0x20004a04 _end = __end__0x20004a04 end = __end__*(.heap*)0x20004a04 __HeapLimit = ..co_stack 0x20004a04 0x404 load address 0x08013a1c0x20004a08 . = ALIGN (0x8)*fill* 0x20004a04 0x4 *(.co_stack .co_stack.*).co_stack 0x20004a08 0x400 ..\obj\startup_stm32f10x_md.o0x20004a08 pulStack0x20005000 __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_SIZEuint32_t FLASH_SIZE = 0xCC00; // 51 kBJumpAddress = *(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.2014-08-08 04:02 AM
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.2014-08-08 04:50 AM
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:20004E08800502D80079AD80079B980079D180079E98007A01000SP should then be set to 20004E08, which looks correct. Right?2014-08-08 06:36 AM
''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?2014-08-08 07:02 AM
Vector table is aligned to 32 bytes:
0x3400/32 = 416Or 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 0x3400void 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?2014-08-08 07:13 AM
''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.h2014-08-08 08:14 AM
I get
undefined reference to `__get_MSP when I try to call itand if i try to #include core_cmFunc.hI 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'