0
void _general_exception_handler (unsigned caused, unsigned status)
    {
       RCON = RCON_EXCEPTION;

       // Point of No return.
       Kernel_Reset();
    }

My code seems to be getting in this trap and I have few questions to figure out why it get here from calling valid functions in my code or the better question that keeps bothering me is how does the processor know there has been a violation.

1) When I look in the watch window in the debugger, the cause shows me Address 0xA0007EC0 and the value 0x10800C1C and the status shows me address 0xA0007EC4 and value is 0x00100003. How can I, From these Address and value information figure out the cause and status of the exception? 2) How does the processor know that there has been an exception fault?

Snapshots of Memory

newb7777
  • 517
  • 5
  • 22
  • 3
    Software does not know. Hardware knows. – 0___________ Jul 25 '17 at 10:23
  • Could a pointer that is initialized to NULL, `static Log_t *pLog = NULL;` cause an exception fault because it has the address NULL in it. If for example `pLog` is being used to read data from before it has been assigned a VALID ADDRESS. Since NULL would mean the beginning of memory and if you are trying to access forbidden section it throws exception fault? – newb7777 Jul 25 '17 at 21:42
  • 1
    Yup. Basically it's the hardware itself detecting invalid conditions, such as accessing memory locations that are reserved. You can check out the memory map of your MCU to get an idea of where these reserved sections are. The processor knows to call that exeception handler because when the hardware detects an exception, the exception is "vectored" to a particular address. Effectively it means if there is an exception, execute the code at this designated address, and the compiler/linker takes care of the rest. More info: http://microchipdeveloper.com/faq:82 – mindcruzer Aug 02 '17 at 02:00

2 Answers2

0

Here is the handler I usually use in a PIC32 project:

//  Exception handler: 
static enum { 
EXCEP_IRQ = 0,          // interrupt 
EXCEP_AdEL = 4,         // address error exception (load or ifetch) 
EXCEP_AdES,             // address error exception (store) 
EXCEP_IBE,              // bus error (ifetch) 
EXCEP_DBE,              // bus error (load/store) 
EXCEP_Sys,              // syscall 
EXCEP_Bp,               // breakpoint 
EXCEP_RI,               // reserved instruction 
EXCEP_CpU,              // coprocessor unusable 
EXCEP_Overflow,         // arithmetic overflow 
EXCEP_Trap,             // trap (possible divide by zero) 
EXCEP_IS1 = 16,         // implementation specfic 1 
EXCEP_CEU,              // CorExtend Unuseable 
EXCEP_C2E               // coprocessor 2 
  } _excep_code; 

  static unsigned int _epc_code; 
  static unsigned int _excep_addr; 

  // this function overrides the normal _weak_ generic handler 
  void _general_exception_handler(void) 
  { 
     asm volatile("mfc0 %0,$13" : "=r" (_excep_code)); 
    asm volatile("mfc0 %0,$14" : "=r" (_excep_addr)); 

    _excep_code = (_excep_code & 0x0000007C) >> 2; 
        while (1) { 
       // Examine _excep_code to identify the type of exception 
       // Examine _excep_addr to find the address that caused the 
    exception 
    Nop(); 
    Nop(); 
    Nop();  
  } 
}// End of exception handler  
blsmit5728
  • 434
  • 3
  • 11
0

I had an issue that turned out to be a bug in microchip's code:

sprintf(foo_str, "%f", NAN)

would (and will) throw a bus error exception... (bug in their "_fconvert" function) To debug/identify that I modified my exception handler to print out (product was already had an ASCII UART connection to its host) what the exception was, what the violating address was and then it will reset itself. The reset portion was hard to find, it is in one of the many Microchip docs for the PIC32MX. This replaces the Harmony (1.10) generated "_general_exception_handler()", not sure if it's compatible with Harmony 2.x

void _general_exception_handler ( void )
{
    char fail_str[96];
    /* Mask off Mask of the ExcCode Field from the Cause Register
    Refer to the MIPs Software User's manual */
    _excep_code = (_CP0_GET_CAUSE() & 0x0000007C) >> 2;
    _excep_addr = _CP0_GET_EPC();
    _cause_str  = cause[_excep_code];
    sprintf(fail_str, "ERROR,%s,cause=%d,addr=%x,", 
                    _cause_str, _excep_code, _excep_addr);
    //"send_my_string" copies the string to the ring buffer
    send_my_string(fail_str);
    //"tx_chars_from_ring_buffer" returns # of chars left in the ring buffer
    while(tx_chars_from_ring_buffer());
    //queue up another set of chars equal to the length of the UART FIFO
    sprintf(fail_str, "\r\r\r\r\r\r\r\r\r\r");
    send_my_string(fail_str);
    while(tx_chars_from_ring_buffer());
#if (__DEBUG)
    while (1)
    {
        SYS_DEBUG_BreakPoint();
    }
#endif
/* The following code illustrates a software Reset */
// assume interrupts are disabled
// assume the DMA controller is suspended
// assume the device is locked
/* perform a system unlock sequence */
// starting critical sequence
SYSKEY = 0x00000000; //write invalid key to force lock
SYSKEY = 0xAA996655; //write key1 to SYSKEY
SYSKEY = 0x556699AA; //write key2 to SYSKEY
// OSCCON is now unlocked
/* set SWRST bit to arm reset */
RSWRSTSET = 1;
/* read RSWRST register to trigger reset */
_excep_code = RSWRST;
/* prevent any unwanted code execution until reset occurs*/
while(1);
}

I did have to play with it a bit to ensure that the message got thru the output FIFO before the reset was invoked...

grambo
  • 283
  • 2
  • 10