-
Notifications
You must be signed in to change notification settings - Fork 1
/
pic32mx.c
194 lines (148 loc) · 4.23 KB
/
pic32mx.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
/*
PIC32MX Related functions.
*/
#include <sys/kmem.h>
#include "pic32mx.h"
//================================================================
/*! spin lock delay functions.
*/
static void delay_ticks( uint32_t ticks )
{
uint32_t t_start = _CP0_GET_COUNT();
while( (_CP0_GET_COUNT() - t_start) < ticks )
;
}
// emulate PIC16/24 delay function.
void __delay_us( uint32_t us )
{
delay_ticks( us * (_XTAL_FREQ/2/1000000) );
}
void __delay_ms( uint32_t ms )
{
delay_ticks( ms * (_XTAL_FREQ/2/1000) );
}
//================================================================
/*! lock system register
*/
void system_register_lock(void)
{
SYSKEY = 0x0;
}
//================================================================
/*! unlock system register
*/
void system_register_unlock(void)
{
unsigned int status;
// Suspend or Disable all Interrupts
asm volatile ("di %0" : "=r" (status));
// starting critical sequence
SYSKEY = 0x00000000; // write invalid key to force lock
SYSKEY = 0xAA996655; // write key1 to SYSKEY
SYSKEY = 0x556699AA; // write key2 to SYSKEY
// Restore Interrupts
if (status & 0x00000001) {
asm volatile ("ei");
} else {
asm volatile ("di");
}
}
//================================================================
/*! software reset DS60001118H
*/
void system_reset(void)
{
system_register_unlock();
RSWRSTSET = 1;
// read RSWRST register to trigger reset
uint32_t dummy = RSWRST;
(void)dummy;
while(1)
;
}
#if 0
//================================================================
/*! general exception handler
Referred to the MCC auto generated code.
*/
void _general_exception_handler()
{
static const char *cause[] = {
"Interrupt", "Undefined", "Undefined", "Undefined",
"Load/fetch address error", "Store address error",
"Instruction bus error", "Data bus error", "Syscall",
"Breakpoint", "Reserved instruction", "Coprocessor unusable",
"Arithmetic overflow", "Trap", "Reserved", "Reserved",
"Reserved", "Reserved", "Reserved"
};
/* Mask off the ExcCode Field from the Cause Register
Refer to the MIPs Software User's manual */
uint8_t excep_code = (_CP0_GET_CAUSE() & 0x0000007C) >> 2;
uint8_t excep_addr = _CP0_GET_EPC();
const uint8_t *cause_str = cause[excep_code];
uart1_write( cause_str, strlen(cause_str) );
uart1_write( "\r\n", 2 );
while(1) {
}
}
#endif
//================================================================
/*! NVM unlock and execute nvm operation.
@param nvmop NVM Operation bits. (see: DS60001121G, Sect 5.2.1)
@return not zero if errors.
*/
unsigned int NVMUnlock(unsigned int nvmop)
{
unsigned int status;
// Suspend or Disable all Interrupts
asm volatile ("di %0" : "=r" (status));
// clearing error bits before performing an NVM operation
NVMCONCLR = 0x0f;
// Enable Flash Write/Erase Operations and Select
// Flash operation to perform
NVMCON = (0x4000 | nvmop);
// Write Keys
NVMKEY = 0xAA996655;
NVMKEY = 0x556699AA;
// Start the operation using the Set Register
NVMCONSET = 0x8000;
// Wait for operation to complete
while (NVMCON & 0x8000);
// Restore Interrupts
if( status & 0x00000001 ) {
asm volatile ("ei");
} else {
asm volatile ("di");
}
// Disable NVM write enable
NVMCONCLR = 0x4000;
// Return WRERR and LVDERR Error Status Bits
return (NVMCON & 0x3000);
}
//================================================================
/*! Erase one *PAGE* of FLASH ROM
@param address flash rom address
@return not zero if errors.
*/
unsigned int flash_erase_page(void *address)
{
// Set NVMADDR to the Start Address of page to erase
NVMADDR = KVA_TO_PA(address);
// Unlock and Erase Page
return NVMUnlock( 0x4 ); // 0x4 = Page Erase Operation
}
//================================================================
/*! Write one *ROW* of FLASH ROM
@param address flash rom address
@param data write data address
@return not zero if errors.
*/
unsigned int flash_write_row(void *address, void *data)
{
// Set NVMADDR to Start Address of row to program
NVMADDR = KVA_TO_PA(address);
// Set NVMSRCADDR to the SRAM data buffer Address
NVMSRCADDR = KVA_TO_PA(data);
// Unlock and Write Row
return NVMUnlock( 0x3 ); // 0x3 = Row Program Operation
}