Debugging improvements.

This forum is dedicated to feedback, discussions about ongoing or future developments, ideas and suggestions regarding the ChibiOS projects are welcome. This forum is NOT for support.
User avatar
barthess
Posts: 861
Joined: Wed Dec 08, 2010 7:55 pm
Location: Minsk, Belarus
Been thanked: 7 times

Re: Debugging improvements.

Postby barthess » Fri Nov 07, 2014 10:42 am

russian wrote:is there a version of this without labels?

I have no such version and never used IAR.

User avatar
russian
Posts: 364
Joined: Mon Oct 29, 2012 3:17 am
Location: Jersey City, USA
Has thanked: 16 times
Been thanked: 14 times

Re: Debugging improvements.

Postby russian » Fri Nov 07, 2014 5:59 pm

Another random potential debugging improvement: int getRemainingStack(Thread *otp) method which could be used for debug-time assertions. Not sure if that's even possible on all the platforms, but that's an option at least sometimes
GCC stm32:

Code: Select all

int getRemainingStack(Thread *otp) {

#if CH_DBG_ENABLE_STACK_CHECK
   register struct intctx *r13 asm ("r13");
   otp->activeStack = r13;

   int rs;
   if (dbg_isr_cnt > 0) {
      // ISR context
      rs = (stkalign_t *) (r13 - 1) - &__main_stack_base__;
   } else {

      rs = (stkalign_t *) (r13 - 1) - otp->p_stklimit;
   }
   otp->remainingStack = rs;
   return rs;
#else
   return 99999;
#endif /* CH_DBG_ENABLE_STACK_CHECK */
}


IAR stm32:

Code: Select all

int getRemainingStack(Thread *otp) {
#if CH_DBG_ENABLE_STACK_CHECK || defined(__DOXYGEN__)
   int remainingStack;
   if (dbg_isr_cnt > 0) {
      remainingStack = 999; // todo
   } else {
      remainingStack = (stkalign_t *)(__get_SP() - sizeof(struct intctx)) - otp->p_stklimit;
   }
   otp->remainingStack = remainingStack;
   return remainingStack;
#else
   return 999999;
#endif 
}

steved
Posts: 823
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 135 times

Re: Debugging improvements.

Postby steved » Mon Mar 13, 2017 3:47 pm

Came across this while attempting to debug an unhandled exception error, and found it extremely helpful in locating the problem.

I made a couple of additions to barthess' file, and integrated it into the ARMCMx vectors.c file.

In debug mode it's now possible to set a local variable and step out of the exception handler; won't work in all situations, but can help in determining the precise location of a problem.

Could be useful to add lots more comments as an aide-memoire of what the various registers do, to save trying to make sense of the programming manual.

This is the sort of thing which could justify separate 'Debug' and 'Release' compile profiles (so debug code is excluded from the final binary).
Attachments
vectors.zip
(4.09 KiB) Downloaded 314 times

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Debugging improvements.

Postby Giovanni » Mon Mar 13, 2017 4:10 pm

Having two profiles (or multiple) could be useful but it would require heavy changes to the makefiles system.

We should do this in next cycle, after 17.3.

Giovanni

genosensor
Posts: 65
Joined: Thu Oct 03, 2013 1:06 am
Location: Santa Cruz, California
Has thanked: 1 time
Been thanked: 1 time

Re: Debugging improvements.

Postby genosensor » Thu Mar 23, 2017 3:29 am

Just adding another vote for a polled output mode in serial drivers so that panic messages can be output when no debugger is attached. I hacked this into the STM32L serial drivers, but there's no reason it couldn't be done more generically:

Code: Select all

/**
 * @brief   Switch to polling mode (disable interrupts)
 *
 * @param[in] sdp       communication channel associated to the USART
 */
void sd_lld_pollMode(SerialDriver *sdp) {
  USART_TypeDef *u = sdp->usart;
  u->CR1 &=
    ~(USART_CR1_TXEIE | USART_CR1_TCIE | USART_CR1_RXNEIE | USART_CR1_PEIE);
  u->CR2 &= ~USART_CR2_LBDIE;
  u->CR3 &= ~USART_CR3_EIE;
}


/**
 * @brief   Output byte in polling mode
 *
 * @param[in] sdp       communication channel associated to the USART
 */
void sd_lld_xmitByte(SerialDriver *sdp, uint8_t b) {
  USART_TypeDef *u = sdp->usart;
  while (!(u->SR & USART_SR_TXE)) ;
  u->DR = b;
}
- brent

User avatar
Giovanni
Site Admin
Posts: 14444
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1074 times
Been thanked: 921 times
Contact:

Re: Debugging improvements.

Postby Giovanni » Thu Mar 23, 2017 8:34 am

Hi,

Do you mind posting this in the bug reports forum? it is a good idea for HAL6, next development cycle.

Giovanni

plyatov
Posts: 25
Joined: Tue Feb 25, 2014 10:24 am
Been thanked: 2 times

Re: Debugging improvements.

Postby plyatov » Fri Dec 01, 2017 2:00 pm

Hello!

I have made some improvements in the exceptionvectors.c
It allow to display a backtrace in the GDB if DEBUG_BACKTRACE defined.
Additionally, HardFault_Handler() improved to show local variables by "i loc" even if optimization is enabled at Makefile.

Code: Select all

/*
 * If a serious error occurs, one of the fault
 * exception vectors in this file will be called.
 *
 * This file attempts to aid the unfortunate debugger
 * to blame someone for the crashing code
 *
 *  Created on: 12.06.2013
 *      Author: uli
 *
 * Released under the CC0 1.0 Universal (public domain)
 */
#include <stdint.h>
#include <ch.h>
#include <string.h>

// Can be uncommented to see backtrace.
#define DEBUG_BACKTRACE

/**
 * Executes the BKPT instruction that causes the debugger to stop.
 * If no debugger is attached, this will be ignored
 */
#define bkpt() __asm volatile("BKPT #0\n")

void NMI_Handler(void) {
    //TODO
    while(1);
}

//See http://infocenter.arm.com/help/topic/com.arm.doc.dui0552a/BABBGBEC.html
typedef enum  {
    Reset = 1,
    NMI = 2,
    HardFault = 3,
    MemManage = 4,
    BusFault = 5,
    UsageFault = 6,
} FaultType;

/* On hard fault, copy FAULT_PSP to the sp reg so gdb can give a trace */
void **FAULT_PSP;
register void *stack_pointer asm("sp");

void HardFault_Handler(void) {
#ifdef DEBUG_BACKTRACE
    asm("mrs %0, psp" : "=r"(FAULT_PSP) : :);
    stack_pointer = FAULT_PSP;
    // Here will be good to assert Error LED, like
    // GPIOA->ODR |= 1;
    while(1);
#else
    //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info
    //Get thread context. Contains main registers including PC and LR
    struct port_extctx ctx;

    memcpy(&ctx, (void*)__get_PSP(), sizeof(struct port_extctx));
    //Interrupt status register: Which interrupt have we encountered, e.g. HardFault?
    FaultType hf_faultType = (FaultType)__get_IPSR();
    //(void)hf_faultType;
    //For HardFault/BusFault this is the address that was accessed causing the error
    uint32_t faultAddress = SCB->BFAR;
    //(void)faultAddress;
    //Flags about hardfault / busfault
    //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference
    bool isFaultPrecise = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 1) ? true : false);
    bool isFaultImprecise = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 2) ? true : false);
    bool isFaultOnUnstacking = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 3) ? true : false);
    bool isFaultOnStacking = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 4) ? true : false);
    bool isFaultAddressValid = ((SCB->CFSR >> SCB_CFSR_BUSFAULTSR_Pos) & (1 << 7) ? true : false);

    // This is to prevent variables to be optimized out
    if ((ctx.r0 != ctx.r1) && (ctx.xpsr != ctx.pc) && (faultAddress != 2))
        asm("nop");
    if (hf_faultType != 2)
        asm("nop");
    if (isFaultPrecise)
        asm("nop");
    if (isFaultImprecise)
        asm("nop");
    if (isFaultOnUnstacking)
        asm("nop");
    if (isFaultOnStacking)
        asm("nop");
    if (isFaultAddressValid)
        asm("nop");
    if ( hf_faultType)
        asm("nop");
    //Cause debugger to stop. Ignored if no debugger is attached
    bkpt();
    NVIC_SystemReset();
#endif
}

void BusFault_Handler(void) __attribute__((alias("HardFault_Handler")));

void UsageFault_Handler(void) {
#ifdef DEBUG_BACKTRACE
    asm("mrs %0, psp" : "=r"(FAULT_PSP) : :);
    stack_pointer = FAULT_PSP;
    while(1);
#else
    //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info
    //Get thread context. Contains main registers including PC and LR
    struct port_extctx ctx;
    memcpy(&ctx, (void*)__get_PSP(), sizeof(struct port_extctx));
    (void)ctx;
    //Interrupt status register: Which interrupt have we encountered, e.g. HardFault?
    FaultType faultType = (FaultType)__get_IPSR();
    (void)faultType;
    //Flags about hardfault / busfault
    //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference
    bool isUndefinedInstructionFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 0) ? true : false);
    bool isEPSRUsageFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 1) ? true : false);
    bool isInvalidPCFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 2) ? true : false);
    bool isNoCoprocessorFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 3) ? true : false);
    bool isUnalignedAccessFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 8) ? true : false);
    bool isDivideByZeroFault = ((SCB->CFSR >> SCB_CFSR_USGFAULTSR_Pos) & (1 << 9) ? true : false);
    (void)isUndefinedInstructionFault;
    (void)isEPSRUsageFault;
    (void)isInvalidPCFault;
    (void)isNoCoprocessorFault;
    (void)isUnalignedAccessFault;
    (void)isDivideByZeroFault;
    bkpt();
    NVIC_SystemReset();
#endif
}

void MemManage_Handler(void) {
#ifdef DEBUG_BACKTRACE
    asm("mrs %0, psp" : "=r"(FAULT_PSP) : :);
    stack_pointer = FAULT_PSP;
    while(1);
#else
   //Copy to local variables (not pointers) to allow GDB "i loc" to directly show the info
    //Get thread context. Contains main registers including PC and LR
    struct port_extctx ctx;
    memcpy(&ctx, (void*)__get_PSP(), sizeof(struct port_extctx));
    (void)ctx;
    //Interrupt status register: Which interrupt have we encountered, e.g. HardFault?
    FaultType faultType = (FaultType)__get_IPSR();
    (void)faultType;
    //For HardFault/BusFault this is the address that was accessed causing the error
    uint32_t faultAddress = SCB->MMFAR;
    (void)faultAddress;
    //Flags about hardfault / busfault
    //See http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0552a/Cihdjcfc.html for reference
    bool isInstructionAccessViolation = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 0) ? true : false);
    bool isDataAccessViolation = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 1) ? true : false);
    bool isExceptionUnstackingFault = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 3) ? true : false);
    bool isExceptionStackingFault = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 4) ? true : false);
    bool isFaultAddressValid = ((SCB->CFSR >> SCB_CFSR_MEMFAULTSR_Pos) & (1 << 7) ? true : false);
    (void)isInstructionAccessViolation;
    (void)isDataAccessViolation;
    (void)isExceptionUnstackingFault;
    (void)isExceptionStackingFault;
    (void)isFaultAddressValid;
    bkpt();
    NVIC_SystemReset();
#endif
}


Return to “Development and Feedback”

Who is online

Users browsing this forum: No registered users and 17 guests