1 /*
2 * Copyright (C) 2005-2019 Darron Broad
3 * All rights reserved.
4 *
5 * This file is part of Pickle Microchip PIC ICSP.
6 *
7 * Pickle Microchip PIC ICSP is free software: you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as published
9 * by the Free Software Foundation.
10 *
11 * Pickle Microchip PIC ICSP is distributed in the hope that it will be
12 * useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
14 * Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License along
17 * with Pickle Microchip PIC ICSP. If not, see http://www.gnu.org/licenses/
18 */
19
20 #undef DEBUG
21
22 #include "pickle.h"
23
24 /******************************************************************************
25 *
26 * Session
27 *
28 *****************************************************************************/
29
30 extern struct pickle p;
31
32 /*****************************************************************************
33 *
34 * Hardware operations
35 *
36 *****************************************************************************/
37
38 struct pic_ops pic32_ops = {
39 .arch = ARCH32BIT,
40 .align = sizeof(uint32_t),
41 .selector = pic32_selector,
42 .bootloader = NULL,
43 .program_begin = pic32_program_begin,
44 .program_data = pic32_program_data,
45 .program_end = pic32_program_end,
46 .verify_begin = pic32_program_begin,
47 .verify_data = pic32_verify_data,
48 .verify_end = pic32_standby,
49 .view_data = pic32_view_data,
50 .read_config_memory = pic32_read_config_memory,
51 .get_program_count = pic32_get_program_count,
52 .get_program_size = pic32_get_program_size,
53 .get_data_size = NULL,
54 .get_executive_size = NULL,
55 .get_boot_size = pic32_get_boot_size,
56 .read_program_memory_block = pic32_read_program_memory_block,
57 .read_data_memory_block = NULL,
58 .write_panel = pic32_write_panel,
59 .bulk_erase = pic32_bulk_erase,
60 .write_osccal = NULL,
61 .write_bandgap = NULL,
62 .write_calib = NULL,
63 .row_erase = NULL,
64 .dumpdeviceid = pic32_dumpdeviceid,
65 .dumpconfig = pic32_dumpconfig,
66 .dumposccal = NULL,
67 .dumpdevice = NULL,
68 .dumpadj = 4,
69 .dumphexcode = pic32_dumphexcode,
70 .dumpinhxcode = pic32_dumpinhxcode,
71 .dumphexdata = NULL,
72 .dumpinhxdata = NULL,
73 .debug = NULL,
74 };
75
76 uint32_t
pic32_arch(void)77 pic32_arch(void)
78 {
79 p.pic = &pic32_ops;
80
81 return p.pic->arch;
82 }
83
84 /*****************************************************************************
85 *
86 * Hardware configuration
87 *
88 *****************************************************************************/
89
90 struct pic32_config pic32_conf;
91
92 /*****************************************************************************
93 *
94 * Hardware algorithm map: Device
95 *
96 *****************************************************************************/
97
98 struct pic32_dsmap pic32_map[] =
99 {
100 /*Device name Device id App. Data-Sheet BOOT/PROG Size Row/Page Size*/
101
102 /* PIC32MX1XX/2XX DS60001168F */
103 {"PIC32MX110F016B", PIC32MX110F016B, DS60001168F, 768, 4096, 32, 256},
104 {"PIC32MX110F016C", PIC32MX110F016C, DS60001168F, 768, 4096, 32, 256},
105 {"PIC32MX110F016D", PIC32MX110F016D, DS60001168F, 768, 4096, 32, 256},
106
107 {"PIC32MX120F032B", PIC32MX120F032B, DS60001168F, 768, 8192, 32, 256},
108 {"PIC32MX120F032C", PIC32MX120F032C, DS60001168F, 768, 8192, 32, 256},
109 {"PIC32MX120F032D", PIC32MX120F032D, DS60001168F, 768, 8192, 32, 256},
110
111 {"PIC32MX130F064B", PIC32MX130F064B, DS60001168F, 768, 16384, 32, 256},
112 {"PIC32MX130F064C", PIC32MX130F064C, DS60001168F, 768, 16384, 32, 256},
113 {"PIC32MX130F064D", PIC32MX130F064D, DS60001168F, 768, 16384, 32, 256},
114
115 {"PIC32MX150F128B", PIC32MX150F128B, DS60001168F, 768, 32768, 32, 256},
116 {"PIC32MX150F128C", PIC32MX150F128C, DS60001168F, 768, 32768, 32, 256},
117 {"PIC32MX150F128D", PIC32MX150F128D, DS60001168F, 768, 32768, 32, 256},
118
119 {"PIC32MX170F256B", PIC32MX170F256B, DS60001168F, 768, 65536, 32, 256},
120 {"PIC32MX170F256D", PIC32MX170F256D, DS60001168F, 768, 65536, 32, 256},
121
122 {"PIC32MX210F016B", PIC32MX210F016B, DS60001168F, 768, 4096, 32, 256},
123 {"PIC32MX210F016C", PIC32MX210F016C, DS60001168F, 768, 4096, 32, 256},
124 {"PIC32MX210F016D", PIC32MX210F016D, DS60001168F, 768, 4096, 32, 256},
125
126 {"PIC32MX220F032B", PIC32MX220F032B, DS60001168F, 768, 8192, 32, 256},
127 {"PIC32MX220F032C", PIC32MX220F032C, DS60001168F, 768, 8192, 32, 256},
128 {"PIC32MX220F032D", PIC32MX220F032D, DS60001168F, 768, 8192, 32, 256},
129
130 {"PIC32MX230F064B", PIC32MX230F064B, DS60001168F, 768, 16384, 32, 256},
131 {"PIC32MX230F064C", PIC32MX230F064C, DS60001168F, 768, 16384, 32, 256},
132 {"PIC32MX230F064D", PIC32MX230F064D, DS60001168F, 768, 16384, 32, 256},
133
134 {"PIC32MX250F128B", PIC32MX250F128B, DS60001168F, 768, 32768, 32, 256},
135 {"PIC32MX250F128C", PIC32MX250F128C, DS60001168F, 768, 32768, 32, 256},
136 {"PIC32MX250F128D", PIC32MX250F128D, DS60001168F, 768, 32768, 32, 256},
137
138 {"PIC32MX270F256B", PIC32MX270F256B, DS60001168F, 768, 65536, 32, 256},
139 {"PIC32MX270F256D", PIC32MX270F256D, DS60001168F, 768, 65536, 32, 256},
140
141 /* PIC32MX330/350/370/430/450/470 DS60001185C */
142 {"PIC32MX330F064H", PIC32MX330F064H, DS60001185C, 3072, 16384, 128, 1024},
143 {"PIC32MX330F064L", PIC32MX330F064H, DS60001185C, 3072, 16384, 128, 1024},
144
145 {"PIC32MX350F128H", PIC32MX350F128H, DS60001185C, 3072, 32768, 128, 1024},
146 {"PIC32MX350F128L", PIC32MX350F128H, DS60001185C, 3072, 32768, 128, 1024},
147
148 {"PIC32MX350F256H", PIC32MX350F256H, DS60001185C, 3072, 65536, 128, 1024},
149 {"PIC32MX350F256L", PIC32MX350F256H, DS60001185C, 3072, 65536, 128, 1024},
150
151 {"PIC32MX370F512H", PIC32MX370F512H, DS60001185C, 3072, 131072, 128, 1024},
152 {"PIC32MX370F512L", PIC32MX370F512H, DS60001185C, 3072, 131072, 128, 1024},
153
154 {"PIC32MX430F064H", PIC32MX430F064H, DS60001185C, 3072, 16384, 128, 1024},
155 {"PIC32MX430F064L", PIC32MX430F064H, DS60001185C, 3072, 16384, 128, 1024},
156
157 {"PIC32MX450F128H", PIC32MX450F128H, DS60001185C, 3072, 32768, 128, 1024},
158 {"PIC32MX450F128L", PIC32MX450F128H, DS60001185C, 3072, 32768, 128, 1024},
159
160 {"PIC32MX450F256H", PIC32MX450F256H, DS60001185C, 3072, 65536, 128, 1024},
161 {"PIC32MX450F256L", PIC32MX450F256H, DS60001185C, 3072, 65536, 128, 1024},
162
163 {"PIC32MX470F512H", PIC32MX470F512H, DS60001185C, 3072, 131072, 128, 1024},
164 {"PIC32MX470F512L", PIC32MX470F512H, DS60001185C, 3072, 131072, 128, 1024},
165
166 /* PIC32MX3XX/4XX DS61143H */
167 {"PIC32MX320F032H", PIC32MX320F032H, DS61143H, 3072, 8192, 128, 1024},
168 {"PIC32MX320F064H", PIC32MX320F064H, DS61143H, 3072, 16384, 128, 1024},
169 {"PIC32MX320F128H", PIC32MX320F128H, DS61143H, 3072, 32768, 128, 1024},
170
171 {"PIC32MX340F128H", PIC32MX340F128H, DS61143H, 3072, 32768, 128, 1024},
172 {"PIC32MX340F256H", PIC32MX340F256H, DS61143H, 3072, 65536, 128, 1024},
173 {"PIC32MX340F512H", PIC32MX340F512H, DS61143H, 3072, 131072, 128, 1024},
174
175 {"PIC32MX320F128L", PIC32MX320F128L, DS61143H, 3072, 32768, 128, 1024},
176 {"PIC32MX340F128L", PIC32MX340F128L, DS61143H, 3072, 32768, 128, 1024},
177
178 {"PIC32MX360F256L", PIC32MX360F256L, DS61143H, 3072, 65536, 128, 1024},
179 {"PIC32MX360F512L", PIC32MX360F512L, DS61143H, 3072, 131072, 128, 1024},
180
181 {"PIC32MX420F032H", PIC32MX420F032H, DS61143H, 3072, 8192, 128, 1024},
182
183 {"PIC32MX440F128H", PIC32MX440F128H, DS61143H, 3072, 32768, 128, 1024},
184 {"PIC32MX440F256H", PIC32MX440F256H, DS61143H, 3072, 65536, 128, 1024},
185 {"PIC32MX440F512H", PIC32MX440F512H, DS61143H, 3072, 131072, 128, 1024},
186 {"PIC32MX440F128L", PIC32MX440F128L, DS61143H, 3072, 32768, 128, 1024},
187
188 {"PIC32MX460F256L", PIC32MX460F256L, DS61143H, 3072, 65536, 128, 1024},
189 {"PIC32MX460F512L", PIC32MX460F512L, DS61143H, 3072, 131072, 128, 1024},
190
191 /* PIC32MX5XX/6XX/7XX DS61156H */
192 {"PIC32MX534F064H", PIC32MX534F064H, DS61156H, 3072, 16384, 128, 1024},
193 {"PIC32MX564F064H", PIC32MX564F064H, DS61156H, 3072, 16384, 128, 1024},
194 {"PIC32MX564F128H", PIC32MX564F128H, DS61156H, 3072, 32768, 128, 1024},
195 {"PIC32MX575F256H", PIC32MX575F256H, DS61156H, 3072, 65536, 128, 1024},
196 {"PIC32MX575F512H", PIC32MX575F512H, DS61156H, 3072, 131072, 128, 1024},
197
198 {"PIC32MX534F064L", PIC32MX534F064L, DS61156H, 3072, 16384, 128, 1024},
199 {"PIC32MX564F064L", PIC32MX564F064L, DS61156H, 3072, 16384, 128, 1024},
200 {"PIC32MX564F128L", PIC32MX564F128L, DS61156H, 3072, 32768, 128, 1024},
201 {"PIC32MX575F256L", PIC32MX575F256L, DS61156H, 3072, 65536, 128, 1024},
202 {"PIC32MX575F512L", PIC32MX575F512L, DS61156H, 3072, 131072, 128, 1024},
203
204 {"PIC32MX664F064H", PIC32MX664F064H, DS61156H, 3072, 16384, 128, 1024},
205 {"PIC32MX664F128H", PIC32MX664F128H, DS61156H, 3072, 32768, 128, 1024},
206 {"PIC32MX675F256H", PIC32MX675F256H, DS61156H, 3072, 65536, 128, 1024},
207 {"PIC32MX675F512H", PIC32MX675F512H, DS61156H, 3072, 131072, 128, 1024},
208 {"PIC32MX695F512H", PIC32MX695F512H, DS61156H, 3072, 131072, 128, 1024},
209
210 {"PIC32MX664F064L", PIC32MX664F064L, DS61156H, 3072, 16384, 128, 1024},
211 {"PIC32MX664F128L", PIC32MX664F128L, DS61156H, 3072, 32768, 128, 1024},
212 {"PIC32MX675F256L", PIC32MX675F256L, DS61156H, 3072, 65536, 128, 1024},
213 {"PIC32MX675F512L", PIC32MX675F512L, DS61156H, 3072, 131072, 128, 1024},
214 {"PIC32MX695F512L", PIC32MX695F512L, DS61156H, 3072, 131072, 128, 1024},
215
216 {"PIC32MX764F128H", PIC32MX764F128H, DS61156H, 3072, 32768, 128, 1024},
217 {"PIC32MX775F256H", PIC32MX775F256H, DS61156H, 3072, 65536, 128, 1024},
218 {"PIC32MX775F512H", PIC32MX775F512H, DS61156H, 3072, 131072, 128, 1024},
219 {"PIC32MX795F512H", PIC32MX795F512H, DS61156H, 3072, 131072, 128, 1024},
220
221 {"PIC32MX764F128L", PIC32MX764F128L, DS61156H, 3072, 32768, 128, 1024},
222 {"PIC32MX775F256L", PIC32MX775F256L, DS61156H, 3072, 65536, 128, 1024},
223 {"PIC32MX775F512L", PIC32MX775F512L, DS61156H, 3072, 131072, 128, 1024},
224 {"PIC32MX795F512L", PIC32MX795F512L, DS61156H, 3072, 131072, 128, 1024},
225
226 /* PIC32MZ EC DS60001191C */
227 {"PIC32MZ1024ECG064", PIC32MZ1024ECG064, DS60001191C, 40960, 262144, 512, 4096},
228 {"PIC32MZ1024ECG100", PIC32MZ1024ECG100, DS60001191C, 40960, 262144, 512, 4096},
229 {"PIC32MZ1024ECG124", PIC32MZ1024ECG124, DS60001191C, 40960, 262144, 512, 4096},
230 {"PIC32MZ1024ECG144", PIC32MZ1024ECG144, DS60001191C, 40960, 262144, 512, 4096},
231
232 {"PIC32MZ1024ECH064", PIC32MZ1024ECH064, DS60001191C, 40960, 262144, 512, 4096},
233 {"PIC32MZ1024ECH100", PIC32MZ1024ECH100, DS60001191C, 40960, 262144, 512, 4096},
234 {"PIC32MZ1024ECH124", PIC32MZ1024ECH124, DS60001191C, 40960, 262144, 512, 4096},
235 {"PIC32MZ1024ECH144", PIC32MZ1024ECH144, DS60001191C, 40960, 262144, 512, 4096},
236
237 {"PIC32MZ2048ECG064", PIC32MZ2048ECG064, DS60001191C, 40960, 524288, 512, 4096},
238 {"PIC32MZ2048ECG100", PIC32MZ2048ECG100, DS60001191C, 40960, 524288, 512, 4096},
239 {"PIC32MZ2048ECG124", PIC32MZ2048ECG124, DS60001191C, 40960, 524288, 512, 4096},
240 {"PIC32MZ2048ECG144", PIC32MZ2048ECG144, DS60001191C, 40960, 524288, 512, 4096},
241
242 {"PIC32MZ2048ECH064", PIC32MZ2048ECH064, DS60001191C, 40960, 524288, 512, 4096},
243 {"PIC32MZ2048ECH100", PIC32MZ2048ECH100, DS60001191C, 40960, 524288, 512, 4096},
244 {"PIC32MZ2048ECH124", PIC32MZ2048ECH124, DS60001191C, 40960, 524288, 512, 4096},
245 {"PIC32MZ2048ECH144", PIC32MZ2048ECH144, DS60001191C, 40960, 524288, 512, 4096},
246
247 {"PIC32MZ1024ECM064", PIC32MZ1024ECM064, DS60001191C, 40960, 262144, 512, 4096},
248 {"PIC32MZ1024ECM100", PIC32MZ1024ECM100, DS60001191C, 40960, 262144, 512, 4096},
249 {"PIC32MZ1024ECM124", PIC32MZ1024ECM124, DS60001191C, 40960, 262144, 512, 4096},
250 {"PIC32MZ1024ECM144", PIC32MZ1024ECM144, DS60001191C, 40960, 262144, 512, 4096},
251
252 {"PIC32MZ2048ECM064", PIC32MZ2048ECM064, DS60001191C, 40960, 524288, 512, 4096},
253 {"PIC32MZ2048ECM100", PIC32MZ2048ECM100, DS60001191C, 40960, 524288, 512, 4096},
254 {"PIC32MZ2048ECM124", PIC32MZ2048ECM124, DS60001191C, 40960, 524288, 512, 4096},
255 {"PIC32MZ2048ECM144", PIC32MZ2048ECM144, DS60001191C, 40960, 524288, 512, 4096},
256
257 /* PIC32MX1XX/2XX/5XX 64/100-PIN FAMILY */
258 {"PIC32MX120F064H", PIC32MX120F064H, DS60001290D, PIC32_WORD(3),PIC32_WORD(64), 32,256},
259 {"PIC32MX130F128H", PIC32MX130F128H, DS60001290D, PIC32_WORD(3),PIC32_WORD(128),32,256},
260 {"PIC32MX130F128L", PIC32MX130F128L, DS60001290D, PIC32_WORD(3),PIC32_WORD(128),32,256},
261 {"PIC32MX230F128H", PIC32MX230F128H, DS60001290D, PIC32_WORD(3),PIC32_WORD(128),32,256},
262 {"PIC32MX230F128L", PIC32MX230F128L, DS60001290D, PIC32_WORD(3),PIC32_WORD(128),32,256},
263 {"PIC32MX530F128H", PIC32MX530F128H, DS60001290D, PIC32_WORD(3),PIC32_WORD(128),32,256},
264 {"PIC32MX530F128L", PIC32MX530F128L, DS60001290D, PIC32_WORD(3),PIC32_WORD(128),32,256},
265 {"PIC32MX150F256H", PIC32MX150F256H, DS60001290D, PIC32_WORD(3),PIC32_WORD(256),32,256},
266 {"PIC32MX150F256L", PIC32MX150F256L, DS60001290D, PIC32_WORD(3),PIC32_WORD(256),32,256},
267 {"PIC32MX250F256H", PIC32MX250F256H, DS60001290D, PIC32_WORD(3),PIC32_WORD(256),32,256},
268 {"PIC32MX250F256L", PIC32MX250F256L, DS60001290D, PIC32_WORD(3),PIC32_WORD(256),32,256},
269 {"PIC32MX550F256H", PIC32MX550F256H, DS60001290D, PIC32_WORD(3),PIC32_WORD(256),32,256},
270 {"PIC32MX550F256L", PIC32MX550F256L, DS60001290D, PIC32_WORD(3),PIC32_WORD(256),32,256},
271 {"PIC32MX170F512H", PIC32MX170F512H, DS60001290D, PIC32_WORD(3),PIC32_WORD(512),32,256},
272 {"PIC32MX170F512L", PIC32MX170F512L, DS60001290D, PIC32_WORD(3),PIC32_WORD(512),32,256},
273 {"PIC32MX270F512H", PIC32MX270F512H, DS60001290D, PIC32_WORD(3),PIC32_WORD(512),32,256},
274 {"PIC32MX270F512L", PIC32MX270F512L, DS60001290D, PIC32_WORD(3),PIC32_WORD(512),32,256},
275 {"PIC32MX570F512H", PIC32MX570F512H, DS60001290D, PIC32_WORD(3),PIC32_WORD(512),32,256},
276 {"PIC32MX570F512L", PIC32MX570F512L, DS60001290D, PIC32_WORD(3),PIC32_WORD(512),32,256},
277
278 /* PIC32MM0016/0032/0064/0128/0256GPL0XX */
279 {"PIC32MM0016GPL020", PIC32MM0016GPL020, DS60001324B, PIC32_WORD(6),PIC32_WORD(16), 64,512},
280 {"PIC32MM0032GPL020", PIC32MM0032GPL020, DS60001324B, PIC32_WORD(6),PIC32_WORD(32), 64,512},
281 {"PIC32MM0064GPL020", PIC32MM0064GPL020, DS60001324B, PIC32_WORD(6),PIC32_WORD(64), 64,512},
282 {"PIC32MM0016GPL028", PIC32MM0016GPL028, DS60001324B, PIC32_WORD(6),PIC32_WORD(16), 64,512},
283 {"PIC32MM0032GPL028", PIC32MM0032GPL028, DS60001324B, PIC32_WORD(6),PIC32_WORD(32), 64,512},
284 {"PIC32MM0064GPL028", PIC32MM0064GPL028, DS60001324B, PIC32_WORD(6),PIC32_WORD(64), 64,512},
285 {"PIC32MM0016GPL036", PIC32MM0016GPL036, DS60001324B, PIC32_WORD(6),PIC32_WORD(16), 64,512},
286 {"PIC32MM0032GPL036", PIC32MM0032GPL036, DS60001324B, PIC32_WORD(6),PIC32_WORD(32), 64,512},
287 {"PIC32MM0064GPL036", PIC32MM0064GPL036, DS60001324B, PIC32_WORD(6),PIC32_WORD(64), 64,512},
288
289 {"(null)", 0, 0, 0, 0, 0, 0},
290 /*Device name Device id App. Data-Sheet BOOT/PROG Size Row/Page Size*/
291 };
292 #define PIC32_SIZE ((sizeof(pic32_map) / sizeof(struct pic32_dsmap)) - 1)
293
294 /* Default device (null) */
295 uint32_t pic32_index = PIC32_SIZE;
296
297 void
pic32_selector(void)298 pic32_selector(void)
299 {
300 uint32_t i;
301 char *dnames[PIC32_SIZE];
302
303 for (i = 0; i < PIC32_SIZE; ++i) {
304 dnames[i] = pic32_map[i].devicename;
305 }
306 qsort(dnames, PIC32_SIZE, sizeof(char *), pic_cmp);
307 for (i = 0; i < PIC32_SIZE; ++i) {
308 if ((i % PIC_NCOLS) == (PIC_NCOLS - 1))
309 printf("%s\n", dnames[i]);
310 else
311 printf("%-19s", dnames[i]);
312 }
313 if (i % PIC_NCOLS)
314 printf("\n");
315 printf("Total: %u\n", (uint32_t)PIC32_SIZE);
316 }
317
318 /*****************************************************************************
319 *
320 * Hardware algorithm map: Device family
321 *
322 *****************************************************************************/
323
324 struct pic32_dstab pic32_tab[] =
325 {
326 /* Extract PE: unzip PICKIT3.jar */
327
328 /* PIC32MX1XX/2XX DS60001168F */
329 {DS60001168F, "RIPE_11_000301"},
330
331 /* PIC32MX330/350/370/430/450/470 DS60001185C */
332 {DS60001185C, "RIPE_06_000201"},
333
334 /* PIC32MX3XX/4XX DS61143H */
335 {DS61143H, "RIPE_06_000201"},
336
337 /* PIC32MX5XX/6XX/7XX DS61156H */
338 {DS61156H, "RIPE_06_000201"},
339
340 /* PIC32MZ EC DS60001191C */
341 {DS60001191C, "RIPE_15_000504"},
342
343 /* PIC32MX1XX/2XX/5XX DS60001290D */
344 {DS60001290D, "RIPE_11_000301"},
345
346 /* PIC32MK 0512/1024 */
347 /* "RIPE_15a_000506" */
348 #if 0
349 /* PIC32MM0016/0032/0064/0128/0256GPL0XX */
350 {DS60001324B, "RIPE_20b_000510"},
351 #endif
352 /* EOF */
353 {0, "(null)"},
354
355 /* DS60001145P-page 9 */
356 /* PIC32MK0128/0256/0512/1024 RIPE_15_aabbcc */
357
358 /* DS60001145S-page 10 */
359 /* PIC32MX1XX/2XX/5XX RIPE_11_aabbcc */
360 /* PIC32MK 0512/1024 RIPE_15a_aabbcc */
361
362 /* DS60001364C-page 8 */
363 /* PIC32MM0016/0032/0064/0128/0256GPL0XX */
364 /* RIPE_20b_aabbcc */
365 };
366
367 /*****************************************************************************
368 *
369 * Program/Verify mode
370 *
371 *****************************************************************************/
372
373 /*
374 * ENTER LVP PROGRAM/VERIFY MODE
375 *
376 * ENTRY - VDD FIRST
377 */
378 void
pic32_program_verify(void)379 pic32_program_verify(void)
380 {
381 /* RESET & ACQUIRE GPIO */
382 io_set_vpp(LOW);
383 /* DS60001145M P6(100ns) */
384 io_usleep(1000);
385
386 /* PGD + PGC + PGM(N/A) LOW */
387 io_set_pgd(LOW);
388 io_set_pgc(LOW);
389 io_set_pgm(LOW);
390 io_usleep(1000);
391
392 /* CONFIGURE I/O (GPIO-BB, FTDI-BB) */
393 io_configure(TRUE, FALSE);
394
395 /* VPP HIGH */
396 io_set_vpp(HIGH);
397 /* DS60001145M P20(500us) */
398 io_usleep(500);
399
400 /* VPP LOW */
401 io_set_vpp(LOW);
402 /* DS60001145M P18(40ns) */
403 io_usleep(500);
404
405 /* PROGRAM/VERIFY ENTRY CODE */
406 io_program_out(PHCMKEY, 32);
407 /* DS60001145M P19(40ns) */
408 io_usleep(500);
409
410 /* VPP HIGH */
411 io_set_vpp(HIGH);
412 /* DS60001145M P7(500ns) */
413 io_usleep(500);
414
415 /* ENTER RUN-TEST/IDLE STATE */
416 pic32_setmode(PIC32_IDLE6);
417 }
418
419 /*
420 * EXIT LVP PROGRAM/VERIFY MODE
421 *
422 * EXIT - VDD LAST
423 */
424 void
pic32_standby(void)425 pic32_standby(void)
426 {
427 /* ENTER TEST-LOGIC-RESET STATE */
428 pic32_setmode(PIC32_RESET);
429 /* DS60001145M P16(0s) */
430 io_usleep(500);
431
432 /* PGD + PGC + VPP + PGM(N/A) LOW */
433 io_set_pgd(LOW);
434 io_set_pgc(LOW);
435 io_set_vpp(LOW);
436 io_set_pgm(LOW);
437 }
438
439 /*****************************************************************************
440 *
441 * Pseudo Operations
442 *
443 *****************************************************************************/
444
445 /*
446 * SetMode Pseudo Operation
447 *
448 * To set the EJTAG state machine to a specific state
449 *
450 * 2-WIRE 4-PHASE
451 *
452 * DS60001145M-page 13
453 */
454 void
pic32_setmode(uint8_t nbits,uint32_t tms)455 pic32_setmode(uint8_t nbits, uint32_t tms)
456 {
457 /* SET MODE */
458 io_clock_bits_4phase(nbits, tms, /* tdi */ 0);
459 }
460
461 /*
462 * SendCommand Pseudo Operation
463 *
464 * To send a command to select a specific TAP register
465 *
466 * 2-WIRE 4-PHASE
467 *
468 * DS60001145M-page 14
469 */
470 void
pic32_sendcommand(uint8_t nbits,uint32_t tdi)471 pic32_sendcommand(uint8_t nbits, uint32_t tdi)
472 {
473 uint32_t tms = 1UL << (nbits - 1);
474
475 /*
476 * 1. The TMS Header is clocked into the device to select the
477 * Shift IR state.
478 */
479
480 /* ENTER SHIFT-IR STATE */
481 io_clock_bit_4phase(1, 0); /* SELECT-DR */
482 io_clock_bit_4phase(1, 0); /* SELECT-IR */
483 io_clock_bit_4phase(0, 0); /* CAPTURE-IR */
484 io_clock_bit_4phase(0, 0); /* SHIFT-IR */
485
486 /*
487 * 2. The command is clocked into the device on TDI while
488 * holding signal TMS low.
489 *
490 * 3. The last Most Significant bit (MSb) of the command is
491 * clocked in while setting TMS high.
492 */
493
494 /* SEND COMMAND */
495 io_clock_bits_4phase(nbits, /* SHIFT-IR .. EXIT1-IR */
496 tms, tdi);
497 /*
498 * 4. The TMS Footer is clocked in on TMS to return the TAP
499 * controller to the Run/Test Idle state.
500 */
501
502 /* ENTER RUN-TEST/IDLE STATE */
503 io_clock_bit_4phase(1, 0); /* UPDATE-IR */
504 io_clock_bit_4phase(0, 0); /* RUN-TEST/IDLE */
505 }
506
507 /*
508 * XferData Pseudo Operation
509 *
510 * To clock data to and from the register selected by the command
511 *
512 * 2-WIRE 4-PHASE
513 *
514 * DS60001145M-page 15
515 */
516 uint32_t
pic32_xferdata(uint8_t nbits,uint32_t tdi)517 pic32_xferdata(uint8_t nbits, uint32_t tdi)
518 {
519 uint32_t tms = 1UL << (nbits - 1);
520 uint32_t tdo;
521
522 /*
523 * 1. The TMS Header is clocked into the device to select the
524 * Shift DR state.
525 */
526
527 /* ENTER SHIFT-DR STATE */
528 io_clock_bit_4phase(1, 0); /* SELECT-DR */
529 io_clock_bit_4phase(0, 0); /* CAPTURE-DR */
530 tdo = io_clock_bit_4phase(0, 0); /* SHIFT-DR */
531
532 /*
533 * 2. The data is clocked in/out of the device on TDI/TDO while
534 * holding signal TMS low.
535 *
536 * 3. The last MSb of the data is clocked in/out while setting
537 * TMS high.
538 */
539
540 /* TRANSFER DATA */
541 tdo |= io_clock_bits_4phase(nbits, /* SHIFT-DR .. EXIT1-DR */
542 tms, tdi) << 1;
543 /*
544 * 4. The TMS Footer is clocked in on TMS to return the TAP
545 * controller to the Run/Test Idle state.
546 */
547
548 /* ENTER RUN-TEST/IDLE STATE */
549 io_clock_bit_4phase(1, 0); /* UPDATE-DR */
550 io_clock_bit_4phase(0, 0); /* RUN-TEST/IDLE */
551
552 return tdo;
553 }
554
555 /*
556 * XferFastData Pseudo Operation
557 *
558 * To quickly send 32 bits of data in/out of the device
559 *
560 * 2-WIRE 4-PHASE
561 *
562 * DS60001145M-page 16
563 */
564 uint32_t
pic32_xferfastdata(uint32_t tdi)565 pic32_xferfastdata(uint32_t tdi)
566 {
567 uint8_t pracc;
568 uint32_t tms = 0x80000000;
569 uint32_t tdo;
570
571 /*
572 * 1. The TMS Header is clocked into the device to select the
573 * Shift DR state.
574 */
575
576 /* ENTER SHIFT-DR STATE */
577 io_clock_bit_4phase(1, 0); /* SELECT-DR */
578 io_clock_bit_4phase(0, 0); /* CAPTURE-DR */
579
580 pracc = io_clock_bit_4phase(0, 0); /* SHIFT-DR */
581 if (!pracc) {
582 printf("%s: fatal error: processor access invalid [%d]\n",
583 __func__, pracc);
584 pic32_standby();
585 io_exit(EX_SOFTWARE); /* Panic */
586 }
587
588 /*
589 * 2. The input value of the PrAcc bit, which is ‘0’, is clocked
590 * in.
591 */
592
593 /* PROCESSOR ACCESS */
594 tdo = io_clock_bit_4phase(0, 0); /* SHIFT-DR */
595
596 /* TRANSFER DATA */
597 tdo |= io_clock_bits_4phase(32, /* SHIFT-DR .. EXIT1-DR */
598 tms, tdi) << 1;
599 /*
600 * 3. TMS Footer = 10 is clocked in to return the TAP controller
601 * to the Run/Test Idle state.
602 */
603
604 /* ENTER RUN-TEST/IDLE STATE */
605 io_clock_bit_4phase(1, 0); /* UPDATE-DR */
606 io_clock_bit_4phase(0, 0); /* RUN-TEST/IDLE */
607
608 return tdo;
609 }
610
611 /*
612 * Wait until CPU is ready
613 *
614 * Check if processor access bit is set
615 *
616 * DS60001145P-page 17
617 */
618 void
pic32_wait_for_cpu(void)619 pic32_wait_for_cpu(void)
620 {
621 uint32_t controlVal;
622 struct timeval tv1, tv2, tv3;
623
624 /* Select control register */
625 pic32_sendcommand(PIC32_ETAP_CONTROL);
626
627 /* Wait until CPU is ready */
628 gettimeofday(&tv1, NULL);
629 do {
630 /* Check if processor access bit is set */
631 controlVal = pic32_xferdata(32,
632 PIC32_EJTAG_CONTROL_PRACC | PIC32_EJTAG_CONTROL_PROBEN | PIC32_EJTAG_CONTROL_PROBTRAP);
633 if (controlVal & PIC32_EJTAG_CONTROL_PRACC)
634 return;
635
636 gettimeofday(&tv2, NULL);
637 timersub(&tv2, &tv1, &tv3);
638 }
639 while (tv3.tv_sec < PIC_TIMEOUT);
640
641 printf("%s: fatal error: cpu not ready\n", __func__);
642 pic32_standby();
643 io_exit(EX_SOFTWARE); /* Panic */
644 }
645
646 /*
647 * XferInstruction Pseudo Operation
648 *
649 * To send 32 bits of data for the device to execute
650 *
651 * DS60001145M-page 18
652 */
653 uint32_t
pic32_xferinstruction(uint32_t instruction)654 pic32_xferinstruction(uint32_t instruction)
655 {
656 uint32_t response;
657
658 /* Wait until CPU is ready */
659 pic32_wait_for_cpu();
660
661 /* Select data register */
662 pic32_sendcommand(PIC32_ETAP_DATA);
663
664 /* Send the instruction */
665 response = pic32_xferdata(32, instruction);
666
667 /* Select control register */
668 pic32_sendcommand(PIC32_ETAP_CONTROL);
669
670 /* Tell CPU to execute instruction */
671 pic32_xferdata(32, PIC32_EJTAG_CONTROL_PROBEN | PIC32_EJTAG_CONTROL_PROBTRAP);
672
673 return response;
674 }
675
676 /*
677 * ReadFromAddress Pseudo Operation for PIC32MX, PIC32MZ & PIC32MK devices
678 *
679 * To read 32 bits of data from the device memory
680 *
681 * DS60001145P-page 18
682 */
683 uint32_t
pic32_readfromaddress_m4k(uint32_t addr)684 pic32_readfromaddress_m4k(uint32_t addr)
685 {
686 uint32_t data;
687
688 /*
689 * 1. Load Fast Data register address to s3
690 */
691
692 /* LUI S3, 0xFF20 LOAD UPPER IMMEDIATE, CLEAR LOWER */
693 pic32_xferinstruction(0x3C13FF20);
694
695 /*
696 * 2. Load memory address to be read into t0
697 */
698
699 /* LUI T0, <Addr31:16> LOAD UPPER IMMEDIATE, CLEAR LOWER */
700 pic32_xferinstruction(0x3C080000 | (addr >> 16));
701 /* ORI T0,T0 <Addr15:0> OR LOWER IMMEDIATE */
702 pic32_xferinstruction(0x35080000 | (addr & 0xFFFF));
703
704 /*
705 * 3. Read data
706 */
707
708 /* LW T1, 0(T0) LOAD WORD */
709 pic32_xferinstruction(0x8D090000);
710
711 /*
712 * 4. Store data into Fast Data register
713 */
714
715 /* SW T1, 0(S3) STORE WORD */
716 pic32_xferinstruction(0xAE690000);
717 /* NOP */
718 pic32_xferinstruction(0x00000000);
719
720 /*
721 * 5. Shift out the data
722 */
723
724 /* Select the Fastdata Register */
725 pic32_sendcommand(PIC32_ETAP_FASTDATA);
726
727 /* Send/Receive 32-bit Data */
728 data = pic32_xferfastdata(0);
729
730 return data;
731 }
732
733 /*
734 * ReadFromAddress Pseudo Operation for PIC32MM devices
735 *
736 * To read 32 bits of data from the device memory
737 *
738 * DS60001145P-page 19
739 * DS60001364C-page 17
740 */
741 uint32_t
pic32_readfromaddress_mm(uint32_t addr)742 pic32_readfromaddress_mm(uint32_t addr)
743 {
744 uint32_t data;
745
746 /*
747 * 1. Load Fast Data register address to s3
748 */
749
750 /* LUI S3, 0xFF20 LOAD UPPER IMMEDIATE, CLEAR LOWER */
751 pic32_xferinstruction(0xFF2041B3);
752
753 /*
754 * 2. Load memory address to be read into t0
755 */
756
757 /* LUI T0, <Addr31:16> LOAD UPPER IMMEDIATE, CLEAR LOWER */
758 pic32_xferinstruction(0x000041A8 | (addr & 0xFFFF0000));
759 /* ORI T0,T0 <Addr15:0> OR LOWER IMMEDIATE */
760 pic32_xferinstruction(0x00005108 | (addr << 16));
761
762 /*
763 * 3. Read data
764 */
765
766 /* LW T1, 0(T0) LOAD WORD */
767 pic32_xferinstruction(0x0000FD28);
768
769 /*
770 * 4. Store data into Fast Data register
771 */
772
773 /* SW T1, 0(S3) STORE WORD */
774 pic32_xferinstruction(0x0000F933);
775 /* NOP32 */
776 pic32_xferinstruction(0x00000000);
777
778 /*
779 * 5. Shift out the data
780 */
781
782 /* Select the Fastdata Register */
783 pic32_sendcommand(PIC32_ETAP_FASTDATA);
784
785 /* Send/Receive 32-bit Data */
786 data = pic32_xferfastdata(0);
787
788 return data;
789 }
790
791 /*
792 * Read From Address
793 */
794 static inline uint32_t
pic32_readfromaddress(uint32_t addr)795 pic32_readfromaddress(uint32_t addr)
796 {
797 switch (pic32_map[pic32_index].datasheet) {
798 default:return pic32_readfromaddress_m4k(addr);
799 case DS60001324B: /* PIC32MM */
800 return pic32_readfromaddress_mm(addr);
801 }
802 }
803
804 /*****************************************************************************
805 *
806 * Memory Operations
807 *
808 *****************************************************************************/
809
810 /*
811 * Kernel KSEG1 address to physical address
812 *
813 * DS61115F-page 3-15
814 */
815 static inline uint32_t
pic32_phy(uint32_t addr)816 pic32_phy(uint32_t addr)
817 {
818 return addr & 0x1FFFFFFF;
819 }
820
821 /*
822 * Physical address to kernel KSEG1 address
823 *
824 * DS61115F-page 3-15
825 */
826 static inline uint32_t
pic32_kseg1(uint32_t addr)827 pic32_kseg1(uint32_t addr)
828 {
829 return addr | 0xA0000000;
830 }
831
832 /*****************************************************************************
833 *
834 * Utility Operations
835 *
836 *****************************************************************************/
837
838 /*
839 * Check device status
840 *
841 * DS60001145M-page 20
842 */
843 uint32_t
pic32_check_device_status(void)844 pic32_check_device_status(void)
845 {
846 pic32_sendcommand(PIC32_MTAP_SW_MTAP);
847 pic32_sendcommand(PIC32_MTAP_COMMAND);
848
849 return pic32_xferdata(PIC32_MCHP_STATUS) & PIC32_MCHP_STATUS_MASK;
850 }
851
852 /*
853 * Erase Device
854 *
855 * DS60001145M-page 21
856 * DS60001364C-page 20
857 */
858 static inline void
pic32_erase_device(void)859 pic32_erase_device(void)
860 {
861 uint32_t statusVal;
862 struct timeval tv1, tv2, tv3;
863
864 /*
865 * SendCommand (MTAP_SW_MTAP).
866 *
867 * SendCommand (MTAP_COMMAND).
868 *
869 * XferData (MCHP_ERASE).
870 */
871
872 pic32_sendcommand(PIC32_MTAP_SW_MTAP);
873 pic32_sendcommand(PIC32_MTAP_COMMAND);
874 pic32_xferdata(PIC32_MCHP_ERASE);
875
876 /*
877 * XferData (MCHP_DE_ASSERT_RST), not PIC32MX.
878 */
879
880 if ((pic32_map[pic32_index].datasheet == DS60001191C) || /* MZ EC */
881 (pic32_map[pic32_index].datasheet == DS60001324B)) { /* MM */
882 pic32_xferdata(PIC32_MCHP_DE_ASSERT_RST);
883 }
884
885 /*
886 * Delay > 10 ms.
887 *
888 * statusVal = XferData (MCHP_STATUS).
889 *
890 * If CFGRDY (statusVal<3>) is not ‘1’ and FCBUSY (statusVal<2>) is not ‘0’, GOTO to step 5.
891 */
892
893 gettimeofday(&tv1, NULL);
894 do {
895 /*
896 * Wait for "Self-Timed Page Erase Time"
897 *
898 * Eg. DS60001324B-page 214
899 */
900 io_usleep(18000); /* 18 ms */
901
902 statusVal = pic32_xferdata(PIC32_MCHP_STATUS) & (PIC32_MCHP_STATUS_CFGRDY | PIC32_MCHP_STATUS_FCBUSY);
903 gettimeofday(&tv2, NULL);
904 timersub(&tv2, &tv1, &tv3);
905 }
906 while ((statusVal != PIC32_MCHP_STATUS_CFGRDY) && (tv3.tv_sec < PIC_TIMEOUT));
907
908 if (statusVal != PIC32_MCHP_STATUS_CFGRDY) {
909 printf("%s: fatal error: erase device failed\n", __func__);
910 pic32_standby();
911 io_exit(EX_SOFTWARE); /* Panic */
912 }
913 }
914
915 /*
916 * Enter Serial Execution Mode
917 *
918 * DS60001145M-page 22
919 */
920 void
pic32_enter_serial_execution_mode(void)921 pic32_enter_serial_execution_mode(void)
922 {
923 uint32_t statusVal;
924
925 statusVal = pic32_check_device_status();
926 if (statusVal != (PIC32_MCHP_STATUS_CPS | PIC32_MCHP_STATUS_CFGRDY)) {
927 printf("%s: fatal error: status invalid [0x%02X]\n", __func__, statusVal);
928 pic32_standby();
929 io_exit(EX_SOFTWARE); /* Panic */
930 }
931
932 pic32_xferdata(PIC32_MCHP_ASSERT_RST); /* 2-Wire */
933
934 pic32_sendcommand(PIC32_MTAP_SW_ETAP);
935 pic32_sendcommand(PIC32_ETAP_EJTAGBOOT);
936
937 pic32_sendcommand(PIC32_MTAP_SW_MTAP); /* 2-Wire ... */
938 pic32_sendcommand(PIC32_MTAP_COMMAND);
939
940 pic32_xferdata(PIC32_MCHP_DE_ASSERT_RST);
941
942 /*
943 * Flash Enable, PIC32MX devices only
944 */
945
946 if ((pic32_map[pic32_index].datasheet != DS60001191C) && /* ! MZ EC */
947 (pic32_map[pic32_index].datasheet != DS60001324B)) { /* ! MM */
948 pic32_xferdata(PIC32_MCHP_FLASH_ENABLE);
949 statusVal = pic32_xferdata(PIC32_MCHP_STATUS) & PIC32_MCHP_STATUS_MASK;
950 if (statusVal != (PIC32_MCHP_STATUS_CPS | PIC32_MCHP_STATUS_CFGRDY | PIC32_MCHP_STATUS_FAEN)) {
951 printf("%s: fatal error: status invalid [0x%02X]\n", __func__, statusVal);
952 pic32_standby();
953 io_exit(EX_SOFTWARE); /* Panic */
954 }
955 }
956
957 pic32_sendcommand(PIC32_MTAP_SW_ETAP);
958 }
959
960 /*****************************************************************************
961 *
962 * PE loader
963 *
964 *****************************************************************************/
965
966 /*
967 * PIC32MX BMX
968 */
969 static void
pic32_bmx(void)970 pic32_bmx(void)
971 {
972 /*
973 * PIC32MX devices only: Initialize BMXCON to 0x1F0040.
974 *
975 * lui a0,0xbf88
976 * ori a0,a0,0x2000 // address of BMXCON
977 * lui a1,0x1f
978 * ori a1,a1,0x40 // $a1 has 0x1f0040
979 * sw a1,0(a0) // BMXCON initialized
980 */
981
982 pic32_xferinstruction(0x3c04bf88);
983 pic32_xferinstruction(0x34842000);
984 pic32_xferinstruction(0x3c05001f);
985 pic32_xferinstruction(0x34a50040);
986 pic32_xferinstruction(0xac850000);
987
988 /*
989 * PIC32MX devices only: Initialize BMXDKPBA to 0x800.
990 *
991 * li a1,0x800
992 * sw a1,16(a0)
993 */
994
995 pic32_xferinstruction(0x34050800);
996 pic32_xferinstruction(0xac850010);
997
998 /*
999 * PIC32MX devices only: Initialize BMXDUDBA and BMXDUPBA to the value of BMXDRMSZ.
1000 *
1001 * lw a1,64(a0) // load BMXDMSZ
1002 * sw a1,32(a0)
1003 * sw a1,48(a0)
1004 */
1005
1006 pic32_xferinstruction(0x8C850040);
1007 pic32_xferinstruction(0xac850020);
1008 pic32_xferinstruction(0xac850030);
1009 }
1010
1011 #if 0
1012 /*
1013 * Download the PE for PIC32MX, PIC32MZ & PIC32MK devices
1014 *
1015 * Custom PE loader.
1016 */
1017 void
1018 pic32_download_custom_pe_m4k(uint8_t *pe, uint32_t nbytes)
1019 {
1020 /* PIC32MX BMX */
1021 if (pic32_map[pic32_index].datasheet != DS60001191C) /* ! MZ EC */
1022 pic32_bmx();
1023
1024 /* LUI S0, <RAM_ADDR(31:16)> */
1025 pic32_xferinstruction(0x3C1A0000);
1026
1027 /* ORI S0,S0, <RAM_ADDR(15:0)> */
1028 pic32_xferinstruction(0x36100900);
1029
1030 for (uint32_t i = 0; i < nbytes; i += 4) {
1031 /* Get low and high word data */
1032 uint16_t datal = pe[i] | (pe[i + 1] << 8);
1033 uint16_t datah = pe[i + 2] | (pe[i + 3] << 8);
1034
1035 /* LUI T0, <Data31:16> LOAD UPPER IMMEDIATE, CLEAR LOWER */
1036 pic32_xferinstruction(0x3C080000 + datah);
1037
1038 /* ORI T0,T0 <Data15:0> OR LOWER IMMEDIATE */
1039 pic32_xferinstruction(0x35080000 + datal);
1040
1041 /* SW T0, <OFFSET>(S0) STORE WORD */
1042 pic32_xferinstruction(0xAE080000 + i);
1043 }
1044
1045 /*
1046 * Jump to the PE
1047 *
1048 * lui t9,0xa000
1049 * ori t9,t9,0x900
1050 * jr t9
1051 * nop
1052 */
1053
1054 pic32_xferinstruction(0x3c19a000);
1055 pic32_xferinstruction(0x37390900);
1056 pic32_xferinstruction(0x03200008);
1057 pic32_xferinstruction(0x00000000);
1058 }
1059 #endif
1060
1061 /*
1062 * Download the PE for PIC32MX, PIC32MZ & PIC32MK devices
1063 *
1064 * DS60001145N-page 23
1065 */
1066 void
pic32_download_pe_m4k(uint8_t * pe,uint32_t nbytes)1067 pic32_download_pe_m4k(uint8_t *pe, uint32_t nbytes)
1068 {
1069 /* PE LOADER OP CODES */
1070 static uint32_t peloader[] = {
1071 0x3c07dead, // lui a3, 0xdead
1072 0x3c06ff20, // lui a2, 0xff20
1073 0x3c05ff20, // lui al, 0xff20
1074 // here1:
1075 0x8cc40000, // lw a0, 0 (a2)
1076 0x8cc30000, // lw v1, 0 (a2)
1077 0x1067000b, // beq v1, a3, <here3>
1078 0x00000000, // nop
1079 0x1060fffb, // beqz v1, <here1>
1080 0x00000000, // nop
1081 // here2:
1082 0x8ca20000, // lw v0, 0 (a1)
1083 0x2463ffff, // addiu v1, v1, -1
1084 0xac820000, // sw v0, 0 (a0)
1085 0x24840004, // addiu a0, a0, 4
1086 0x1460fffb, // bnez v1, <here2>
1087 0x00000000, // nop
1088 0x1000fff3, // b <here1>
1089 0x00000000, // nop
1090 // here3:
1091 0x3c02a000, // lui v0, 0xa000
1092 0x34420900, // ori v0, v0, 0x900
1093 0x00400008, // jr v0
1094 0x00000000, // nop
1095 };
1096 #define PESIZE (sizeof(peloader) / sizeof(uint32_t))
1097
1098 /* PIC32MX BMX */
1099 if (pic32_map[pic32_index].datasheet != DS60001191C) /* ! MZ EC */
1100 pic32_bmx();
1101
1102 /*
1103 * Set up PIC32 RAM address for PE.
1104 *
1105 * lui a0,0xa000
1106 * ori a0,a0,0x800
1107 */
1108
1109 pic32_xferinstruction(0x3c04a000);
1110 pic32_xferinstruction(0x34840800);
1111
1112 /*
1113 * Load the PE_Loader.
1114 *
1115 * lui a2, <PE_loader hi++>
1116 * ori a2,a2, <PE_loader lo++>
1117 * sw a2,0(a0)
1118 * addiu a0,a0,4
1119 */
1120
1121 for (uint32_t i = 0; i < PESIZE; ++i) {
1122 uint32_t datah = peloader[i] >> 16;
1123 uint32_t datal = peloader[i] & 0x0000FFFF;
1124
1125 pic32_xferinstruction(0x3c060000 + datah);
1126 pic32_xferinstruction(0x34c60000 + datal);
1127 pic32_xferinstruction(0xac860000);
1128 pic32_xferinstruction(0x24840004);
1129 }
1130
1131 /*
1132 * Jump to the PE_Loader.
1133 *
1134 * lui t9,0xa000
1135 * ori t9,t9,0x800
1136 * jr t9
1137 * nop
1138 */
1139
1140 pic32_xferinstruction(0x3c19a000);
1141 pic32_xferinstruction(0x37390800);
1142 pic32_xferinstruction(0x03200008);
1143 pic32_xferinstruction(0x00000000);
1144
1145 /*
1146 * Load the PE using the PE_Loader.
1147 */
1148
1149 pic32_sendcommand(PIC32_ETAP_FASTDATA);
1150 pic32_xferfastdata(pic32_kseg1(0x0900));
1151 pic32_xferfastdata(nbytes >> 2);
1152 for (uint32_t i = 0; i < nbytes; i += 4) {
1153 uint32_t wdata = (uint32_t)pe[i] |
1154 ((uint32_t)pe[i + 1] << 8) |
1155 ((uint32_t)pe[i + 2] << 16) |
1156 ((uint32_t)pe[i + 3] << 24);
1157 pic32_xferfastdata(wdata);
1158 }
1159
1160 /*
1161 * Jump to the PE.
1162 */
1163
1164 pic32_xferfastdata(0x00000000);
1165 pic32_xferfastdata(0xDEAD0000);
1166 io_usleep(10000); /* 10ms */
1167 }
1168
1169 #if 0
1170 /*
1171 * PIC32MM CFGCON
1172 */
1173 static void
1174 pic32_cfgcon(void)
1175 {
1176 pic32_xferinstruction(0xBF8041A4); /* lui a0,0xbf80 */
1177 pic32_xferinstruction(0x3B005084); /* ori a0,a0,0x3b00 */
1178 pic32_xferinstruction(0x000041A5); /* lui a1,0x0000 */
1179 pic32_xferinstruction(0x000050A5); /* ori a1,a1,0x0000 */
1180 pic32_xferinstruction(0x0000F8A4); /* sw a1,0(a0) */
1181 }
1182 #endif
1183
1184 /*
1185 * Download the PE for PIC32MM devices
1186 *
1187 * Custom PE loader.
1188 */
1189 void
pic32_download_custom_pe_mm(uint8_t * pe,uint32_t nbytes)1190 pic32_download_custom_pe_mm(uint8_t *pe, uint32_t nbytes)
1191 {
1192 uint32_t address = 0xA0000300;
1193
1194 /* LUI A0, <RAM_ADDR(31:16)> */
1195 pic32_xferinstruction(0x41A4 | (address & 0xFFFF0000));
1196
1197 /* ORI A0,A0, <RAM_ADDR(15:0)> */
1198 pic32_xferinstruction(0x5084 | (address << 16));
1199
1200 for (uint32_t i = 0; i < nbytes; i += 4) {
1201 /* Get low and high word data */
1202 uint16_t datal = pe[i] | (pe[i + 1] << 8);
1203 uint16_t datah = pe[i + 2] | (pe[i + 3] << 8);
1204
1205 /* LUI A1, <Data31:16> LOAD UPPER IMMEDIATE, CLEAR LOWER */
1206 pic32_xferinstruction(0x41A5 | (datah << 16));
1207
1208 /* ORI A1,A1 <Data15:0> OR LOWER IMMEDIATE */
1209 pic32_xferinstruction(0x50A5 | (datal << 16));
1210
1211 /* SW A1, <OFFSET>(A0) STORE WORD */
1212 pic32_xferinstruction(0xF8A4 | (i << 16));
1213 }
1214 #if 1
1215 for (uint32_t i = 0; i < nbytes; i += 4) {
1216 uint32_t *ptr = (uint32_t *)&pe[i];
1217 uint32_t wrote = *ptr;
1218 uint32_t read = pic32_readfromaddress(address + i);
1219 printf("ADDRESS=0x%08X WROTE=0x%08X READ=0x%08X\n",
1220 address + i, wrote, read);
1221 if (wrote != read) {
1222 printf("FAULT\n");
1223 pic32_standby();
1224 io_exit(EX_SOFTWARE); /* Panic */
1225 }
1226 }
1227 #endif
1228 /*
1229 * Jump to the PE.
1230 *
1231 * lui t9,0xXXXX
1232 * ori t9,t9,0xXXXX
1233 * jr t9; nop16
1234 */
1235
1236 pic32_xferinstruction(0x41B9 | (address & 0xFFFF0000));
1237 pic32_xferinstruction(0x5339 | (address << 16));
1238 pic32_xferinstruction(0x0C004599);
1239 }
1240
1241 #if 0
1242 /*
1243 * Download the PE for PIC32MM devices
1244 *
1245 * DS60001145P-page 25
1246 * DS60001364C-page 23
1247 *
1248 * XXX DATA-SHEET INVALID
1249 */
1250 void
1251 pic32_download_pe_mm(uint8_t *pe, uint32_t nbytes)
1252 {
1253 /* PE LOADER OP CODES */
1254 static uint32_t peloader[] = {
1255 0xDEAD41A7, // lui a3, 0xdead
1256 0xFF2041A6, // lui a2, 0xff20
1257 0xFF2041A5, // lui al, 0xff20
1258 // here1:
1259 0x69E06A60, // lw a0, 0 (a2)
1260 // lw v1, 0 (a2)
1261 0x000C94E3, // beq v1, a3, <here3>
1262 0x8DFA0C00, // nop16
1263 // beqz v1, <here1>
1264 // here2:
1265 // lw v0, 0 (a1)
1266 0xE9406DBE, // addiu v1, v1, -1
1267 // sw v0, 0 (a0)
1268 0xADFB6E42, // addiu a0, a0, 4
1269 // bnez v1, <here2>
1270 0xCFF20C00, // nop16
1271 // b <here1>
1272 0x0C000C00, // nop16; nop16
1273 // here3:
1274 0xA00041A2, // lui v0, 0xa000
1275 0x03005042, // ori v0, v0, 0x300
1276 0x0C004582, // jr v0
1277 // nop16
1278 };
1279 #define PESIZE (sizeof(peloader) / sizeof(uint32_t))
1280
1281 printf("%s() 1\n", __func__);
1282
1283 /*
1284 * Set up the PIC32MM RAM address for the PE.
1285 *
1286 * lui a0,0xa000
1287 * ori a0,a0,0x200 XXX
1288 */
1289
1290 pic32_xferinstruction(0xA00041A4);
1291 pic32_xferinstruction(0x02005084);
1292
1293 /*
1294 * Load the PE_loader.
1295 *
1296 * lui a2, <PE_loader hi++>
1297 * ori a2,a2, <PE_loader lo++>
1298 * sw a2,0(a0)
1299 * addiu a0,a0,4
1300 */
1301
1302 for (uint32_t i = 0; i < PESIZE; ++i) {
1303 pic32_xferinstruction(0x41A6 | (peloader[i] & 0xFFFF0000));
1304 pic32_xferinstruction(0x50C6 | (peloader[i] << 16));
1305 pic32_xferinstruction(0x6E42EB40);
1306 }
1307
1308 /*
1309 * Jump to the PE_loader.
1310 *
1311 * lui t9,0xa000
1312 * ori t9,t9,0x200 XXX
1313 * jr t9; nop16
1314 */
1315
1316 pic32_xferinstruction(0xA00041B9);
1317 pic32_xferinstruction(0x02005339);
1318 pic32_xferinstruction(0x0C004599);
1319
1320 /*
1321 * Load the PE using the PE_loader.
1322 */
1323
1324 printf("%s() 2\n", __func__);
1325
1326 pic32_sendcommand(PIC32_ETAP_FASTDATA);
1327 pic32_xferfastdata(pic32_kseg1(0x0300));
1328 pic32_xferfastdata(nbytes >> 2);
1329 for (uint32_t i = 0; i < nbytes; i += 4) {
1330 uint32_t wdata = (uint32_t)pe[i] |
1331 ((uint32_t)pe[i + 1] << 8) |
1332 ((uint32_t)pe[i + 2] << 16) |
1333 ((uint32_t)pe[i + 3] << 24);
1334 pic32_xferfastdata(wdata);
1335 }
1336
1337 /*
1338 * Jump to the PE.
1339 */
1340
1341 printf("%s() 3\n", __func__);
1342
1343 pic32_xferfastdata(0x00000000);
1344 pic32_xferfastdata(0xDEAD0000);
1345 io_usleep(10000); /* 10ms */
1346 }
1347 #endif
1348
1349 /*****************************************************************************
1350 *
1351 * Download data
1352 *
1353 *****************************************************************************/
1354
1355 /*
1356 * Download Data Block for PIC32MX, PIC32MZ & PIC32MK devices
1357 *
1358 * DS60001145M-page 25
1359 */
1360 void
pic32_download_data_block_m4k(uint32_t * panel,uint32_t panel_size)1361 pic32_download_data_block_m4k(uint32_t *panel, uint32_t panel_size)
1362 {
1363 /*
1364 * Initialize SRAM Base Address to 0xA0000000.
1365 */
1366
1367 /* LUI S0, 0xA000 LOAD UPPER IMMEDIATE, CLEAR LOWER */
1368 pic32_xferinstruction(0x3C10A000);
1369
1370 /*
1371 * Write the entire row of data to be programmed into system SRAM.
1372 *
1373 * Repeat until one row of data has been loaded.
1374 */
1375
1376 uint32_t offset = 0;
1377 uint16_t datal, datah;
1378 do {
1379 /* Get low and high word data */
1380 datal = (uint16_t)panel[offset + 0] | (uint16_t)panel[offset + 1] << 8;
1381 datah = (uint16_t)panel[offset + 2] | (uint16_t)panel[offset + 3] << 8;
1382
1383 /* LUI T0, <Data31:16> LOAD UPPER IMMEDIATE, CLEAR LOWER */
1384 pic32_xferinstruction(0x3C080000 | datah);
1385
1386 /* ORI T0,T0 <Data15:0> OR LOWER IMMEDIATE */
1387 pic32_xferinstruction(0x35080000 | datal);
1388
1389 /* SW T0, <OFFSET>(S0) STORE WORD */
1390 pic32_xferinstruction(0xAE080000 | offset);
1391
1392 /* OFFSET increments by 4 */
1393 offset += 4;
1394 }
1395 while (offset < panel_size);
1396 }
1397
1398 /*
1399 * Download Data Block for PIC32MM devices
1400 *
1401 * DS60001364C-page 24
1402 */
1403 void
pic32_download_data_block_mm(uint32_t * panel,uint32_t panel_size)1404 pic32_download_data_block_mm(uint32_t *panel, uint32_t panel_size)
1405 {
1406 /*
1407 * Initialize SRAM Base Address to 0xA0000000.
1408 */
1409
1410 /* LUI A0, 0xA000 LOAD UPPER IMMEDIATE, CLEAR LOWER */
1411 pic32_xferinstruction(0xA00041A4);
1412
1413 /*
1414 * Write the entire row of data to be programmed into system SRAM.
1415 *
1416 * Repeat until one row of data has been loaded.
1417 */
1418
1419 uint32_t offset = 0;
1420 uint16_t datal, datah;
1421 do {
1422 /* Get low and high word data */
1423 datal = (uint16_t)panel[offset + 0] | (uint16_t)panel[offset + 1] << 8;
1424 datah = (uint16_t)panel[offset + 2] | (uint16_t)panel[offset + 3] << 8;
1425
1426 /* LUI A1, <Data31:16> LOAD UPPER IMMEDIATE, CLEAR LOWER */
1427 pic32_xferinstruction(0x41A5 | (datah << 16));
1428
1429 /* ORI A1,A1 <Data15:0> OR LOWER IMMEDIATE */
1430 pic32_xferinstruction(0x50A5 | (datal << 16));
1431
1432 /* SW A1, <OFFSET>(A0) STORE WORD */
1433 pic32_xferinstruction(0xF8A4 | (offset << 16));
1434
1435 /* OFFSET increments by 4 */
1436 offset += 4;
1437 }
1438 while (offset < panel_size);
1439 }
1440
1441 /*
1442 * Download Data Block
1443 */
1444 static inline void
pic32_download_data_block(uint32_t * panel,uint32_t panel_size)1445 pic32_download_data_block(uint32_t *panel, uint32_t panel_size)
1446 {
1447 switch (pic32_map[pic32_index].datasheet) {
1448 default:pic32_download_data_block_m4k(panel, panel_size);
1449 break;
1450 case DS60001324B: /* PIC32MM */
1451 pic32_download_data_block_mm(panel, panel_size);
1452 break;
1453 }
1454 }
1455
1456 /*****************************************************************************
1457 *
1458 * Flash write
1459 *
1460 *****************************************************************************/
1461
1462 /*
1463 * Flash Row Write for PIC32MX, PIC32MZ & PIC32MK devices
1464 *
1465 * DS60001145M-page 26
1466 */
1467 void
pic32_flash_row_write_m4k(uint32_t address)1468 pic32_flash_row_write_m4k(uint32_t address)
1469 {
1470 /*
1471 * Registers a1, a2, and a3 are set for WREN = 1 or NVMOP<3:0> = 0011,
1472 * WR = 1 and WREN = 1, respectively.
1473 *
1474 * Registers s1 and s2 are set for the unlock data values and S0 is
1475 * initialized to ‘0’.
1476 */
1477
1478 pic32_xferinstruction(0x34054003); /* ori a1,$0,0x4003 */
1479 pic32_xferinstruction(0x34068000); /* ori a2,$0,0x8000 */
1480 pic32_xferinstruction(0x34074000); /* ori a3,$0,0x4000 */
1481
1482 pic32_xferinstruction(0x3c11aa99); /* lui s1,0xaa99 */
1483 pic32_xferinstruction(0x36316655); /* ori s1,s1,0x6655 */
1484 pic32_xferinstruction(0x3c125566); /* lui s2,0x5566 */
1485 pic32_xferinstruction(0x365299aa); /* ori s2,s2,0x99aa */
1486
1487 /*
1488 * Set the physical source SRAM address
1489 */
1490
1491 pic32_xferinstruction(0x3c100000); /* lui s0,0x0000 <RAM_ADDR(31:16)> */
1492
1493 /*
1494 * PIC32MX devices only: Set register a0 to the base address of the NVM
1495 * register (0xBF80_F400).
1496 */
1497
1498 if (pic32_map[pic32_index].datasheet != DS60001191C) { /* ! MZ EC */
1499 pic32_xferinstruction(0x3c04bf80); /* lui a0,0xbf80 */
1500 pic32_xferinstruction(0x3484f400); /* ori a0,a0,0xf400 */
1501 }
1502
1503 /*
1504 * PIC32MZ EC devices only: Set register a0 to the base address of the
1505 * NVM register (0xBF80_0600).
1506 *
1507 * Register s3 is set for the value used to disable write protection in
1508 * NVMBPB.
1509 *
1510 * Unlock and disable Boot Flash write protection.
1511 */
1512
1513 else {
1514 pic32_xferinstruction(0x3c04bf80); /* lui a0,0xbf80 */
1515 pic32_xferinstruction(0x34840600); /* ori a0,a0,0x0600 */
1516
1517 pic32_xferinstruction(0x34138080); /* ori s3,$0,0x8080 */
1518
1519 pic32_xferinstruction(0xac910010); /* sw s1,16(a0) */
1520 pic32_xferinstruction(0xac920010); /* sw s2,16(a0) */
1521 pic32_xferinstruction(0xac930090); /* sw s3,144(a0) */
1522
1523 pic32_xferinstruction(0x00000000); /* nop */
1524 }
1525
1526 /*
1527 * Set the NVMADDR register with the address of the Flash row to be programmed.
1528 */
1529
1530 uint32_t addrh = pic32_phy(address) >> 16, addrl = pic32_phy(address) & 0x0000FFFF;
1531
1532 pic32_xferinstruction(0x3c080000 + addrh); /* lui t0,<FLASH_ROW_ADDR(31:16)> */
1533 pic32_xferinstruction(0x35080000 + addrl); /* ori t0,t0,<FLASH_ROW_ADDR(15:0)> */
1534 pic32_xferinstruction(0xac880020); /* sw t0,32(a0) */
1535
1536 /*
1537 * PIC32MX devices only: Set the NVMSRCADDR register with the physical
1538 * source SRAM address (offset is 64).
1539 */
1540
1541 if (pic32_map[pic32_index].datasheet != DS60001191C) /* ! MZ EC */
1542 pic32_xferinstruction(0xac900040); /* sw s0,64(a0) */
1543
1544 /*
1545 * PIC32MZ EC devices only: Set the NVMSRCADDR register with the
1546 * physical source SRAM address (offset is 112).
1547 */
1548
1549 else
1550 pic32_xferinstruction(0xac900070); /* sw s0,112(a0) */
1551
1552 /*
1553 * Set up the NVMCON register for write operation.
1554 */
1555
1556 pic32_xferinstruction(0xac850000); /* sw a1,0(a0) */
1557 #if 0
1558 io_usleep(6); /* Min. delay 6 us */
1559 #endif
1560 /*
1561 * Unlock the NVMCON register and start the write operation.
1562 */
1563
1564 pic32_xferinstruction(0xac910010); /* sw s1,16(a0) */
1565 pic32_xferinstruction(0xac920010); /* sw s2,16(a0) */
1566 pic32_xferinstruction(0xac860008); /* sw a2,8(a0) */
1567
1568 /*
1569 * Wait for "Self-Timed Row Write Cycle Time"
1570 *
1571 * Eg. DS60001324B-page 214
1572 */
1573 #if 0
1574 io_usleep(1500); /* 1.5 ms */
1575 #endif
1576 /*
1577 * Clear the WREN bit (NVMCONM<14>).
1578 */
1579
1580 pic32_xferinstruction(0xac870004); /* sw a3,4(a0) */
1581 }
1582
1583 /*
1584 * Flash Row Write for PIC32MM devices
1585 *
1586 * DS60001145P-page 29
1587 * DS60001364C-page 26
1588 */
1589 void
pic32_flash_row_write_mm(uint32_t address)1590 pic32_flash_row_write_mm(uint32_t address)
1591 {
1592 /*
1593 * Initialize constants. Registers a1 and a2 are set for WREN = 1 or NVMOP<3:0> = 0011
1594 * and WR = 1, respectively. Registers s1 and s2 are set for the unlock data values and
1595 * s0 is initialized to ‘0’.
1596 */
1597
1598 pic32_xferinstruction(0x400350A0); /* li a1,0x4003 */
1599 pic32_xferinstruction(0x800050C0); /* li a2,0x8000 */
1600
1601 pic32_xferinstruction(0xAA9941B1); /* lui s1,0xaa99 */
1602 pic32_xferinstruction(0x66555231); /* ori s1,s1,0x6655 */
1603 pic32_xferinstruction(0x556641B2); /* lui s2,0x5566 */
1604 pic32_xferinstruction(0x99AA5252); /* ori s2,s2,0x99aa */
1605
1606 /*
1607 * Set the physical source SRAM address
1608 */
1609
1610 pic32_xferinstruction(0x000041B0); /* lui s0,0x0000 <RAM_ADDR(31:16)> */
1611
1612 /*
1613 * Set register a0 to the base address of the NVM controller (0xBF80_2380). Register s3
1614 * is set for the value used to disable write protection in NVMBPB.
1615 */
1616
1617 pic32_xferinstruction(0xBF8041A4); /* lui a0,0xbf80 */
1618 pic32_xferinstruction(0x23805084); /* ori a0,a0,0x2380 */
1619 pic32_xferinstruction(0x80005260); /* li s3,0x8000 // BWPAUNLK bit mask */
1620
1621 /*
1622 * Unlock and disable Boot Flash write protection.
1623 */
1624
1625 pic32_xferinstruction(0x0010FA24); /* sw s1,16(a0) // NVMKEY = 0xaa996655 */
1626 pic32_xferinstruction(0x0010FA44); /* sw s2,16(a0) // NVMKEY = 0x556699aa */
1627 pic32_xferinstruction(0x0070FA64); /* sw s3,112(a0) // BWPAUNLK bit (NVMBPB register) = 1 */
1628
1629 /*
1630 * Set the NVMADDR register with the address of the Flash row to be programmed.
1631 */
1632
1633 pic32_xferinstruction(0x41A8 | (address & 0xFFFF0000)); /* lui t0,<FLASH_ROW_ADDR(31:16)> */
1634 pic32_xferinstruction(0x5108 | (address << 16)); /* ori t0,t0,<FLASH_ROW_ADDR(15:0)> */
1635 pic32_xferinstruction(0x0020F904); /* sw t0,32(a0) */
1636
1637 /*
1638 * Set the NVMSRCADDR register with the physical source SRAM address.
1639 */
1640
1641 pic32_xferinstruction(0x0050FA04); /* sw s0,80(a0) */
1642
1643 /*
1644 * Set up the NVMCON register for write operation.
1645 */
1646
1647 pic32_xferinstruction(0x0C00EAC0); /* sw a1,0(a0); nop16 // NVMCON = 0x4003 */
1648 #if 0
1649 io_usleep(6); /* Min. delay 6 us */
1650 #endif
1651 /*
1652 * Unlock the NVMCON register and start the write operation (WR bit = 1).
1653 */
1654
1655 pic32_xferinstruction(0xFA44E8C4); /* sw s1,16(a0) // NVMKEY = 0xaa996655 */
1656 pic32_xferinstruction(0xEB420010); /* sw s2,16(a0) // NVMKEY = 0x556699aa */
1657 /* sw a2,8(a0) // NVMCONSET = 0x8000 */
1658 /*
1659 * Wait for "Self-Timed Row Write Cycle Time"
1660 *
1661 * Eg. DS60001324B-page 214
1662 */
1663 #if 0
1664 io_usleep(1500); /* 1.5 ms */
1665 #endif
1666 /*
1667 * Clear the WREN bit (NVMCONM<14>).
1668 */
1669
1670 pic32_xferinstruction(0x400050E0); /* li a3,0x4000 */
1671 pic32_xferinstruction(0x0C00EBC1); /* sw a3,4(a0); nop16 */
1672 }
1673
1674 /*
1675 * Flash Row Write
1676 */
1677 static inline void
pic32_flash_row_write(uint32_t address)1678 pic32_flash_row_write(uint32_t address)
1679 {
1680 switch (pic32_map[pic32_index].datasheet) {
1681 default:pic32_flash_row_write_m4k(address);
1682 break;
1683 case DS60001324B: /* PIC32MM */
1684 pic32_flash_row_write_mm(address);
1685 break;
1686 }
1687 }
1688
1689 /*
1690 * Get PE Resonse
1691 *
1692 * DS60001145N-page 30
1693 */
1694 static inline uint32_t
pic32_getperesponse(void)1695 pic32_getperesponse(void)
1696 {
1697 return pic32_xferinstruction(0x00000000);
1698 }
1699
1700 /*****************************************************************************
1701 *
1702 * PE Commands
1703 *
1704 *****************************************************************************/
1705
1706 /*
1707 * PE ROW PROGRAM
1708 *
1709 * Op code 0x0
1710 *
1711 * DS60001145N-page 32
1712 */
1713 void
pic32_pe_row_program(uint32_t addr,uint32_t * panel,uint32_t panel_size)1714 pic32_pe_row_program(uint32_t addr, uint32_t *panel, uint32_t panel_size)
1715 {
1716 /* Select the Fastdata Register */
1717 pic32_sendcommand(PIC32_ETAP_FASTDATA);
1718
1719 /* Op code + Operand */
1720 pic32_xferfastdata(panel_size >> 2);
1721
1722 /* PHYSICAL Address */
1723 pic32_xferfastdata(pic32_phy(addr));
1724
1725 /* Data */
1726 for (uint32_t i = 0; i < panel_size; i += 4) {
1727 uint32_t wdata = (uint32_t)panel[i] |
1728 ((uint32_t)panel[i + 1] << 8) |
1729 ((uint32_t)panel[i + 2] << 16) |
1730 ((uint32_t)panel[i + 3] << 24);
1731 pic32_xferfastdata(wdata);
1732 }
1733
1734 /* Check response */
1735 uint32_t rc = pic32_getperesponse();
1736 if (rc & 0xFFFF) {
1737 printf("%s: fatal error: PE ROW PROGRAM failed [0x%08X]\n",
1738 __func__, rc);
1739 pic32_standby();
1740 io_exit(EX_SOFTWARE); /* Panic */
1741 }
1742 }
1743
1744 /*
1745 * PE READ
1746 *
1747 * Op code 0x1
1748 *
1749 * DS60001145N-page 33
1750 */
1751 void
pic32_pe_read(uint32_t addr,uint16_t nwords,uint32_t * data)1752 pic32_pe_read(uint32_t addr, uint16_t nwords, uint32_t *data)
1753 {
1754 /* Select the Fastdata Register */
1755 pic32_sendcommand(PIC32_ETAP_FASTDATA);
1756
1757 /* Op code + Operand */
1758 pic32_xferfastdata(0x00010000 + nwords);
1759
1760 /* KSEG1 Address */
1761 pic32_xferfastdata(pic32_kseg1(addr));
1762
1763 /* Check response */
1764 uint32_t rc = pic32_getperesponse();
1765 if (rc != 0x00010000) {
1766 printf("%s: fatal error: PE READ failed [0x%08X]\n",
1767 __func__, rc);
1768 pic32_standby();
1769 io_exit(EX_SOFTWARE); /* Panic */
1770 }
1771
1772 /* Select the Fastdata Register */
1773 pic32_sendcommand(PIC32_ETAP_FASTDATA);
1774
1775 /* Get Data */
1776 for (uint32_t i = 0; i < nwords; ++i)
1777 data[i] = pic32_xferfastdata(0);
1778 }
1779
1780 /*****************************************************************************
1781 *
1782 * PE functions
1783 *
1784 *****************************************************************************/
1785
1786 /*
1787 * PE LOAD
1788 */
1789 void
pic32_pe_load(void)1790 pic32_pe_load(void)
1791 {
1792 uint8_t *pe = NULL;
1793 uint32_t nbytes = 0;
1794
1795 /* Validate PE */
1796 if (pic32_conf.pepath[0] == '\0') {
1797 return;
1798 }
1799
1800 /* Get PE */
1801 pe = pic_pe_read_file(pic32_conf.pepath, &nbytes);
1802 if (pe == NULL) {
1803 bzero(pic32_conf.pepath, STRLEN);
1804 return;
1805 }
1806
1807 /* Download PE (upload to chip) */
1808 switch (pic32_map[pic32_index].datasheet) {
1809 default:pic32_download_pe_m4k(pe, nbytes);
1810 break;
1811 case DS60001324B: /* PIC32MM */
1812 pic32_download_custom_pe_mm(pe, nbytes);
1813 break;
1814 }
1815
1816 /* Free PE */
1817 free(pe);
1818 }
1819
1820 /*
1821 * PE READ WITH CACHE
1822 */
1823 uint32_t
pic32_pe_readword(uint32_t address)1824 pic32_pe_readword(uint32_t address)
1825 {
1826 static uint32_t cache_addr = UINT32_MAX;
1827 static uint32_t cache_data[PIC32_PE_READWORDS];
1828
1829 uint32_t new_address = address & PIC32_PE_READPAGE;
1830
1831 if (new_address != cache_addr) {
1832 pic32_pe_read(new_address, PIC32_PE_READWORDS, cache_data);
1833 cache_addr = new_address;
1834 }
1835 return cache_data[(address >> 2) & PIC32_PE_READMASK];
1836 }
1837
1838 /*****************************************************************************
1839 *
1840 * Compound functions
1841 *
1842 *****************************************************************************/
1843
1844 /*
1845 * BLANK DEVICE
1846 *
1847 * DISABLE PROTECTION AND BULK ERASE
1848 */
1849 void
pic32_bulk_erase(void)1850 pic32_bulk_erase(void)
1851 {
1852 pic32_program_verify();
1853
1854 pic32_erase_device();
1855
1856 pic32_standby();
1857 }
1858
1859 /*****************************************************************************
1860 *
1861 * Read block data
1862 *
1863 *****************************************************************************/
1864
1865 /*
1866 * GET CONFIGURATION
1867 */
1868 int32_t
pic32_read_config_memory(void)1869 pic32_read_config_memory(void)
1870 {
1871 /* NULL device */
1872 pic32_index = PIC32_SIZE;
1873
1874 /* Reset configuraton */
1875 memset(&pic32_conf, 0, sizeof(pic32_conf));
1876
1877 pic32_program_verify();
1878
1879 /* Device id/rev */
1880 pic32_conf.deviceid = pic32_xferdata(32, 0);
1881
1882 uint32_t dev = 0;
1883 while (pic32_map[dev].deviceid) {
1884 if (pic32_map[dev].deviceid == (pic32_conf.deviceid & PIC32_IDMASK))
1885 break;
1886 ++dev;
1887 }
1888 if (!pic32_map[dev].deviceid) {
1889 if (pic32_conf.deviceid == 0x00000000 || pic32_conf.deviceid == 0xFFFFFFFF) {
1890 printf("%s: information: %s\n",
1891 __func__, io_fault(pic32_conf.deviceid));
1892 } else {
1893 printf("%s: information: device unknown: [%08X]\n",
1894 __func__, pic32_conf.deviceid);
1895 }
1896 pic32_standby();
1897 return -1;
1898 }
1899
1900 /* Device recognised */
1901 pic32_index = dev;
1902
1903 /* Device status */
1904 pic32_conf.status = pic32_check_device_status();
1905 if (PIC32_MCHP_STATUS_CFGRDY != (pic32_conf.status & (PIC32_MCHP_STATUS_CFGRDY | PIC32_MCHP_STATUS_FCBUSY))) {
1906 printf("%s: information: status invalid [0x%02X]\n", __func__, pic32_conf.status);
1907 pic32_standby();
1908 return -1;
1909 }
1910
1911 pic32_enter_serial_execution_mode();
1912
1913 /* Device id/rev */
1914 switch (pic32_map[pic32_index].datasheet) {
1915 default:pic32_conf.devidaddr = PIC32_DEVID;
1916 break;
1917 case DS60001324B: /* PIC32MM */
1918 pic32_conf.devidaddr = PIC32MM_DEVID;
1919 break;
1920 }
1921
1922 /* Device id/rev validation */
1923 uint32_t deviceid = pic32_readfromaddress(pic32_conf.devidaddr);
1924 if (deviceid != pic32_conf.deviceid) {
1925 printf("%s: information: device id invalid [0x%08X] != [0x%08X]\n",
1926 __func__, deviceid, pic32_conf.deviceid);
1927 pic32_standby();
1928 return -1;
1929 }
1930
1931 /* Device family */
1932 dev = 0;
1933 while (pic32_tab[dev].datasheet) {
1934 if (pic32_tab[dev].datasheet == pic32_map[pic32_index].datasheet) {
1935 pic_pe_lookup(pic32_conf.pepath, pic32_tab[dev].filename);
1936 break;
1937 }
1938 ++dev;
1939 }
1940
1941 /* Config */
1942 switch (pic32_map[pic32_index].datasheet) {
1943 default:pic32_conf.configaddr = PIC32_BOOT + (pic32_map[pic32_index].boot << 2) - (4 << 2);
1944 pic32_conf.configsize = PIC32_CONFIG_SIZE;
1945 for (uint32_t i = 0; i < pic32_conf.configsize; ++i)
1946 pic32_conf.config[pic32_conf.configsize - 1 - i] = pic32_readfromaddress(pic32_conf.configaddr + 4 * i);
1947 break;
1948 case DS60001324B: /* PIC32MM */
1949 pic32_conf.configaddr = PIC32MM_PRI_CONFIG;
1950 pic32_conf.configsize = PIC32MM_CONFIG_SIZE;
1951 for (uint32_t i = 0; i < pic32_conf.configsize; ++i)
1952 pic32_conf.config[i] = pic32_readfromaddress(pic32_conf.configaddr + 4 * i);
1953 break;
1954 }
1955
1956 pic32_standby();
1957
1958 return 0;
1959 }
1960
1961 /*
1962 * GET PROGRAM COUNT
1963 *
1964 * RETURN NUMBER OF PARTITIONS
1965 */
1966 uint32_t
pic32_get_program_count(void)1967 pic32_get_program_count(void)
1968 {
1969 return 1;
1970 }
1971
1972 /*
1973 * GET PROGRAM FLASH SIZE
1974 *
1975 * RETURN SIZE IN WORDS
1976 */
1977 uint32_t
pic32_get_program_size(uint32_t * addr,uint32_t partition)1978 pic32_get_program_size(uint32_t *addr, uint32_t partition)
1979 {
1980 *addr = pic32_phy(PIC32_CODE);
1981
1982 return pic32_map[pic32_index].prog;
1983 }
1984
1985 /*
1986 * GET BOOT FLASH SIZE
1987 *
1988 * RETURN SIZE IN WORDS
1989 */
1990 uint32_t
pic32_get_boot_size(uint32_t * addr)1991 pic32_get_boot_size(uint32_t *addr)
1992 {
1993 *addr = pic32_phy(PIC32_BOOT);
1994
1995 return pic32_map[pic32_index].boot;
1996 }
1997
1998 /*
1999 * READ PROGRAM FLASH MEMORY BLOCK ADDR .. ADDR + SIZE
2000 *
2001 * RETURN ADDR
2002 */
2003 uint32_t
pic32_read_program_memory_block(uint32_t * data,uint32_t addr,uint32_t size)2004 pic32_read_program_memory_block(uint32_t *data, uint32_t addr, uint32_t size)
2005 {
2006 pic32_program_verify();
2007 pic32_enter_serial_execution_mode();
2008 pic32_pe_load();
2009
2010 if (pic32_conf.pepath[0]) {
2011 /* PE */
2012 for (uint32_t i = 0; i < size; ++i) {
2013 data[i] = pic32_pe_readword(addr);
2014 addr += 4;
2015 }
2016 } else {
2017 /* !PE */
2018 for (uint32_t i = 0; i < size; ++i) {
2019 data[i] = pic32_readfromaddress(addr);
2020 addr += 4;
2021 }
2022 }
2023
2024 pic32_standby();
2025
2026 return addr;
2027 }
2028
2029 /*****************************************************************************
2030 *
2031 * Program Code
2032 *
2033 *****************************************************************************/
2034
2035 /*
2036 * WRITE PANEL TO 32-BIT PROGRAM FLASH
2037 */
2038 void
pic32_write_panel(uint32_t region,uint32_t address,uint32_t * panel,uint32_t panel_size)2039 pic32_write_panel(uint32_t region, uint32_t address, uint32_t *panel, uint32_t panel_size)
2040 {
2041 switch (region) {
2042 case PIC_REGIONCODE:
2043 case PIC_REGIONBOOT:
2044 if (pic32_conf.pepath[0]) {
2045 /* PE */
2046 pic32_pe_row_program(address, panel, panel_size);
2047 } else {
2048 /* !PE */
2049 pic32_download_data_block(panel, panel_size);
2050 pic32_flash_row_write(address);
2051 }
2052 break;
2053 default:printf("%s: warning: region unsupported [%d]\n", __func__, region);
2054 break;
2055 }
2056 }
2057
2058 /*****************************************************************************
2059 *
2060 * Programming
2061 *
2062 *****************************************************************************/
2063
2064 /*
2065 * DETERMINE MEMORY REGION: CODE OR BOOT
2066 *
2067 * RETURN PIC_REGIONCODE:
2068 * 0x1D000000 .. 0x1D1FFFFF (2048KB)
2069 *
2070 * RETURN PIC_REGIONBOOT:
2071 * 0x1FC00000 .. 0x1FC1XXXX
2072 *
2073 * DS60001145N-page 10
2074 */
2075 uint32_t
pic32_getregion(uint32_t address)2076 pic32_getregion(uint32_t address)
2077 {
2078 uint32_t vaddr = pic32_kseg1(address);
2079
2080 if (vaddr >= PIC32_CODE && vaddr < (PIC32_CODE + (pic32_map[pic32_index].prog << 2))) {
2081 return PIC_REGIONCODE;
2082 }
2083 if (vaddr >= PIC32_BOOT && vaddr < (PIC32_BOOT + (pic32_map[pic32_index].boot << 2))) {
2084 return PIC_REGIONBOOT;
2085 }
2086 if (p.f) fprintf(p.f, "%s: warning: address unsupported [%08X]\n",
2087 __func__, address);
2088 return PIC_REGIONNOTSUP;
2089 }
2090
2091 /*
2092 * INIT REGION FOR WRITING
2093 *
2094 * RETURN REGION IF WRITING SUPPORTED
2095 */
2096 static inline uint32_t
pic32_init_writeregion(uint32_t region)2097 pic32_init_writeregion(uint32_t region)
2098 {
2099 switch (region) {
2100 case PIC_REGIONCODE:
2101 case PIC_REGIONBOOT:
2102 pic_write_panel(PIC_PANEL_BEGIN, region, pic32_map[pic32_index].row << 2);
2103 return region;
2104 }
2105 if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
2106 __func__, region);
2107 return PIC_REGIONNOTSUP;
2108 }
2109
2110 /*
2111 * WRITE REGION
2112 */
2113 static inline void
pic32_writeregion(uint32_t address,uint32_t region,uint32_t data)2114 pic32_writeregion(uint32_t address, uint32_t region, uint32_t data)
2115 {
2116 switch (region) {
2117 case PIC_REGIONCODE:
2118 case PIC_REGIONBOOT:
2119 pic_write_panel(PIC_PANEL_UPDATE, address, data);
2120 return;
2121 }
2122 if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
2123 __func__, region);
2124 }
2125
2126 /*
2127 * INIT REGION FOR VERIFY
2128 *
2129 * RETURN REGION IF VERIFY SUPPORTED
2130 */
2131 static inline uint32_t
pic32_init_verifyregion(uint32_t region)2132 pic32_init_verifyregion(uint32_t region)
2133 {
2134 switch (region) {
2135 case PIC_REGIONCODE:
2136 case PIC_REGIONBOOT:
2137 /* Nothing to do on PIC32 */
2138 return region;
2139 }
2140 if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
2141 __func__, region);
2142 return PIC_REGIONNOTSUP;
2143 }
2144
2145 /*
2146 * GET VERIFY DATA FOR REGION
2147 */
2148 static inline uint32_t
pic32_verifyregion(uint32_t address,uint32_t region,uint32_t wdata)2149 pic32_verifyregion(uint32_t address, uint32_t region, uint32_t wdata)
2150 {
2151 uint32_t vdata = 0;
2152
2153 if (region == PIC_REGIONNOTSUP) {
2154 if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
2155 __func__, region);
2156 return wdata;
2157 }
2158 if (pic32_conf.pepath[0]) {
2159 /* PE */
2160 vdata = pic32_pe_readword(address);
2161 } else {
2162 /* !PE */
2163 vdata = pic32_readfromaddress(pic32_kseg1(address));
2164 }
2165 return vdata;
2166 }
2167
2168 /*****************************************************************************
2169 *
2170 * Program & verify
2171 *
2172 *****************************************************************************/
2173
2174 /*
2175 * BEGIN PROGRAMMING
2176 */
2177 void
pic32_program_begin(void)2178 pic32_program_begin(void)
2179 {
2180 pic32_program_verify();
2181 pic32_enter_serial_execution_mode();
2182 pic32_pe_load();
2183 }
2184
2185 /*
2186 * PROGRAM DATA
2187 */
2188 uint32_t
pic32_program_data(uint32_t current_region,pic_data * pdata)2189 pic32_program_data(uint32_t current_region, pic_data *pdata)
2190 {
2191 uint32_t address, new_region;
2192
2193 for (uint32_t i = 0; i < pdata->nbytes; ++i) {
2194 address = pdata->address + i;
2195 new_region = pic32_getregion(address);
2196 if (new_region != current_region) {
2197 pic_write_panel(PIC_PANEL_END, PIC_VOID, PIC_VOID);
2198 current_region = pic32_init_writeregion(new_region);
2199 }
2200 if (current_region == PIC_REGIONNOTSUP)
2201 continue;
2202 pic32_writeregion(address, current_region, pdata->bytes[i]);
2203 }
2204 return current_region;
2205 }
2206
2207 /*
2208 * END PROGRAMMING
2209 */
2210 void
pic32_program_end(int config)2211 pic32_program_end(__attribute__((unused)) int config)
2212 {
2213 pic_write_panel(PIC_PANEL_END, PIC_VOID, PIC_VOID);
2214 pic32_standby();
2215 }
2216
2217 /*
2218 * VERIFY DATA
2219 */
2220 uint32_t
pic32_verify_data(uint32_t current_region,pic_data * pdata,uint32_t * fail)2221 pic32_verify_data(uint32_t current_region, pic_data *pdata, uint32_t *fail)
2222 {
2223 uint32_t address, new_region, wdata, vdata;
2224
2225 for (uint32_t i = 0; i < pdata->nbytes; i += 4) {
2226 address = pdata->address + i;
2227 new_region = pic32_getregion(address);
2228 if (new_region != current_region)
2229 current_region = pic32_init_verifyregion(new_region);
2230 if (current_region == PIC_REGIONNOTSUP)
2231 continue;
2232 wdata = (uint32_t)pdata->bytes[i] |
2233 ((uint32_t)pdata->bytes[i + 1] << 8) |
2234 ((uint32_t)pdata->bytes[i + 2] << 16) |
2235 ((uint32_t)pdata->bytes[i + 3] << 24);
2236 vdata = pic32_verifyregion(address, current_region, wdata);
2237 if (vdata != wdata) {
2238 if (p.f) printf("%s: error: read [%08X] expected [%08X] at [%08X]\n",
2239 __func__, vdata, wdata, pic32_phy(address));
2240 pdata->bytes[i] = vdata;
2241 pdata->bytes[i + 1] = vdata >> 8;
2242 pdata->bytes[i + 2] = vdata >> 16;
2243 pdata->bytes[i + 3] = vdata >> 24;
2244 (*fail) += 4;
2245 }
2246 }
2247 return current_region;
2248 }
2249
2250 /*
2251 * VIEW DATA
2252 */
2253 void
pic32_view_data(pic_data * pdata)2254 pic32_view_data(pic_data *pdata)
2255 {
2256 uint32_t wdata;
2257
2258 printf("[%08X] ", pdata->address);
2259 for (uint32_t i = 0; i < pdata->nbytes; i += 4) {
2260 wdata = (uint32_t)pdata->bytes[i] |
2261 ((uint32_t)pdata->bytes[i + 1] << 8) |
2262 ((uint32_t)pdata->bytes[i + 2] << 16) |
2263 ((uint32_t)pdata->bytes[i + 3] << 24);
2264 printf("%08X ", wdata);
2265 }
2266 putchar('\n');
2267 }
2268
2269 /*****************************************************************************
2270 *
2271 * Diagnostic functions
2272 *
2273 *****************************************************************************/
2274
2275 /*
2276 * DUMP DEVICE ID DETAILS
2277 */
2278 void
pic32_dumpdeviceid(void)2279 pic32_dumpdeviceid(void)
2280 {
2281 printf("[%08X] [PROGRAM] %08X WORDS\n", pic32_phy(PIC32_CODE), pic32_map[pic32_index].prog);
2282 printf("[%08X] [DEVICEID] %08X VER:%1X DEV:%04X MAN:%03X %s\n",
2283 pic32_phy(pic32_conf.devidaddr),
2284 pic32_conf.deviceid,
2285 (pic32_conf.deviceid & 0xF0000000) >> 28,
2286 (pic32_conf.deviceid & 0x0FFFF000) >> 12,
2287 (pic32_conf.deviceid & 0x00000FFF),
2288 pic32_map[pic32_index].devicename);
2289 printf("[%08X] [BOOT] %08X WORDS\n", pic32_phy(PIC32_BOOT), pic32_map[pic32_index].boot);
2290 pic32_dumpconfig(PIC_BRIEF, 0);
2291 if (pic32_conf.pepath[0]) {
2292 char *pedup = (char *)strdup(pic32_conf.pepath);
2293 if (pedup == NULL) {
2294 printf("%s: fatal error: strdup failed\n", __func__);
2295 io_exit(EX_OSERR); /* Panic */
2296 }
2297 printf(" [PE] %s\n", basename(pedup));
2298 free(pedup);
2299 }
2300 }
2301
2302 /*
2303 * DUMP CONFIG WORD DETAILS FOR DEVICE
2304 */
2305 void
pic32_dumpconfig(uint32_t mode,uint32_t partition)2306 pic32_dumpconfig(uint32_t mode, uint32_t partition)
2307 {
2308 switch (pic32_map[pic32_index].datasheet) {
2309 default:for (uint32_t i = 0; i < pic32_conf.configsize; ++i) {
2310 printf("[%08X] [DEVCFG%d] %08X\n", pic32_phy(pic32_conf.configaddr + 4 * i),
2311 pic32_conf.configsize - 1 - i, pic32_conf.config[pic32_conf.configsize - 1 - i]);
2312 }
2313 break;
2314 case DS60001324B: /* PIC32MM */
2315 printf("[%08X] [RESERVED] %08X\n", pic32_phy(pic32_conf.configaddr), pic32_conf.config[0]);
2316 printf("[%08X] [FDEVOPT] %08X\n", pic32_phy(pic32_conf.configaddr) + 4, pic32_conf.config[1]);
2317 printf("[%08X] [FICD] %08X\n", pic32_phy(pic32_conf.configaddr) + 8, pic32_conf.config[2]);
2318 printf("[%08X] [FPOR] %08X\n", pic32_phy(pic32_conf.configaddr) + 12, pic32_conf.config[3]);
2319 printf("[%08X] [FWDT] %08X\n", pic32_phy(pic32_conf.configaddr) + 16, pic32_conf.config[4]);
2320 printf("[%08X] [FOCSEL] %08X\n", pic32_phy(pic32_conf.configaddr) + 20, pic32_conf.config[5]);
2321 printf("[%08X] [FSEC] %08X\n", pic32_phy(pic32_conf.configaddr) + 24, pic32_conf.config[6]);
2322 printf("[%08X] [RESERVED] %08X\n", pic32_phy(pic32_conf.configaddr) + 28, pic32_conf.config[7]);
2323 printf("[%08X] [FSIGN] %08X\n", pic32_phy(pic32_conf.configaddr) + 32, pic32_conf.config[8]);
2324 printf("[%08X] [RESERVED] %08X\n", pic32_phy(pic32_conf.configaddr) + 36, pic32_conf.config[9]);
2325 }
2326 }
2327
2328 /*
2329 * DUMP HEX FLASH WORDS
2330 */
2331 void
pic32_dumphexcode(uint32_t address,uint32_t size,uint32_t * data)2332 pic32_dumphexcode(uint32_t address, uint32_t size, uint32_t *data)
2333 {
2334 uint32_t i, j, nlines = 0;
2335
2336 for (i = 0; i < size; address += 16, i += 4) {
2337 #ifndef DEBUG
2338 if (pic_mtcode(PIC32_MASK, 4, &data[i]))
2339 continue;
2340 #endif
2341 printf("[%08X] ", pic32_phy(address));
2342 for (j = 0; j < 4; ++j) {
2343 printf("%08X ", data[i + j]);
2344 }
2345 for (j = 0; j < 4; ++j) {
2346 putchar(PIC_CHAR(0xFF & data[i + j]));
2347 putchar(PIC_CHAR(0xFF & (data[i + j] >> 8)));
2348 putchar(PIC_CHAR(0xFF & (data[i + j] >> 16)));
2349 putchar(PIC_CHAR(0xFF & (data[i + j] >> 24)));
2350 }
2351 putchar('\n');
2352 nlines++;
2353 }
2354 if (!nlines)
2355 printf("%s: information: flash empty\n", __func__);
2356 }
2357
2358 /*
2359 * DUMP INHX32 FLASH WORDS
2360 */
2361 void
pic32_dumpinhxcode(uint32_t address,uint32_t size,uint32_t * data)2362 pic32_dumpinhxcode(uint32_t address, uint32_t size, uint32_t *data)
2363 {
2364 uint32_t i, j;
2365
2366 /* PIC32: Physical addressing */
2367 address = pic32_phy(address);
2368
2369 /* PIC32: Extended address */
2370 pic_dumpaddr(address, 1);
2371
2372 for (i = 0; i < size; address += 16, i += 4) {
2373 if (pic_mtcode(PIC32_MASK, 4, &data[i]))
2374 continue;
2375
2376 /* PIC32: Extended address */
2377 pic_dumpaddr(address, 0);
2378
2379 uint8_t cc, b0, b1, b2, b3;
2380 b0 = address >> 8;
2381 b1 = address;
2382 printf(":%02X%02X%02X00", 16, b0, b1);
2383
2384 cc = 16 + b0 + b1 + 0x00;
2385 for (j = 0; j < 4; ++j) {
2386 b0 = data[i + j];
2387 b1 = data[i + j] >> 8;
2388 b2 = data[i + j] >> 16;
2389 b3 = data[i + j] >> 24;
2390 printf("%02X%02X%02X%02X", b0, b1, b2, b3);
2391 cc = cc + b0 + b1 + b2 + b3;
2392 }
2393 printf("%02X\n", (0x0100 - cc) & 0xFF);
2394 }
2395 }
2396