Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I debug unexpected resets in a STM32 device?

I'm doing some development in C with a STM32F107 chip and, at some point, the device began to reset when I call a specific function. I don't have a debugger and my debugging is just plain text over a serial port.

I've used some other microcontrollers in which I was able to access a register to see the cause of the reset, but I can't seem to find an equivalent for this device. I'm aware of the hardware exceptions of the Cortex-M3, but I don't know if one of them is being triggered since I can't seem to send text over usart when I'm inside those handlers (maybe because my TX functions use interruptions?).

So, I decided to ask people with more experience than I in this device: what is usually done to debug situations like these?

EDIT

One of the developers activated the WWDG watchdog and it was reseting the hardware before I could get my info from the fault handlers. It was a Hard Fault due to calling a function by a pointer that was pointing to the wrong place. However, I will keep this question in the hope that someone will give more details (or material about it) for pointing back to C code from the registers saved in, lets say, a Hard Fault (@dwelch idea).

like image 578
ivarec Avatar asked Jan 10 '12 16:01

ivarec


3 Answers

You can use below code for debugging.

void HardFault_Handler(void)
{
    __asm volatile
       (
           " tst lr, #4                                                \n"
           " ite eq                                                    \n"
           " mrseq r0, msp                                             \n"
           " mrsne r0, psp                                             \n"
           " ldr r1, [r0, #24]                                         \n"
           " ldr r2, handler2_address_const                            \n"
           " bx r2                                                     \n"
           " handler2_address_const: .word prvGetRegistersFromStack    \n"
       );

  /* Go to infinite loop when Hard Fault exception occurs */
  while (1)
  {
  }
}

Also add this as well.

void prvGetRegistersFromStack( uint32_t *pulFaultStackAddress )
{
    /* These are volatile to try and prevent the compiler/linker optimising them
    away as the variables never actually get used.  If the debugger won't show the
    values of the variables, make them global my moving their declaration outside
    of this function. */
    volatile uint32_t r0;
    volatile uint32_t r1;
    volatile uint32_t r2;
    volatile uint32_t r3;
    volatile uint32_t r12;
    volatile uint32_t lr; /* Link register. */
    volatile uint32_t pc; /* Program counter. */
    volatile uint32_t psr;/* Program status register. */

    r0 = pulFaultStackAddress[ 0 ];
    r1 = pulFaultStackAddress[ 1 ];
    r2 = pulFaultStackAddress[ 2 ];
    r3 = pulFaultStackAddress[ 3 ];

    r12 = pulFaultStackAddress[ 4 ];
    lr = pulFaultStackAddress[ 5 ];
    pc = pulFaultStackAddress[ 6 ];
    psr = pulFaultStackAddress[ 7 ];

    /* When the following line is hit, the variables contain the register values. */
    for( ;; );
}

I am using this to get any value of the register before going into hardfault. You can also add more registers if you like.

like image 144
Dheeraj Kumar Avatar answered Sep 23 '22 07:09

Dheeraj Kumar


The Cortex M3 has excellent fault handling features that will make your life easier. On hitting a fault, it automatically stacks several registers like PC and LR, and fault status registers will tell you things like address of bus fault, etc.

You should implement a good fault handler (for example, the hard fault handler here: http://blog.frankvh.com/2011/12/07/cortex-m3-m4-hard-fault-handler/) to print out the stacked registers and debug fault status registers.

You should use the UART for printing, just write your own simple custom version of printf for use from your fault handler that doesn't depend on interrupts. Just write bytes directly to uart Tx data register and poll for byte completion.

like image 11
TJD Avatar answered Oct 14 '22 21:10

TJD


Aside from what has been mentioned about the interrupt handlers for debugging, some ST micros also have a reset source register that you can read on power-up (that is after a reset). For the cortex M family (m0/m3/m4) the register is RCC_CSR. http://www.st.com/web/en/resource/technical/document/reference_manual/DM00031020.pdf

Unfortunately you wouldn't be able to know whether the specifics, such as hard fault but it would tell you if the watchdog (window or independent) had tripped.

like image 3
embeddedninja Avatar answered Oct 14 '22 21:10

embeddedninja