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 #include "pickle.h"
21
22 /******************************************************************************
23 *
24 * Session
25 *
26 *****************************************************************************/
27
28 extern struct pickle p;
29
30 /*****************************************************************************
31 *
32 * Hardware operations
33 *
34 *****************************************************************************/
35
36 struct pic_ops pic16n_ops = {
37 .arch = ARCH16BIT,
38 .align = sizeof(uint8_t),
39 .selector = pic16n_selector,
40 #ifdef LOADER
41 .bootloader = pic16n_bootloader,
42 #else
43 .bootloader = NULL,
44 #endif
45 .program_begin = pic16n_program_begin,
46 .program_data = pic16n_program_data,
47 .program_end = pic16n_program_end,
48 .verify_begin = pic16n_program_verify,
49 .verify_data = pic16n_verify_data,
50 .verify_end = pic16n_standby,
51 .view_data = pic16n_view_data,
52 .read_config_memory = pic16n_read_config_memory,
53 .get_program_count = pic16n_get_program_count,
54 .get_program_size = pic16n_get_program_size,
55 .get_data_size = pic16n_get_data_size,
56 .get_executive_size = NULL,
57 .get_boot_size = NULL,
58 .read_program_memory_block = pic16n_read_program_memory_block,
59 .read_data_memory_block = pic16n_read_data_memory_block,
60 .write_panel = pic16n_write_panel,
61 .bulk_erase = pic16n_bulk_erase,
62 .write_osccal = NULL,
63 .write_bandgap = NULL,
64 .write_calib = NULL,
65 .row_erase = NULL,
66 .dumpdeviceid = pic16n_dumpdeviceid,
67 .dumpconfig = pic16n_dumpconfig,
68 .dumposccal = NULL,
69 .dumpdevice = pic16n_dumpdevice,
70 .dumpadj = 2,
71 .dumphexcode = pic16n_dumphexcode,
72 .dumpinhxcode = pic16n_dumpinhxcode,
73 .dumphexdata = pic16n_dumphexdata,
74 .dumpinhxdata = pic16n_dumpinhxdata,
75 .debug = NULL,
76 };
77
78 uint32_t
pic16n_arch(void)79 pic16n_arch(void)
80 {
81 p.pic = &pic16n_ops;
82
83 return p.pic->arch;
84 }
85
86 /*****************************************************************************
87 *
88 * Hardware configuration
89 *
90 *****************************************************************************/
91
92 struct pic16n_config pic16n_conf;
93
94 /*****************************************************************************
95 *
96 * Hardware config masks
97 *
98 * DS40001772B TABLE B-4: SUMMARY OF CONFIGURATION WORDS
99 * DS40001836A TABLE B-4: SUMMARY OF CONFIGURATION WORDS
100 * DS40001886B TABLE B-4: SUMMARY OF CONFIGURATION WORDS
101 * DS40001927A TABLE B-4: SUMMARY OF CONFIGURATION WORDS
102 * DS40001874F TABLE B-1: CONFIGURATION WORD AND MASK
103 *
104 * In the following tables ZERO represents undocumented configuration bits
105 *
106 *****************************************************************************/
107
108 /* 0 1L 1 1H 2 2L 3 2H 4 3L 5 3H 6 4L 7 4H 8 5L 9 5H A 6L B 6H */
109 uint8_t DS40001772B_B4[] = {0x77,0x29,0xE3,0xBF,0x7F,0x3F,0xFF,0x37,0x03,ZERO,0xFF,0x02};
110 uint8_t DS40001836A_B4[] = {0x77,0x2B,0xFF,0xBF,0x7F,0x3F,0x9F,0x2F,0x01,0x00};
111 uint8_t DS40001886B_B4[] = {0x77,0x2B,0xFF,0xBF,0x7F,0x3F,0x9F,0x2F,0x01,0x00};
112 uint8_t DS40001927A_B4[] = {0x77,0x2B,0xFF,0xBF,0x7F,0x3F,0x9F,0x2F,0x01,0x00};
113 uint8_t DS40001874F_B1[] = {0x77,0x29,0xE3,0xBF,0x7F,0x3F,0xFF,0x37,0x03,0x00,0xFF,0x02};
114
115 /*****************************************************************************
116 *
117 * Hardware algorithm map
118 *
119 *****************************************************************************/
120
121 struct pic16n_dsmap pic16n_map[] =
122 {
123 /*Device name Device id Data-sheet Flash Config EEProm Latches Inf/Con/Id MASKS*/
124 {"PIC18F24K40", PIC18F24K40, DS40001772B, PIC16N_WORD(16), 12, 256, 64, 0,0,16, DS40001772B_B4},
125 {"PIC18F25K40", PIC18F25K40, DS40001772B, PIC16N_WORD(32), 12, 256, 64, 0,0,16, DS40001772B_B4},
126 {"PIC18F45K40", PIC18F45K40, DS40001772B, PIC16N_WORD(32), 12, 256, 64, 0,0,16, DS40001772B_B4},
127 {"PIC18F26K40", PIC18F26K40, DS40001772B, PIC16N_WORD(64), 12, 1024, 64, 0,0,16, DS40001772B_B4},
128 {"PIC18F46K40", PIC18F46K40, DS40001772B, PIC16N_WORD(64), 12, 1024, 64, 0,0,16, DS40001772B_B4},
129 {"PIC18F27K40", PIC18F27K40, DS40001772B, PIC16N_WORD(128),12, 1024, 128, 0,0,16, DS40001772B_B4},
130 {"PIC18F47K40", PIC18F47K40, DS40001772B, PIC16N_WORD(128),12, 1024, 128, 0,0,16, DS40001772B_B4},
131 {"PIC18LF24K40",PIC18LF24K40, DS40001772B, PIC16N_WORD(16), 12, 256, 64, 0,0,16, DS40001772B_B4},
132 {"PIC18LF25K40",PIC18LF25K40, DS40001772B, PIC16N_WORD(32), 12, 256, 64, 0,0,16, DS40001772B_B4},
133 {"PIC18LF45K40",PIC18LF45K40, DS40001772B, PIC16N_WORD(32), 12, 256, 64, 0,0,16, DS40001772B_B4},
134 {"PIC18LF26K40",PIC18LF26K40, DS40001772B, PIC16N_WORD(64), 12, 1024, 64, 0,0,16, DS40001772B_B4},
135 {"PIC18LF46K40",PIC18LF46K40, DS40001772B, PIC16N_WORD(64), 12, 1024, 64, 0,0,16, DS40001772B_B4},
136 {"PIC18LF27K40",PIC18LF27K40, DS40001772B, PIC16N_WORD(128),12, 1024, 128, 0,0,16, DS40001772B_B4},
137 {"PIC18LF47K40",PIC18LF47K40, DS40001772B, PIC16N_WORD(128),12, 1024, 128, 0,0,16, DS40001772B_B4},
138
139 {"PIC18F24K42", PIC18F24K42, DS40001836A, PIC16N_WORD(16), 10, 256, 64, 32,5,16, DS40001836A_B4},
140 {"PIC18F25K42", PIC18F25K42, DS40001836A, PIC16N_WORD(32), 10, 256, 64, 32,5,16, DS40001836A_B4},
141 {"PIC18LF24K42",PIC18LF24K42, DS40001836A, PIC16N_WORD(16), 10, 256, 64, 32,5,16, DS40001836A_B4},
142 {"PIC18LF25K42",PIC18LF25K42, DS40001836A, PIC16N_WORD(32), 10, 256, 64, 32,5,16, DS40001836A_B4},
143
144 {"PIC18F26K42", PIC18F26K42, DS40001886B, PIC16N_WORD(64), 10, 1024, 128, 32,5,16, DS40001886B_B4},
145 {"PIC18F27K42", PIC18F27K42, DS40001886B, PIC16N_WORD(128),10, 1024, 128, 32,5,16, DS40001886B_B4},
146 {"PIC18F45K42", PIC18F45K42, DS40001886B, PIC16N_WORD(32), 10, 256, 128, 32,5,16, DS40001886B_B4},
147 {"PIC18F46K42", PIC18F46K42, DS40001886B, PIC16N_WORD(64), 10, 1024, 128, 32,5,16, DS40001886B_B4},
148 {"PIC18F47K42", PIC18F47K42, DS40001886B, PIC16N_WORD(128),10, 1024, 128, 32,5,16, DS40001886B_B4},
149 {"PIC18F55K42", PIC18F55K42, DS40001886B, PIC16N_WORD(32), 10, 256, 128, 32,5,16, DS40001886B_B4},
150 {"PIC18F56K42", PIC18F56K42, DS40001886B, PIC16N_WORD(64), 10, 1024, 128, 32,5,16, DS40001886B_B4},
151 {"PIC18F57K42", PIC18F57K42, DS40001886B, PIC16N_WORD(128),10, 1024, 128, 32,5,16, DS40001886B_B4},
152 {"PIC18LF26K42",PIC18LF26K42, DS40001886B, PIC16N_WORD(64), 10, 1024, 128, 32,5,16, DS40001886B_B4},
153 {"PIC18LF27K42",PIC18LF27K42, DS40001886B, PIC16N_WORD(128),10, 1024, 128, 32,5,16, DS40001886B_B4},
154 {"PIC18LF45K42",PIC18LF45K42, DS40001886B, PIC16N_WORD(32), 10, 256, 128, 32,5,16, DS40001886B_B4},
155 {"PIC18LF46K42",PIC18LF46K42, DS40001886B, PIC16N_WORD(64), 10, 1024, 128, 32,5,16, DS40001886B_B4},
156 {"PIC18LF47K42",PIC18LF47K42, DS40001886B, PIC16N_WORD(128),10, 1024, 128, 32,5,16, DS40001886B_B4},
157 {"PIC18LF55K42",PIC18LF55K42, DS40001886B, PIC16N_WORD(32), 10, 256, 128, 32,5,16, DS40001886B_B4},
158 {"PIC18LF56K42",PIC18LF56K42, DS40001886B, PIC16N_WORD(64), 10, 1024, 128, 32,5,16, DS40001886B_B4},
159 {"PIC18LF57K42",PIC18LF57K42, DS40001886B, PIC16N_WORD(128),10, 1024, 128, 32,5,16, DS40001886B_B4},
160
161 {"PIC18F25K83", PIC18F25K83, DS40001927A, PIC16N_WORD(32), 10, 1024, 128, 32,5,16, DS40001927A_B4},
162 {"PIC18F26K83", PIC18F26K83, DS40001927A, PIC16N_WORD(64), 10, 1024, 128, 32,5,16, DS40001927A_B4},
163 {"PIC18LF25K83",PIC18LF25K83, DS40001927A, PIC16N_WORD(32), 10, 1024, 128, 32,5,16, DS40001927A_B4},
164 {"PIC18LF26K83",PIC18LF26K83, DS40001927A, PIC16N_WORD(64), 10, 1024, 128, 32,5,16, DS40001927A_B4},
165
166 {"PIC18F46Q10", PIC18F46Q10, DS40001874F, PIC16N_WORD(64), 12, 1024, 2, 0,0,256, DS40001874F_B1},
167 {"PIC18F45Q10", PIC18F45Q10, DS40001874F, PIC16N_WORD(32), 12, 256, 2, 0,0,256, DS40001874F_B1},
168 {"PIC18F26Q10", PIC18F26Q10, DS40001874F, PIC16N_WORD(64), 12, 1024, 2, 0,0,256, DS40001874F_B1},
169 {"PIC18F25Q10", PIC18F25Q10, DS40001874F, PIC16N_WORD(32), 12, 256, 2, 0,0,256, DS40001874F_B1},
170 {"PIC18F24Q10", PIC18F24Q10, DS40001874F, PIC16N_WORD(16), 12, 256, 2, 0,0,256, DS40001874F_B1},
171 {"PIC18F27Q10", PIC18F27Q10, DS40001874F, PIC16N_WORD(128),12, 1024, 2, 0,0,256, DS40001874F_B1},
172 {"PIC18F47Q10", PIC18F47Q10, DS40001874F, PIC16N_WORD(128),12, 1024, 2, 0,0,256, DS40001874F_B1},
173
174 {"(null)", 0, 0, 0, 0, 0, 0, 0,0,0, 0},
175 /*Device name Device id Data-sheet Flash Config EEProm Latches Inf/Con/Id MASKS*/
176 };
177 #define PIC16N_SIZE ((sizeof(pic16n_map) / sizeof(struct pic16n_dsmap)) - 1)
178
179 /* Default device (null) */
180 uint32_t pic16n_index = PIC16N_SIZE;
181
182 void
pic16n_selector(void)183 pic16n_selector(void)
184 {
185 uint32_t i;
186 char *dnames[PIC16N_SIZE];
187
188 for (i = 0; i < PIC16N_SIZE; ++i) {
189 dnames[i] = pic16n_map[i].devicename;
190 }
191 qsort(dnames, PIC16N_SIZE, sizeof(char *), pic_cmp);
192 for (i = 0; i < PIC16N_SIZE; ++i) {
193 if ((i % PIC_NCOLS) == (PIC_NCOLS - 1))
194 printf("%s\n", dnames[i]);
195 else
196 printf("%s\t", dnames[i]);
197 }
198 if (i % PIC_NCOLS)
199 printf("\n");
200 printf("Total: %u\n", (uint32_t)PIC16N_SIZE);
201 }
202
203 #ifdef LOADER
204 void
pic16n_bootloader(void)205 pic16n_bootloader(void)
206 {
207 uint32_t dev, i;
208 char s[BUFLEN];
209
210 for (dev = 0; pic16n_map[dev].deviceid; ++dev) {
211 if (pic16n_map[dev].datasheet == DS40001874F)
212 continue;
213
214 for (i = 0; pic16n_map[dev].devicename[i] && i < BUFLEN; ++i)
215 s[i] = tolower(pic16n_map[dev].devicename[i]);
216 s[i] = 0;
217 printf("#IFDEF __%s\n", &pic16n_map[dev].devicename[3]);
218 printf(" LIST P=%s\n", pic16n_map[dev].devicename);
219 printf(" #INCLUDE \"p%s.inc\"\n", &s[3]);
220 printf(" NOLIST\n");
221 printf(" #DEFINE ERASE_FLASH 0x94\n");
222 printf(" #DEFINE WRITE_FLASH 0x84\n");
223 printf(" #DEFINE MAX_FLASH 0x%X\n",
224 pic16n_map[dev].flash << 1);
225 if (pic16n_map[dev].eeprom)
226 printf(" #DEFINE MAX_EE %d ; X 64\n",
227 pic16n_map[dev].eeprom / 64);
228 printf(" #DEFINE ROWSIZE %d\n",
229 pic16n_map[dev].latches);
230 printf(" #DEFINE ERASESIZE %d\n",
231 pic16n_map[dev].latches);
232 printf(" #DEFINE TYPE 2\n");
233 printf("#ENDIF\n");
234 }
235 }
236 #endif
237
238 /*****************************************************************************
239 *
240 * Program/Verify mode
241 *
242 *****************************************************************************/
243
244 /*
245 * ENTER HVP/LVP PROGRAM/VERIFY MODE
246 *
247 * ENTRY - VDD FIRST
248 */
249 void
pic16n_program_verify(void)250 pic16n_program_verify(void)
251 {
252 /* RESET & ACQUIRE GPIO */
253 io_set_vpp(LOW);
254 /* DS40001753B TENTS(100ns) */
255 io_usleep(1000);
256
257 /* PGD + PGC + PGM(N/A) LOW */
258 io_set_pgd(LOW);
259 io_set_pgc(LOW);
260 io_set_pgm(LOW);
261 io_usleep(1000);
262
263 /* INPUT DATA ON CLOCK RISING EDGE, MSB FIRST */
264 io_configure(FALSE, TRUE);
265
266 /* LVP */
267 if (p.key == LVPKEY) {
268 /* VPP HIGH */
269 io_set_vpp(HIGH);
270 /* TENTH(250ns) */
271 io_usleep(250);
272
273 /* VPP LOW */
274 io_set_vpp(LOW);
275 /* TENTH(250ns) */
276 io_usleep(250);
277
278 /* PROGRAM/VERIFY ENTRY CODE */
279 io_program_out(MCHPKEY, 32);
280 /* UNSPECIFIED */
281 io_usleep(250);
282 }
283 /* HVP */
284 else {
285 /* VPP HIGH */
286 io_set_vpp(HIGH);
287 /* DS40001753B TENTS(100ns) */
288 io_usleep(250);
289 }
290 }
291
292 /*
293 * EXIT HVP/LVP PROGRAM/VERIFY MODE
294 *
295 * EXIT - VDD LAST
296 */
297 void
pic16n_standby(void)298 pic16n_standby(void)
299 {
300 /* PGD + PGC + VPP + PGM(N/A) LOW */
301 io_set_pgd(LOW);
302 io_set_pgc(LOW);
303 io_set_vpp(LOW);
304 io_set_pgm(LOW);
305 }
306
307 /*****************************************************************************
308 *
309 * Hardware functions
310 *
311 *****************************************************************************/
312
313 /*I/O*************************************************************************/
314
315 /*
316 * LOAD DATA FOR NVM
317 * 0x00 PC = PC
318 * 0x02 PC = PC + 2 CODE
319 * 0x02 PC = PC + 1 DATA
320 *
321 * DS40001772B-page 12
322 */
323 static inline void
pic16n_load_data_for_nvm(uint32_t word,uint8_t j)324 pic16n_load_data_for_nvm(uint32_t word, uint8_t j /* 0 || 1 */)
325 {
326 io_program_out(j << 1, 8);
327 /* TDLY 1us */
328 io_program_out(word << 1, 24);
329 /* TDLY 1us */
330 }
331
332 /*
333 * READ DATA FROM NVM
334 * 0xFC PC = PC
335 * 0xFE PC = PC + 2 CODE
336 * 0xFE PC = PC + 1 DATA
337 *
338 * DS40001772B-page 10
339 */
340 static inline uint32_t
pic16n_read_data_from_nvm(uint8_t j)341 pic16n_read_data_from_nvm(uint8_t j /* 0 || 1 */)
342 {
343 uint32_t word;
344
345 io_program_out(0xFC | (j << 1), 8);
346 /* TDLY 1us */
347 word = io_program_in(24);
348 /* TDLY 1us */
349
350 word = (word >> 1) & PIC16N_WORD_MASK;
351
352 return word;
353 }
354
355 /*
356 * INCREMENT ADDRESS
357 * 0xF8 PC = PC + 2 CODE
358 * 0xF8 PC = PC + 1 DATA
359 *
360 * DS40001772B-page 10
361 */
362 static inline void
pic16n_increment_address(void)363 pic16n_increment_address(void)
364 {
365 io_program_out(0xF8, 8);
366 /* TDLY 1us */
367 }
368
369 /*
370 * LOAD PC ADDRESS
371 * 0x80 PC = address
372 *
373 * DS40001772B-page 10
374 * DS40001874F-page 10
375 */
376 static inline void
pic16n_load_pc_address(uint32_t address)377 pic16n_load_pc_address(uint32_t address)
378 {
379 io_program_out(0x80, 8);
380 /* TDLY 1us */
381 io_program_out(address << 1, 24);
382 /* TDLY 1us */
383 }
384
385 /*PROG************************************************************************/
386
387 /*
388 * BEGIN INTERNALLY TIMED PROGRAMMING
389 * 0xE0
390 *
391 * DS40001772B-page 12
392 *
393 * DS40001772B TPINT(2.8ms PROGRAM) TPINT(5.6ms CONFIG/EEPROM)
394 */
395 static inline void
pic16n_begin_internally_timed_programming(uint32_t t)396 pic16n_begin_internally_timed_programming(uint32_t t)
397 {
398 io_program_out(0xE0, 8);
399 /* TPINT */
400 io_usleep(t);
401 }
402
403 /*
404 * BEGIN EXTERNALLY TIMED PROGRAMMING
405 * 0xC0
406 *
407 * DS40001772B-page 12
408 *
409 * DS40001772B TPEXT(2.1ms PROGRAM) (NOT CONFIG)
410 */
411 static inline void
pic16n_begin_externally_timed_programming(uint32_t t)412 pic16n_begin_externally_timed_programming(uint32_t t)
413 {
414 io_program_out(0xC0, 8);
415 /* TPEXT */
416 io_usleep(t);
417 }
418
419 /*
420 * END EXTERNALLY TIMED PROGRAMMING
421 * 0x82
422 *
423 * DS40001772B-page 12
424 *
425 * DS40001772B TDIS(300us PROGRAM)
426 */
427 static inline void
pic16n_end_externally_timed_programming(uint32_t t)428 pic16n_end_externally_timed_programming(uint32_t t)
429 {
430 io_program_out(0x82, 8);
431 /* TDIS */
432 io_usleep(t);
433 }
434
435 /*
436 * PROGRAM DATA COMMAND
437 * 0xC0 PC = PC
438 * 0xE0 PC = PC + 2
439 *
440 * DS40001874F-page 12
441 *
442 * DS40001874F TPINT(65us PROGRAM & CONFIG) TPDFM (11ms EEPROM)
443 */
444 static inline void
pic16n_program_data_command(uint16_t word,uint8_t j,uint32_t t)445 pic16n_program_data_command(uint16_t word, uint8_t j /* 0 || 1 */, uint32_t t)
446 {
447 io_program_out(j ? 0xE0 : 0xC0, 8);
448 /* TDLY 1us */
449 io_program_out(word << 1, 24);
450 /* TPINT or TPDFM */
451 io_usleep(t);
452 }
453
454 /*ERASE***********************************************************************/
455
456 /*
457 * BULK ERASE MEMORY (PRELOAD PC)
458 * 0x18
459 *
460 * PC = 0x000000 ERASE PROGRAM AND CONFIG
461 * PC = 0x300000 ERASE PROGRAM AND CONFIG AND USERID
462 * PC = 0x310000 ERASE EEPROM
463 *
464 * DS40001772B-page 12
465 * DS40001874F-page 10
466 *
467 * DS40001772B TERAB(25.2ms PIC18F26K40)
468 */
469 static inline void
pic16n_bulk_erase_memory(uint32_t t)470 pic16n_bulk_erase_memory(uint32_t t)
471 {
472 io_program_out(0x18, 8);
473 io_usleep(t);
474 }
475
476 /*
477 * ROW ERASE MEMORY (PRELOAD PC)
478 * 0xF0
479 *
480 * DS40001772B-page 12
481 *
482 * DS40001772B TERAR(2.8ms)
483 */
484 static inline void
pic16n_row_erase_memory(uint32_t t)485 pic16n_row_erase_memory(uint32_t t)
486 {
487 io_program_out(0xF0, 8);
488 io_usleep(t);
489 }
490
491 /*****************************************************************************
492 *
493 * Compound functions
494 *
495 *****************************************************************************/
496
497 void
pic16n_bulk_erase(void)498 pic16n_bulk_erase(void)
499 {
500 uint32_t t = (pic16n_map[pic16n_index].datasheet == DS40001874F)
501 ? PIC16N_TERAB_Q : PIC16N_TERAB;
502
503 pic16n_program_verify();
504
505 pic16n_load_pc_address(PIC16N_USERID_ADDR);
506 pic16n_bulk_erase_memory(t);
507
508 if (pic16n_map[pic16n_index].eeprom) {
509 pic16n_load_pc_address(PIC16N_EEPROM_ADDR);
510 pic16n_bulk_erase_memory(t);
511 }
512
513 pic16n_standby();
514 }
515
516 #if 0
517 void
518 pic16n_row_erase(uint32_t row, uint32_t nrows)
519 {
520 fprintf(stderr, "%s()\n", __func__);
521 }
522 #endif
523
524 /*****************************************************************************
525 *
526 * Read block data
527 *
528 *****************************************************************************/
529
530 /*
531 * READ CONFIGURATION MEMORY AND STORE DEVICE MAP INDEX
532 */
533 int
pic16n_read_config_memory(void)534 pic16n_read_config_memory(void)
535 {
536 uint32_t dev;
537 uint16_t word;
538
539 /* NULL device */
540 pic16n_index = PIC16N_SIZE;
541
542 /* Reset configuraton */
543 memset(&pic16n_conf, 0, sizeof(pic16n_conf));
544
545 pic16n_program_verify();
546 pic16n_load_pc_address(PIC16N_REVID_ADDR);
547
548 pic16n_conf.revisionid = pic16n_read_data_from_nvm(1); /* Revisionid */
549 pic16n_conf.deviceid = pic16n_read_data_from_nvm(1); /* Deviceid */
550
551 /* Device detect */
552 for (dev = 0; pic16n_map[dev].deviceid; ++dev) {
553 if (pic16n_map[dev].deviceid == pic16n_conf.deviceid) {
554 break;
555 }
556 }
557 if (pic16n_map[dev].deviceid == 0) {
558 /*
559 * VELLEMAN K8048 SWITCH IN STANDBY [0000]
560 * VELLEMAN K8048 NO POWER [3FFF]
561 * VELLEMAN K0848 SWITCH IN RUN [3FFF]
562 * VELLEMAN K0848 SWITCH IN PROG [XXXX]
563 */
564 if (pic16n_conf.deviceid == 0x0000 || pic16n_conf.deviceid == 0x3FFF) {
565 printf("%s: information: %s\n",
566 __func__, io_fault(pic16n_conf.deviceid));
567 } else {
568 printf("%s: information: device unknown: [%04X]\n",
569 __func__, pic16n_conf.deviceid);
570 }
571 pic16n_standby();
572 return -1;
573 }
574
575 /* Device recognised */
576 pic16n_index = dev;
577
578 /*
579 * USER ID and CONFIG words are mapped to bytes because PIC18 HEX uses byte addressing.
580 */
581
582 /* User ID */
583 pic16n_load_pc_address(PIC16N_USERID_ADDR);
584 for (uint32_t i = 0; i < pic16n_map[pic16n_index].idsize; i += 2) {
585 word = pic16n_read_data_from_nvm(1);
586 pic16n_conf.userid[i] = word;
587 pic16n_conf.userid[i + 1] = word >> 8;
588 }
589
590 /* Config word(s) */
591 pic16n_load_pc_address(PIC16N_CONFIG_ADDR);
592 for (uint32_t i = 0; i < pic16n_map[pic16n_index].config; i += 2) {
593 word = pic16n_read_data_from_nvm(1);
594 pic16n_conf.config[i] = word;
595 pic16n_conf.config[i + 1] = word >> 8;
596 if (pic16n_map[pic16n_index].masks && (p.config & CONFIGAND)) {
597 pic16n_conf.config[i] &= pic16n_map[pic16n_index].masks[i];
598 pic16n_conf.config[i + 1] &= pic16n_map[pic16n_index].masks[i + 1];
599 }
600 }
601
602 /* Device information area */
603 if (pic16n_map[pic16n_index].devinfo) {
604 pic16n_load_pc_address(PIC16N_DEVINFO_ADDR);
605 for (uint32_t i = 0; i < pic16n_map[pic16n_index].devinfo && i < PIC16N_DEVINFO_MAX; ++i)
606 pic16n_conf.devinfo[i] = pic16n_read_data_from_nvm(1);
607 }
608
609 /* Device configuration information */
610 if (pic16n_map[pic16n_index].devconf) {
611 pic16n_load_pc_address(PIC16N_DEVCONF_ADDR);
612 for (uint32_t i = 0; i < pic16n_map[pic16n_index].devconf && i < PIC16N_DEVCONF_MAX; ++i)
613 pic16n_conf.devconf[i] = pic16n_read_data_from_nvm(1);
614 }
615
616 pic16n_standby();
617
618 return 0;
619 }
620
621 /*
622 * GET PROGRAM COUNT
623 *
624 * RETURN NUMBER OF PARTITIONS
625 */
626 uint32_t
pic16n_get_program_count(void)627 pic16n_get_program_count(void)
628 {
629 return 1;
630 }
631
632 /*
633 * GET PROGRAM FLASH SIZE
634 *
635 * RETURN SIZE IN WORDS
636 */
637 uint32_t
pic16n_get_program_size(uint32_t * addr,uint32_t partition)638 pic16n_get_program_size(uint32_t *addr, uint32_t partition)
639 {
640 *addr = 0;
641
642 return pic16n_map[pic16n_index].flash;
643 }
644
645 /*
646 * GET DATA EEPROM/FLASH SIZE
647 *
648 * RETURN SIZE IN BYTES
649 */
650 uint32_t
pic16n_get_data_size(uint32_t * addr)651 pic16n_get_data_size(uint32_t *addr)
652 {
653 *addr = PIC16N_EEPROM_ADDR;
654
655 return pic16n_map[pic16n_index].eeprom;
656 }
657
658 /*
659 * REWRITE EEPROM/FLASH ADDRESS
660 */
661 #if 0
662 static inline uint32_t
663 pic16n_get_data_addr(uint32_t addr)
664 {
665 if (addr >= PIC16N_EEFAKE_ADDR)
666 addr = addr - PIC16N_EEFAKE_ADDR + PIC16N_EEPROM_ADDR;
667
668 return addr;
669 }
670 #endif
671
672 /*
673 * READ PROGRAM FLASH MEMORY BLOCK ADDR .. ADDR + SIZE
674 *
675 * RETURN ADDR
676 */
677 uint32_t
pic16n_read_program_memory_block(uint32_t * data,uint32_t addr,uint32_t size)678 pic16n_read_program_memory_block(uint32_t *data, uint32_t addr, uint32_t size)
679 {
680 uint32_t i;
681
682 pic16n_program_verify();
683 pic16n_load_pc_address(addr);
684
685 for (i = 0; i < size; ++i)
686 data[i] = (uint32_t)pic16n_read_data_from_nvm(1);
687
688 pic16n_standby();
689
690 return addr;
691 }
692
693 /*
694 * READ DATA EEPROM BLOCK ADDR .. ADDR + SIZE
695 *
696 * RETURN ADDR
697 */
698 uint32_t
pic16n_read_data_memory_block(uint16_t * data,uint32_t addr,uint16_t size)699 pic16n_read_data_memory_block(uint16_t *data, uint32_t addr, uint16_t size)
700 {
701 uint32_t i;
702
703 pic16n_program_verify();
704 pic16n_load_pc_address(addr);
705
706 for (i = 0; i < size; i++)
707 data[i] = (uint16_t)pic16n_read_data_from_nvm(1);
708
709 pic16n_standby();
710
711 return addr;
712 }
713
714 /*****************************************************************************
715 *
716 * Program Code Panel
717 *
718 *****************************************************************************/
719
720 /*
721 * WRITE PANEL
722 */
723 void
pic16n_write_panel(uint32_t region,uint32_t address,uint32_t * panel,uint32_t panel_size)724 pic16n_write_panel(uint32_t region, uint32_t address, uint32_t *panel, uint32_t panel_size)
725 {
726 uint16_t word;
727
728 if (panel_size == 2) { /* DS40001874F */
729 word = panel[0] | panel[1] << 8;
730 pic16n_load_pc_address(address);
731 pic16n_program_data_command(word, 0, PIC16N_TPINT_Q);
732 } else {
733 for (uint32_t i = 0; i < panel_size; i += 2) {
734 word = panel[i] | panel[i + 1] << 8;
735 pic16n_load_data_for_nvm(word, 1);
736 }
737 pic16n_load_pc_address(address);
738 pic16n_begin_internally_timed_programming(PIC16N_TPINT_CODE);
739 }
740 }
741
742 /*****************************************************************************
743 *
744 * Program Data/EEPROM
745 *
746 *****************************************************************************/
747
748 /*
749 * WRITE Data/EEPROM WORD
750 */
751 static inline
752 void
pic16n_write_data_memory(uint32_t address,uint16_t word)753 pic16n_write_data_memory(uint32_t address, uint16_t word)
754 {
755 pic16n_load_pc_address(address);
756
757 if (pic16n_map[pic16n_index].datasheet == DS40001874F) {
758 pic16n_program_data_command(word, 0, PIC16N_TPDFM_Q);
759 } else {
760 pic16n_load_data_for_nvm(word, 0);
761 pic16n_begin_internally_timed_programming(PIC16N_TPINT_CONFIG);
762 }
763 }
764
765 /*****************************************************************************
766 *
767 * Program UserID/Config
768 *
769 *****************************************************************************/
770
771 /*
772 * WRITE USERID/CONFIG WORD
773 *
774 * RETURN WORD
775 */
776 static inline uint16_t
pic16n_write_config_word(uint16_t word)777 pic16n_write_config_word(uint16_t word)
778 {
779 if (pic16n_map[pic16n_index].datasheet == DS40001874F) {
780 pic16n_program_data_command(word, 0, PIC16N_TPINT_Q);
781 } else {
782 pic16n_load_data_for_nvm(word, 0);
783 pic16n_begin_internally_timed_programming(PIC16N_TPINT_CONFIG);
784 }
785
786 return pic16n_read_data_from_nvm(1);
787 }
788
789 /*
790 * WRITE CONFIG
791 *
792 * RETURN 0 ON ERROR ELSE PROGRAM COUNT
793 */
794 uint32_t
pic16n_write_config(void)795 pic16n_write_config(void)
796 {
797 uint16_t wdata, vdata;
798
799 pic16n_program_verify();
800
801 pic16n_load_pc_address(PIC16N_USERID_ADDR);
802 for (uint32_t i = 0; i < pic16n_map[pic16n_index].idsize; i += 2) {
803 wdata = pic16n_conf.userid[i] | pic16n_conf.userid[i + 1] << 8;
804 vdata = pic16n_write_config_word(wdata);
805 if (vdata != wdata) {
806 printf("%s: error: USERID%d write failed: read [%04X] expected [%04X]\n",
807 __func__, i, vdata, wdata);
808 pic16n_standby();
809 return 0;
810 }
811 }
812
813 pic16n_load_pc_address(PIC16N_CONFIG_ADDR);
814 for (uint32_t i = 0; i < pic16n_map[pic16n_index].config; i += 2) {
815 wdata = pic16n_conf.config[i] | pic16n_conf.config[i + 1] << 8;
816 if (pic16n_map[pic16n_index].masks && (p.config & CONFIGSET))
817 wdata |= ~(pic16n_map[pic16n_index].masks[i] |
818 pic16n_map[pic16n_index].masks[i + 1] << 8);
819 vdata = pic16n_write_config_word(wdata);
820 if (pic16n_map[pic16n_index].masks && (p.config & CONFIGVER)) {
821 uint16_t mask = pic16n_map[pic16n_index].masks[i] |
822 pic16n_map[pic16n_index].masks[i + 1] << 8;
823 wdata &= mask;
824 vdata &= mask;
825 }
826 if (vdata != wdata) {
827 printf("%s: error: CONFIG%d write failed: read [%04X] expected [%04X]\n",
828 __func__, i + 1, vdata, wdata);
829 pic16n_standby();
830 return 0;
831 }
832 }
833
834 pic16n_standby();
835
836 return pic16n_map[pic16n_index].idsize + pic16n_map[pic16n_index].config;
837 }
838
839 /*****************************************************************************
840 *
841 * Programming
842 *
843 *****************************************************************************/
844
845 /*
846 * DETERMINE MEMORY REGION: CODE, ID, CONFIG or DATA
847 *
848 * RETURN PIC_REGIONCODE:
849 * 0 .. FLASH SIZE - 1
850 *
851 * RETURN PIC_REGIONID:
852 * 0x200000 .. 0x200007
853 *
854 * RETURN PIC_REGIONCONFIG:
855 * 0x300000 .. 0x30000B
856 *
857 * RETURN PIC_REGIONDATA:
858 * 0x310000 .. 0x31XXXX
859 */
860 uint16_t
pic16n_getregion(uint32_t address)861 pic16n_getregion(uint32_t address)
862 {
863 /* CODE */
864 if (address < (pic16n_map[pic16n_index].flash << 1)) {
865 return PIC_REGIONCODE;
866 }
867 /* ID */
868 if (address >= PIC16N_USERID_ADDR && address < (PIC16N_USERID_ADDR +
869 pic16n_map[pic16n_index].idsize)) {
870 return PIC_REGIONID;
871 }
872 /* CONFIG */
873 if (address >= PIC16N_CONFIG_ADDR && address < (PIC16N_CONFIG_ADDR +
874 pic16n_map[pic16n_index].config)) {
875 return PIC_REGIONCONFIG;
876 }
877 /* DATA EEPROM */
878 if (pic16n_map[pic16n_index].eeprom) {
879 if (address >= PIC16N_EEPROM_ADDR && address < (PIC16N_EEPROM_ADDR +
880 pic16n_map[pic16n_index].eeprom))
881 return PIC_REGIONDATA;
882 }
883 if (p.f) fprintf(p.f, "%s: warning: address unsupported [%04X]\n",
884 __func__, address);
885 return PIC_REGIONNOTSUP;
886 }
887
888 /*
889 * INIT REGION FOR WRITING (ID & CONFIG DELAYED)
890 *
891 * RETURN REGION IF WRITING SUPPORTED
892 */
893 static inline uint32_t
pic16n_init_writeregion(uint32_t region)894 pic16n_init_writeregion(uint32_t region)
895 {
896 switch (region) {
897 case PIC_REGIONCODE:
898 pic16n_load_pc_address(0); /* Reset latch address */
899 pic_write_panel(PIC_PANEL_BEGIN, region, pic16n_map[pic16n_index].latches);
900 /* Follow through */
901 case PIC_REGIONID:
902 case PIC_REGIONCONFIG:
903 case PIC_REGIONDATA:
904 return region;
905 }
906 if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
907 __func__, region);
908 return PIC_REGIONNOTSUP;
909 }
910
911 /*
912 * WRITE REGION (CACHE ID & CONFIG)
913 */
914 static inline void
pic16n_writeregion(uint32_t address,uint32_t region,uint16_t data)915 pic16n_writeregion(uint32_t address, uint32_t region, uint16_t data)
916 {
917 switch (region) {
918 case PIC_REGIONCODE:
919 pic_write_panel(PIC_PANEL_UPDATE, address, data);
920 return;
921 case PIC_REGIONID:
922 pic16n_conf.userid[address - PIC16N_USERID_ADDR] = data;
923 return;
924 case PIC_REGIONCONFIG:
925 pic16n_conf.config[address - PIC16N_CONFIG_ADDR] = data;
926 return;
927 case PIC_REGIONDATA:
928 pic16n_write_data_memory(address, data);
929 return;
930 }
931 }
932
933 /*
934 * INIT REGION FOR VERIFY
935 *
936 * RETURN REGION IF VERIFY SUPPORTED
937 */
938 static inline uint32_t
pic16n_init_verifyregion(uint32_t region)939 pic16n_init_verifyregion(uint32_t region)
940 {
941 if (region == PIC_REGIONNOTSUP) {
942 if (p.f) fprintf(p.f, "%s: warning: region unsupported [%d]\n",
943 __func__, region);
944 }
945
946 return region;
947 }
948
949 /*
950 * GET VERIFY DATA FOR REGION
951 */
952 static uint16_t
pic16n_verifyregion(uint32_t address,uint32_t region,uint16_t index,uint8_t mode)953 pic16n_verifyregion(uint32_t address, uint32_t region, uint16_t index, uint8_t mode)
954 {
955 if (index == 0)
956 pic16n_load_pc_address(address);
957
958 if (mode == 0)
959 return pic16n_read_data_from_nvm(1) & 0xFF; /* EEPROM BYTE */
960
961 if (mode == 1) { /* CODE/USERID/CONFIG BYTE */
962 if (address & 1)
963 return pic16n_read_data_from_nvm(1) >> 8; /* HIGH BYTE */
964 else
965 return pic16n_read_data_from_nvm(1) & 0xFF; /* LOW BYTE */
966 }
967 return pic16n_read_data_from_nvm(1); /* CODE/USERID/CONFIG WORD */
968 }
969
970 /*****************************************************************************
971 *
972 * Program & verify
973 *
974 *****************************************************************************/
975
976 /*
977 * BEGIN PROGRAMMING
978 */
979 void
pic16n_program_begin(void)980 pic16n_program_begin(void)
981 {
982 pic16n_program_verify();
983
984 memset(pic16n_conf.userid, -1, sizeof(uint8_t) * pic16n_map[pic16n_index].idsize);
985 memset(pic16n_conf.config, -1, sizeof(uint8_t) * PIC16N_CONFIG_MAX);
986 }
987
988 /*
989 * PROGRAM DATA
990 */
991 uint32_t
pic16n_program_data(uint32_t current_region,pic_data * pdata)992 pic16n_program_data(uint32_t current_region, pic_data *pdata)
993 {
994 uint32_t address, new_region;
995
996 for (uint32_t i = 0; i < pdata->nbytes; ++i) {
997 address = pdata->address + i;
998 new_region = pic16n_getregion(address);
999 if (new_region != current_region) {
1000 pic_write_panel(PIC_PANEL_END, PIC_VOID, PIC_VOID);
1001 current_region = pic16n_init_writeregion(new_region);
1002 }
1003 if (current_region == PIC_REGIONNOTSUP)
1004 continue;
1005 pic16n_writeregion(address, current_region, pdata->bytes[i]);
1006 }
1007 return current_region;
1008 }
1009
1010 /*
1011 * END PROGRAMMING
1012 */
1013 void
pic16n_program_end(int config)1014 pic16n_program_end(int config)
1015 {
1016 pic_write_panel(PIC_PANEL_END, PIC_VOID, PIC_VOID);
1017 pic16n_standby();
1018 if (config)
1019 pic16n_write_config();
1020 }
1021
1022 /*
1023 * VERIFY DATA
1024 */
1025 uint32_t
pic16n_verify_data(uint32_t current_region,pic_data * pdata,uint32_t * fail)1026 pic16n_verify_data(uint32_t current_region, pic_data *pdata, uint32_t *fail)
1027 {
1028 uint32_t address, new_region;
1029 uint16_t wdata, vdata;
1030
1031 for (uint32_t i = 0; i < pdata->nbytes;) {
1032 address = pdata->address + i;
1033 new_region = pic16n_getregion(address);
1034 if (new_region != current_region)
1035 current_region = pic16n_init_verifyregion(new_region);
1036 if (current_region == PIC_REGIONNOTSUP) {
1037 i += 1;
1038 }
1039 else if (current_region == PIC_REGIONDATA) {
1040 wdata = pdata->bytes[i];
1041 vdata = pic16n_verifyregion(address, current_region, i, 0);
1042 if (vdata != wdata) {
1043 if (p.f) printf("%s: error: read [%02X] expected [%02X] at [%06X]\n",
1044 __func__, vdata, wdata, address);
1045 pdata->bytes[i] = vdata;
1046 (*fail) += 1;
1047 }
1048 i += 1;
1049 }
1050 else if ((pdata->nbytes - i) == 1) { /* BYTE */
1051 wdata = pdata->bytes[i];
1052 vdata = pic16n_verifyregion(address, current_region, i, 1);
1053 if (current_region == PIC_REGIONCONFIG) {
1054 if (pic16n_map[pic16n_index].masks && (p.config & CONFIGVER)) {
1055 uint8_t a = address - PIC16N_CONFIG_ADDR;
1056 wdata &= pic16n_map[pic16n_index].masks[a];
1057 vdata &= pic16n_map[pic16n_index].masks[a];
1058 }
1059 }
1060 if (vdata != wdata) {
1061 if (p.f) printf("%s: error: read [%02X] expected [%02X] at [%06X]\n",
1062 __func__, vdata, wdata, address);
1063 pdata->bytes[i] = vdata;
1064 (*fail) += 1;
1065 }
1066 i += 1;
1067 }
1068 else { /* WORD */
1069 wdata = pdata->bytes[i] | pdata->bytes[i + 1] << 8;
1070 vdata = pic16n_verifyregion(address, current_region, i, 2);
1071 if (current_region == PIC_REGIONCONFIG) {
1072 if (pic16n_map[pic16n_index].masks && (p.config & CONFIGVER)) {
1073 uint8_t a = address - PIC16N_CONFIG_ADDR;
1074 if (a < PIC16N_CONFIG_MAX) {
1075 uint16_t mask = pic16n_map[pic16n_index].masks[a] |
1076 pic16n_map[pic16n_index].masks[a + 1] << 8;
1077 wdata &= mask;
1078 vdata &= mask;
1079 } else {
1080 if (p.f) fprintf(p.f, "%s: warning: config address invalid [%06X]\n",
1081 __func__, address);
1082 }
1083 }
1084 }
1085 if (vdata != wdata) {
1086 if (p.f) printf("%s: error: read [%04X] expected [%04X] at [%06X]\n",
1087 __func__, vdata, wdata, address);
1088 pdata->bytes[i] = vdata;
1089 pdata->bytes[i + 1] = vdata >> 8;
1090 (*fail) += 2;
1091 }
1092 i += 2;
1093 }
1094 }
1095 return current_region;
1096 }
1097
1098 /*
1099 * VIEW DATA
1100 */
1101 void
pic16n_view_data(pic_data * pdata)1102 pic16n_view_data(pic_data *pdata)
1103 {
1104 printf("[%06X] ", pdata->address);
1105 for (uint32_t i = 0; i < pdata->nbytes; ++i)
1106 printf("%02X ", pdata->bytes[i]);
1107 putchar('\n');
1108 }
1109
1110 /*****************************************************************************
1111 *
1112 * Diagnostic functions
1113 *
1114 *****************************************************************************/
1115
1116 /*
1117 * DUMP DEVICE ID DETAILS
1118 */
1119 void
pic16n_dumpdeviceid(void)1120 pic16n_dumpdeviceid(void)
1121 {
1122 uint32_t i, j;
1123 uint16_t word;
1124
1125 printf("[000000] [PROGRAM] %04X WORDS (%04X ROWS OF %04X WORDS)\n",
1126 pic16n_map[pic16n_index].flash,
1127 2 * pic16n_map[pic16n_index].flash / pic16n_map[pic16n_index].latches,
1128 pic16n_map[pic16n_index].latches / 2);
1129
1130 if (pic16n_map[pic16n_index].idsize <= 16) {
1131 for (i = j = 0; i < pic16n_map[pic16n_index].idsize; i += 2, ++j) {
1132 word = pic16n_conf.userid[i] | pic16n_conf.userid[i + 1] << 8;
1133 printf("[%06X] [USERID%d] %04X\n", PIC16N_USERID_ADDR + i, j, word);
1134 }
1135 } else for (i = 0; i < pic16n_map[pic16n_index].idsize; i += 16) {
1136 printf("[%04X] [USERID%02X] ", PIC16N_USERID_ADDR + i, i / 2);
1137 for (j = 0; j < 16; j += 2) {
1138 word = pic16n_conf.userid[i + j] | pic16n_conf.userid[i + j + 1] << 8;
1139 if (j != 14)
1140 printf("%04X ", word);
1141 else
1142 printf("%04X\n", word);
1143 }
1144 }
1145
1146 pic16n_dumpconfig(PIC_BRIEF, 0);
1147
1148 if (pic16n_map[pic16n_index].eeprom) {
1149 printf("[%06X] [DATA] %04X BYTES\n",
1150 PIC16N_EEPROM_ADDR, pic16n_map[pic16n_index].eeprom);
1151 }
1152
1153 /* Device information area */
1154 if (pic16n_map[pic16n_index].devinfo) {
1155 for (uint32_t i = 0; i < pic16n_map[pic16n_index].devinfo; i += 8) {
1156 printf("[%04X] [DEVINF%02X] ", PIC16N_DEVINFO_ADDR + 2 * i, 2 * i);
1157 uint32_t j;
1158 for (j = 0; j < 7; ++j)
1159 printf("%04X ", pic16n_conf.devinfo[i + j]);
1160 printf("%04X\n", pic16n_conf.devinfo[i + j]);
1161 }
1162 }
1163
1164 /* Device configuration information */
1165 if (pic16n_map[pic16n_index].devconf) {
1166 printf("[%04X] [ERASE] %04X\n", PIC16N_ERASE, pic16n_conf.devconf[0]);
1167 printf("[%04X] [LATCHES] %04X\n", PIC16N_LATCHES, pic16n_conf.devconf[1]);
1168 printf("[%04X] [ROWS] %04X\n", PIC16N_ROWS, pic16n_conf.devconf[2]);
1169 printf("[%04X] [EEPROM] %04X\n", PIC16N_EEPROM, pic16n_conf.devconf[3]);
1170 printf("[%04X] [PINS] %04X\n", PIC16N_PINS, pic16n_conf.devconf[4]);
1171 }
1172
1173 printf("[3FFFFC] [REVISION] %04X MAJ:%02X MIN:%02X\n",
1174 pic16n_conf.revisionid,
1175 (pic16n_conf.revisionid >> PIC16N_MAJOR_SHIFT) & PIC16N_REV_MASK,
1176 pic16n_conf.revisionid & PIC16N_REV_MASK);
1177 printf("[3FFFFE] [DEVICEID] %04X %s\n", pic16n_conf.deviceid,
1178 pic16n_map[pic16n_index].devicename);
1179 }
1180
1181 /*
1182 * DUMP CONFIG WORD DETAILS FOR DEVICE
1183 */
1184 void
pic16n_dumpconfig(uint32_t mode,uint32_t partition)1185 pic16n_dumpconfig(uint32_t mode, uint32_t partition)
1186 {
1187 for (uint32_t i = 0; i < pic16n_map[pic16n_index].config; i += 2) {
1188 printf("[%06X] [CONFIG%d] %04X\n",
1189 PIC16N_CONFIG_ADDR + i, i / 2 + 1,
1190 (pic16n_conf.config[i + 1] << 8) | pic16n_conf.config[i]);
1191 }
1192 #ifdef VERBOSE
1193 if (mode == PIC_VERBOSE) switch (pic16n_map[pic16n_index].datasheet) {
1194 default:break;
1195 }
1196 #endif
1197 }
1198
1199 /*
1200 * DUMP HEX FLASH WORDS
1201 */
1202 void
pic16n_dumphexcode(uint32_t address,uint32_t size,uint32_t * data)1203 pic16n_dumphexcode(uint32_t address, uint32_t size, uint32_t *data)
1204 {
1205 uint32_t i, j, nlines = 0;
1206
1207 for (i = 0; i < size; address += 16, i += 8) {
1208 if (pic_mtcode(PIC16N_WORD_MASK, 8, &data[i]))
1209 continue;
1210 printf("[%06X] ", address);
1211 for (j = 0; j < 8; ++j)
1212 printf("%04X ", data[i + j] & PIC16N_WORD_MASK);
1213 for (j = 0; j < 8; ++j) {
1214 putchar(PIC_CHAR(0xFF & data[i + j]));
1215 putchar(PIC_CHAR(0xFF & (data[i + j] >> 8)));
1216 }
1217 putchar('\n');
1218 nlines++;
1219 }
1220 if (!nlines)
1221 printf("%s: information: flash empty\n", __func__);
1222 }
1223
1224 /*
1225 * DUMP INHX32 FLASH WORDS
1226 */
1227 void
pic16n_dumpinhxcode(uint32_t address,uint32_t size,uint32_t * data)1228 pic16n_dumpinhxcode(uint32_t address, uint32_t size, uint32_t *data)
1229 {
1230 uint32_t i, j;
1231
1232 /* 16-bit: Extended address */
1233 pic_dumpaddr(address, 1);
1234
1235 for (i = 0; i < size; address += 16, i += 8) {
1236 if (pic_mtcode(PIC16N_WORD_MASK, 8, &data[i]))
1237 continue;
1238 /* 16-bit: Extended address */
1239 pic_dumpaddr(address, 0);
1240
1241 uint8_t cc, hb, lb;
1242 hb = address >> 8;
1243 lb = address;
1244 printf(":%02X%02X%02X00", 16, hb, lb);
1245 cc = 16 + hb + lb + 0x00;
1246 for (j = 0; j < 8; ++j) {
1247 lb = data[i + j];
1248 hb = data[i + j] >> 8;
1249 printf("%02X%02X", lb, hb);
1250 cc = cc + lb + hb;
1251 }
1252 printf("%02X\n", (0x0100 - cc) & 0xFF);
1253 }
1254 }
1255
1256 /*
1257 * DUMP HEX DATA EEPROM BYTES
1258 */
1259 void
pic16n_dumphexdata(uint32_t address,uint32_t size,uint16_t * data)1260 pic16n_dumphexdata(uint32_t address, uint32_t size, uint16_t *data)
1261 {
1262 uint32_t i, j, nlines = 0;
1263
1264 for (i = 0; i < size; address += 16, i += 16) {
1265 if (pic_mtdata(0xFF, 16, &data[i]))
1266 continue;
1267 printf("[%06X] ", address);
1268 for (j = 0; j < 16; ++j)
1269 printf("%02X ", data[i + j]);
1270 for (j = 0; j < 16; ++j)
1271 putchar(PIC_CHAR(0xFF & data[i + j]));
1272 putchar('\n');
1273 nlines++;
1274 }
1275 if (!nlines)
1276 printf("%s: information: data empty\n", __func__);
1277 }
1278
1279 /*
1280 * DUMP INHX32 DATA EEPROM BYTES
1281 */
1282 void
pic16n_dumpinhxdata(uint32_t address,uint32_t size,uint16_t * data)1283 pic16n_dumpinhxdata(uint32_t address, uint32_t size, uint16_t *data)
1284 {
1285 uint32_t i, j;
1286
1287 /* PIC18: Extended address = 0x0031 (EEPROM: 0x310000) */
1288 pic_dumpaddr(PIC16N_EEPROM_ADDR, 1);
1289
1290 for (i = 0; i < size; address += 16, i += 16) {
1291 if (pic_mtdata(0xFF, 16, &data[i]))
1292 continue;
1293
1294 uint8_t cc, hb, lb;
1295 hb = address >> 8;
1296 lb = address;
1297 printf(":%02X%02X%02X00", 16, hb, lb);
1298 cc = 16 + hb + lb + 0x00;
1299 for (j = 0; j < 16; ++j) {
1300 lb = data[i + j];
1301 printf("%02X", lb);
1302 cc = cc + lb;
1303 }
1304 printf("%02X\n", (0x0100 - cc) & 0xFF);
1305 }
1306 }
1307
1308 /*
1309 * DUMP INHX32 DEVICE CONFIGURATION
1310 */
1311 void
pic16n_dumpdevice(void)1312 pic16n_dumpdevice(void)
1313 {
1314 uint32_t i;
1315
1316 /* PIC18: Extended address = 0x0020 (USERID: 0x200000) */
1317 pic_dumpaddr(PIC16N_USERID_ADDR, 1);
1318
1319 for (i = 0; i < pic16n_map[pic16n_index].idsize; i += 2)
1320 pic_dumpword16(i / 2, pic16n_conf.userid[i] | pic16n_conf.userid[i + 1] << 8);
1321
1322 /* PIC18: Extended address = 0x0030 (CONFIG: 0x300000) */
1323 pic_dumpaddr(PIC16N_CONFIG_ADDR, 1);
1324
1325 for (i = 0; i < pic16n_map[pic16n_index].config; i += 2)
1326 pic_dumpword16(i / 2, pic16n_conf.config[i] | pic16n_conf.config[i + 1] << 8);
1327 }
1328