问题
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?
回答1:
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
回答2:
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...
来源:https://stackoverflow.com/questions/45299750/general-exception-handler-in-pic32-in-mplab-x-how-does-software-know-when-to