2014-01-21 01:43 PM
Hi all,
I''ve spent three strange nights of trying to find solution for the following issue.
No success yet.I'll be very glad for any advice how to solve it.
I've designed a board with STM32L152CBT6 (48pins)
Low power MCU 128kb Flash, 16kb RAM
Running on 32Mhz HSI
gcc 4.7.2 CodeSourcery, C/C++ with stdlib.
Stack size 0x400
The board contains just the MCU, SWD pins for Segger JLink connection for debugging and CC11001 RF 868Mhz module from Alibaba attached via 2mm spacing header and LED.
The power source is 1A DCDC converter TracoPower 3,3V.
The MCU has proper blocking capacitors 100nf (+1uF for VDDA).
The MCU uses SPI2 (PB12 CS, PB13 CLK, PB14 MISO, PB15 MOSI) and PB5 for IRQ handler EXTI_Line5.
I'm running my RF packet library for the Radio as a test case.
At first I need to mention that the same library/test I'm running without any issue on STMF4 Discovery Kit, self-designed board with STM32F103VC and as well on STM32L152 Discovery board.The last STM32L152RBT6 MCU is almost the same MCU with the same memory configuration, just with 64 pins.
So what is the issue:
The issue is Hard Faults during execution. The Hard Fault occurrence is irregular but typically it happens when a packet is sent via RF. Sometimes this is the first packet sometimes it is running stable but when i touch a board the Hard fault occurres. The packet send consumes up to 30mA current.
After three days of testing I have found a workaround how deal with.
It is enough just to put this code during board initialization
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_40MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOB, &GPIO_InitStructure);
The code only initializes the pin PB6 as output on already running GPIOB clock.
That's enough. No setting on/off the pin is needed and the board immediately running perfectly stable like on other boards I've mentioned before.
The PB6 is connected via SMD LED a resistor 750R to ground.
The voltage on the pin is at about 5mV.
When I've tried to remove the LED from board the Hard Fault returned back immediately.
I've tried to build another copy of the board to eliminate the MCU problem, the PCB problem, soldering problem etc.
And the result? The second board has the same strange problem.
Thank you very much for your advice
Regards
Jakub
#stm-forum-software-pisses-me-off #stm32-hard-fault2014-01-22 08:39 AM
There is no Interrupt vector entry pointing to address
0x20000
2014-01-22 08:46 AM
Is the RF field interfering with the hardware? Can you run a simple program on your second PCB while the first one runs the RF control software and see if it is also affected? Does your PCB and RF transmitter share the same power supply? ... the same ground?
Does it still fault if you shield the PCB (with grounded aluminium foil for example).2014-01-22 08:53 AM
At least you have some consistency.
You have the EXTI interrupt, might look at how that's configured, I'd move the clearing code to immediately after you've qualified it, otherwise it's likely to re-enter. I would focus on getting your Hard Fault handler (look's like Joseph Yiu's) working properly. Identify if ZERO is being passed in, and give a specific message in that case. I'd try the Hard Fault stuff off the debugger, let it run the handler, and be getting a very clear idea about what PC/LR come up in the faulting conditions, and then examine the assembler code around the faulting instruction. The C code is far less important.2014-01-22 10:13 AM
>You have the EXTI interrupt, might look at how that's configured, I'd move the clearing code to immediately after you've qualified it, otherwise it's likely to re-enter.
This is configuration of my EXTI handler: GPIO_InitStructure.GPIO_Pin = GPIO_Pin_GD0 ; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(GPIOB, &GPIO_InitStructure);RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOB, EXTI_PinSource5); /* Enable external interrupt */ EXTI_InitStruct.EXTI_Line = EXTI_Line5; EXTI_InitStruct.EXTI_LineCmd = ENABLE; EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_Init(&EXTI_InitStruct); /* Enable EXTI interrupts */ NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn; NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct);And this a code for EXTI IRQ handlervoid EXTI9_5_IRQHandler(void) { if(EXTI_GetITStatus(EXTI_Line5)) { if(!rf_transfer_started) { rf_transfer_started = 1; } else { rf_transfer_completed = 1; } EXTI_ClearITPendingBit(EXTI_Line5); }}>I would focus on getting your Hard Fault handler (look's like Joseph Yiu's) working properly.> Identify if ZERO is being passed in, and give a specific message in that case.I hope I have the right HardFault handler, I'm using this one https://github.com/feabhas/CM3_Fault_HandlerThe ASM code is that:HardFault_Handler: TST LR, #4 ITE EQ MRSEQ R0, MSP MRSNE R0, PSP B Hard_Fault_HandlerI hope it works wellIn Hard Fault HandlerSCB->HFSR = 0x40000000Forced Hard FaultSCB->CFSR = 0x30000Usage fault: r0 = 0x20004000r1 = 0x800e771r2 = 0x800e7c5r3 = 0x80001d8r12 = 0x800e7d1lr = 0x800e7d9pc = 0x800e7e1psr = 0x0All the addresses in registers are the lowest interrupt handlers.>I'd try the Hard Fault stuff off the debugger, let it run the handler, and be getting a very clear idea about what PC/LR come up in the faulting conditions, and then examine the assembler code around the faulting instruction. The C code is far less important.What do you mean by run it off the debugger? How will I get the result without debugger?2014-01-22 10:38 AM
2014-01-22 10:39 AM
>Is the RF field interfering with the hardware? Can you run a simple program on your second PCB while the first one runs the RF control software and see if it is also affected?
I put the RF module standalone and connected it with the main board via 10cm cables. The issue is still here. In the same HW configuration I'm running successfully the code and HW on other STM32 MCUs (F4, F1, STM32L152RBT6). > Does your PCB and RF transmitter share the same power supply? ... the same ground?Yes, yes.>Does it still fault if you shield the PCB (with grounded aluminium foil for example).I'm not able to try it. I think the test with RF board standalone is sufficient.But still, If I have configured the PB6 pin the issue is gone.2014-01-22 10:56 AM
Off Debugger : Stand-alone with diagnostic information out a serial port
It's calling your Hard Fault routine with a stack pointer of ZERO, this is not a valid address for it, and it is therefore dumping the content of the FLASH which is shadowed at ZERO. Thusvoid
Hard_Fault_Handler
(
uint32_t
stack
[])
Called as Hard_Fault_Handler(NULL); You should catch stack == NULL, because the results are useless. I'm not sure if your debugger is causing this, Keil does not.http://blog.feabhas.com/2013/02/developing-a-generic-hard-fault-handler-for-arm-cortex-m3cortex-m4/
Niall Cooling
cites Yiu2014-01-22 12:14 PM
I hope I have the right values:
In Hard Fault HandlerSCB->HFSR = 0x40000000Forced Hard FaultSCB->CFSR = 0x20400Usage fault: Bus fault: r0 = 0xfr1 = 0x20000fbcr2 = 0x20200006r3 = 0x200007acr12 = 0x8lr = 0x800a5afpc = 0x800a794psr = 0x210000002014-01-22 05:57 PM
Yes, that's a bit perplexing, looks to be signalling an INVSTATE
The code also does not appear to be optimized, but does represent the C, although I can't see the literals it's loading. Observe that the address of you Hard Fault Handler in the vector table is EVEN (0x080001D8), this will cause a failure, the entries need to be ODD, indicating THUMB code. I2C1_ER_IRQHandler I2C2_ER_IRQHandler SPI2_IRQHandler2014-01-23 04:21 AM
>The code also does not appear to be optimized, but does represent the C, although I can't see the literals it's loading.
The code is compiled by gcc 4.7.3 with no optimization -O0>Observe that the address of you Hard Fault Handler in the vector table is EVEN (0x080001D8), this will cause a failure, the entries need to be ODD, indicating THUMB code.Yes, the address was even, so I've wrapped the ASM code to C:extern void Hard_Fault_Handler(uint32_t stack[]);__attribute__ ((naked)) void HardFault_Handler(void){ __asm(''MRS r0, MSP''); __asm(''B Hard_Fault_Handler'');}Now the address of the Hard Fault handler is odd and all other handlers as well, see the next picture, the lowest part.But I'm not sure if it is OK that Eclipse debugger shows the Hardfault handler on the nearest lower even address. See the picture, red frames.After the change I had run the code again and GOT SPI2_IRQ. I was very happy but just for one minute. Because the SPI2_IRQ happened just twice from many tens of tests. :-(.For example I've got the following result:If I have breakpoint at start of the HardFault_handler, I'm able to step the handler and print the stack and so on.BUT if I remove the breakpoint the HardFault_handler crashes as shown (purple color).You can see that the function ftdi_println() at address 0x800dbcc is not called because the address is changed to 0x840dbcc. Just one bit is changed. My interpretations is that this is some memory bus problem because of hw problems. The Hard Fault is always caused by touching the PCB by my hand.Am I right?The faults in the Hard fault handler disallow me to use serial debugging without SWD :-(.But for example division by zero fault (manually added to code before the fault critical code) works well, Hard Fault handler catches it a correctly print to serial port the stack.