-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathexceptions.c
127 lines (101 loc) · 4.99 KB
/
exceptions.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/******************************************************************************/
/* Files to Include */
/******************************************************************************/
#ifdef __XC32
#include <xc.h> /* Defines special funciton registers, CP0 regs */
#endif
#include <plib.h> /* Include to use PIC32 peripheral libraries */
#include <stdint.h> /* For uint32_t definition */
#include <stdbool.h> /* For true/false definition */
/******************************************************************************/
/* Exception Macro Definitions */
/******************************************************************************/
/*When WRITE_EXCEPTION_CAUSE_TO_FLASH is defined the PIC32 executes a self
write routine to save the exception cause register.*/
/* #define WRITE_EXCEPTION_CAUSE_TO_FLASH */
#ifdef WRITE_EXCEPTION_CAUSE_TO_FLASH
/* Physical Addresses which are at the end of KSEG 0 program memory. */
/* User may want to adjust these values */
#define EXCEPTION_CAUSE 0x1D007FFC
#define EXCEPTION_ADDR 0x1D007FF8
#endif
/******************************************************************************/
/* Exception Variable Declaration */
/******************************************************************************/
/* static in case exception condition would stop auto variable being created */
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 in case exception condition would stop auto variable being created */
static unsigned int _epc_code;
static unsigned int _excep_addr;
/******************************************************************************/
/* Exception Handling */
/******************************************************************************/
/* This function overrides the normal _weak_ _generic_exception_handler which
is defined in the C32 User's Guide. The _weak_ _generic_exception_handler
just does an infinite loop. */
void _general_exception_handler(void)
{
unsigned long t0 = _CP0_GET_COUNT(); /* Used for NVMOP 6 us Delay */
/* Mask off Mask of the ExcCode Field from the Cause Register
Refer to the MIPs M4K Software User's manual */
_excep_code=_CP0_GET_CAUSE() & 0x0000007C >> 2;
_excep_addr=_CP0_GET_EPC();
_CP0_SET_STATUS(_CP0_GET_STATUS()&0xFFFFFFE); /* Disable Interrupts */
#ifdef WRITE_EXCEPTION_CAUSE_TO_FLASH
/* Store the exception causes in program memory in case the part exhibited
the problem in release mode. Gives user a place to start debugging
the problem. */
NVMCON = 0x4001; /* set WREN and Word Programing mode */
NVMADDR = EXCEPTION_CAUSE; /* PM Address at which we'll store the */
/* cause register */
NVMDATA = _excep_code;
/* wait at least 6 us for LVD start-up
assume we're running at max frequency
(80 MHz) so we're always safe */
{
while (_CP0_GET_COUNT() - t0 < (80/2)*6);
}
NVMKEY = 0xAA996655;
NVMKEY = 0x556699AA; /* unlock sequence */
NVMCONSET = NVMCON_WR;
while(NVMCON & NVMCON_WR); /* wait on write to finish */
NVMCON = 0x4001; /* set WREN and Word Programing mode */
NVMADDR = EXCEPTION_ADDR; /* PM Address at which we'll store the */
/* exception address register */
NVMDATA = _excep_addr;
/* wait at least 6 us for LVD start-up
assume we're running at max frequency
(80 MHz) so we're always safe */
{
while (_CP0_GET_COUNT() - t0 < (80/2)*6);
}
NVMKEY = 0xAA996655;
NVMKEY = 0x556699AA; /* unlock sequence */
NVMCONSET = NVMCON_WR;
while(NVMCON & NVMCON_WR);
/* Write the exception cause and address to the part can be read and
the cause determined. */
NVMWriteWord((void*)EXCEPTION_CAUSE, _excep_code);
NVMWriteWord((void*)EXCEPTION_ADDR, _excep_addr);
#endif
while (1)
{
/* Examine _excep_code to identify the type of exception */
/* Examine _excep_addr to find the address that caused the exception */
}
}