2016-08-02 07:06 AM
Hi,
I've just soldered a second PCB with a STM32F429ZIT6. The first PCB runs perfectly, so the code seems correct. I compile, and debug the code. The code is loaded correctly because there is any complain from Keil.
I've inherited this code from my old colleage which he currently isn't in my company, so I soldered this new board according to the schematic and I’ve resoldered all solders.
So, I’ve compile the code and load through debug and starts, goes fine untill arrives in GUI_Init which crashes!
I’ve debug the code and crashes in the last line of GUI_X_Config function:
void GUI_X_Config(void) {
//
// 32 bit aligned memory area
//
#ifdef GUI_BUFFER_IN_EXT_RAM
static U32 aMemory[GUI_NUMBYTES / 4]__attribute__((at(GUI_BUFFER_ADDRESS)));
#else
static U32 aMemory[GUI_NUMBYTES / 4];
#endif
//
// Assign memory to emWin
//
GUI_ALLOC_AssignMemory(aMemory, GUI_NUMBYTES);
//
// Set default font
//
GUI_SetDefaultFont(GUI_FONT_6X8);
}
I go over to disassembly code and in the line
0x08003C6A BD10 POP {r4,pc}
The code goes to HardFault_Handler function.The disassembly code is below:
0x08003C5E 4803 LDR r0,[pc,#12] ; @0x08003C6C
0x08003C60 F7FDFF22 BL.W GUI_ALLOC_AssignMemory (0x08001AA8)
104: GUI_SetDefaultFont(GUI_FONT_6X8);
105:
0x08003C64 4802 LDR r0,[pc,#8] ; @0x08003C70
0x08003C66 F7FFFD81 BL.W GUI_SetDefaultFont (0x0800376C)
106: }
0x08003C6A BD10 POP {r4,pc}
0x08003C6C 0000 DCW 0x0000
0x08003C6E D060 DCW 0xD060
0x08003C70 0B30 DCW 0x0B30
0x08003C72 0804 DCW 0x0804
88: {
0x08003C74 B510 PUSH {r4,lr}
Is it possible that the code is the problem?
If, for example, the display is not connect correctly should be the problem?
What does exactly GUI_Init function? does it check the hardware?
Thanks!
#crash #emwin #hangs #gui_init2016-08-02 07:35 AM
It suggests you are trashing the stack, most likely because it is too small.
You should fill the stack with a pattern you can recognize in the debuggers ''Memory View'' and confirm how much you are using, and the state of the return addresses it is about to pop off the stack. Some of the Segger Init code checks that RAM addresses provided can read/write properly, if these are bogus addresses the system could fault. You'd have to review the registers and faulting instructions to be sure.2016-08-02 08:49 AM
ST also has code that checks the CRC Peripheral is functioning. There are a couple of loops in the library, make sure you know where it is, and what the disassembly suggests it is doing.
Hard Faults are more a function of doing, or touching something, inappropriately so review the faulting state presented by the processor, ideally with something more advanced than a while(1); loop.2016-08-02 08:53 AM
In Keil, I do it this way..
//*****************************************************************************
/*
HardFault_Handler\
PROC
EXPORT HardFault_Handler
TST lr, #4 ; Determine correct stack
ITE EQ
MRSEQ R0, MSP ; Read MSP (Main)
MRSNE R0, PSP ; Read PSP (Process)
MOV R1, R4 ; Registers R4-R6
MOV R2, R5
MOV R3, R6 ; sourcer32@gmail.com
EXTERN hard_fault_handler_c
B hard_fault_handler_c
ENDP
*/
void hard_fault_handler_c(unsigned int * hardfault_args, unsigned int r4, unsigned int r5, unsigned int r6)
{
printf (''[Hard Fault]
''); // After Joseph Yiu
printf (''r0 = %08X, r1 = %08X, r2 = %08X, r3 = %08
X'',
hardfault_args[0], hardfault_args[1], hardfault_args[2], hardfault_args[3]);
printf (''r4 = %08X, r5 = %08X, r6 = %08X, sp = %08
X'',
r4, r5, r6, (unsigned int)&hardfault_args[8]);
printf (''r12= %08X, lr = %08X, pc = %08X, psr= %08
X'',
hardfault_args[4], hardfault_args[5], hardfault_args[6], hardfault_args[7]);
printf (''bfar=%08X, cfsr=%08X, hfsr=%08X, dfsr=%08X, afsr=%08
X'',
*((volatile unsigned int *)(0xE000ED38)),
*((volatile unsigned int *)(0xE000ED28)),
*((volatile unsigned int *)(0xE000ED2C)),
*((volatile unsigned int *)(0xE000ED30)),
*((volatile unsigned int *)(0xE000ED3C)) );
while(1);
}
//****************************************************************************
2016-08-03 04:00 AM
Hi Clive1,
Thank you for your answer but I don't undestand what I have to do. I'm a junior programmer and there are some functionalities which I don't know but I would like to learn. ''You should fill the stack with a pattern you can recognize in the debuggers ''Memory View'' and confirm how much you are using, and the state of the return addresses it is about to pop off the stack.''I've open Memory 1 tap view but I don't know what I have to view. If you want tell me is that in which memory address the code is all 00, it starts in 0x3CD14CB3. ''Some of the Segger Init code checks that RAM addresses provided can read/write properly, if these are bogus addresses the system could fault. You'd have to review the registers and faulting instructions to be sure.''How I can do this?Thx.2016-08-03 04:08 AM
''ST also has code that checks the CRC Peripheral is functioning''
ok, where I can achieve it?''Hard Faults are more a function of doing, or touching something, inappropriately so review the faulting state presented by the processor, ideally with something more advanced than a while(1); loop.''okThanks2016-08-03 04:12 AM
In my case, the HardFault_Handler is declared as:
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
}
/* USER CODE BEGIN HardFault_IRQn 1 */
/* USER CODE END HardFault_IRQn 1 */
}
So, how can I add variables as your example?
Thanks
2016-08-03 06:03 AM
I'm a junior programmer...
Ok, what does that mean these days, how old and what amount of schooling? Go into startup_stm32fxxx.s and check the stack allocation, if it is only 1KB (0x400) make it bigger.; Amount of memory (in bytes) allocated for Stack
; Tailor this value to your application needs
; <
h
> Stack Configuration
; <
o
> Stack Size (in Bytes) <
0x0-0xFFFFFFFF:8
>
; </
h
>
Stack_Size EQU 0x00001000
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
__initial_sp
In main() you'd want to fill the stack with something you can recognize by sight, ie memset() it with 0xCD bytes, so the unused 32-bit words look like 0xCDCDCDCD. Remember the stack starts at the top of the region, and moves down, it will bounce up/down as you enter/exit subroutines with local variables, and as you descend the call tree. The key is to understand the maximal depth (usage) so that you allocate enough to handle all your local/auto variables. You could also use the debugger's command line to fill specific memory, with a specific pattern.
If you want to replace the Hard Fault Handler, then you're going to need to cut-n-paste the new assembler code into startup.s and replace the current handler (ie remove/rename) with the alternate C code I've provided. You'd also need to provide sufficient hosting in your system to support printf() output to a USART or SWV debug channel.
I'd recommend reviewing Joseph Yiu's Cortex-Mx books, and ARM's TRM (Technical Reference Manual) for the core you are using.
2016-08-04 07:53 AM
Hi Clive1,
Yestarday I had some problems to replay you. I'm thirty but only 8 month ago I'm working with STM32 devices. I'm new in Keil and with this environment. I've tried your advice, but I have other problem. I can't printf. I have an ULINK2/ME which can SWD but I don't know why when the system arrives at printf it hangs. I've configure the Trace as: Because my crystall is 8MHz and my core clock is 168MHz as:RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
RCC_OscInitStruct.PLL.PLLM = 8;
RCC_OscInitStruct.PLL.PLLN = 336;
RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
RCC_OscInitStruct.PLL.PLLQ = 7;
HAL_RCC_OscConfig(&RCC_OscInitStruct);
What is it happen?
Certainly the stack is defined as 0x900
2016-08-04 08:57 AM
Ok, but where does is ''hang'', the debugger provides a means to stop execution and inspect the instructions and state.
I suspect you haven't provided any hosting/retargeting of the stdio to get it to the SWV channel.//******************************************************************************
// Hosting of stdio functionality through SWV - Serial Wire Viewer
//******************************************************************************
#include <
rt_misc.h
>
#pragma import(__use_no_semihosting_swi)
struct __FILE { int handle; /* Add whatever you need here */ };
FILE __stdout;
FILE __stdin;
int fputc(int ch, FILE *f)
{
ITM_SendChar(ch);
return(ch);
}
int fgetc(FILE *f)
{
char ch;
ch = '?';
return((int)ch);
}
int ferror(FILE *f)
{
/* Your implementation of ferror */
return EOF;
}
void _ttywrch(int ch)
{
ITM_SendChar(ch);
}
void _sys_exit(int return_code)
{
label: goto label; /* endless loop */
}
//******************************************************************************