3
This is Picprog, Microchip PIC programmer software for the serial port device.
4
Copyright © 1997,2002,2003,2004,2006,2007,2008,2010 Jaakko Hyvätti
6
This program is free software: you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation, either version 3 of the License, or
9
(at your option) any later version.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program. If not, see http://www.gnu.org/licenses/ .
19
The author may be contacted at:
21
Email: Jaakko.Hyvatti@iki.fi
22
URL: http://www.iki.fi/hyvatti/
23
Phone: +358 40 5011222
25
Please send any suggestions, bug reports, success stories etc. to the
26
Email address above. Include word 'picprog' in the subject line to
27
make sure your email passes my spam filtering.
40
#include <sys/ioctl.h>
54
#define O_NONBLOCK O_NDELAY
57
unsigned int picport::tsc_1000ns = 0;
59
// Data bitrate delay, ns.
60
// Cable delay is tested and this value adjusted when port is opened.
61
int picport::cable_delay = 0;
63
// Set this to -1 if you want to use nanosleep when running as root.
64
// This only works with 2.4 kernels, 2.6 series kernels no more work.
65
int picport::use_nanosleep = 0;
68
static bool disable_interrupts = 1;
71
picport::set_clock_data (int rts, int dtr)
73
if (hardware == k8048) {
77
// Before first call to set_clock_data, read the modem status like this:
78
// ioctl (fd, TIOCMGET, &modembits);
80
modembits |= TIOCM_RTS;
82
modembits &= ~TIOCM_RTS;
84
modembits |= TIOCM_DTR;
86
modembits &= ~TIOCM_DTR;
87
if (0 > ioctl (fd, TIOCMSET, &modembits)) {
89
tcsetattr (fd, TCSANOW, &saved);
90
cerr << "Unable to set RTS/DTR on tty " << portname << ":" << strerror (e) << endl;
96
picport::set_vpp (int vpp)
98
if (hardware == k8048)
100
if (0 > ioctl (fd, vpp ? TIOCSBRK : TIOCCBRK, 0)) {
103
ioctl (fd, TIOCCBRK, 0);
104
tcsetattr (fd, TCSANOW, &saved);
105
cerr << "Unable to " << (vpp ? "start" : "stop") << " break on tty "
106
<< portname << ":" << strerror (e) << endl;
111
picport::picport (const char *tty, bool nordtsc, bool slow, bool reboot,
113
: addr (0), debug_on (0), hardware (h)
115
for (int i = 0; i < 16; ++i)
117
portname = new char [strlen (tty) + 1];
118
strcpy (portname, tty);
120
if (0 > (fd = open (tty, O_RDWR|O_NOCTTY|O_NONBLOCK))) {
122
cerr << "Unable to open tty " << tty << ":" << strerror (e) << endl;
125
tcgetattr (fd, &saved);
127
termstate.c_iflag = IGNBRK | IGNPAR;
128
termstate.c_oflag = 0;
129
termstate.c_cflag = B9600 | CS8 | CREAD | CLOCAL;
130
termstate.c_lflag = 0;
131
tcsetattr (fd, TCSANOW, &termstate);
133
// Initialize lines for programming
135
// RTS/DTR low, sleep and then TxD high (program voltage)
137
ioctl (fd, TIOCCBRK, 0);
138
// Before first call to set_clock_data, read the modem status.
139
ioctl (fd, TIOCMGET, &modembits);
140
modembits &= ~(TIOCM_RTS | TIOCM_DTR);
141
ioctl (fd, TIOCMSET, &modembits);
143
// Check the CTS. If it is up, even when we just lowered DTR,
144
// we probably are not talking to a JDM type programmer.
146
ioctl (fd, TIOCMGET, &i);
148
tcsetattr (fd, TCSANOW, &saved);
149
cerr << tty << ":CTS is high, probably we are not connected to a programmer but a modem or terminal." << endl;
153
struct sched_param scp;
154
scp.sched_priority = sched_get_priority_min (SCHED_FIFO);
155
// sched_get_priority_max()
156
// scp.sched_priority = 50;
157
cerr << "Trying realtime priority " << scp.sched_priority << endl;
158
if (sched_setscheduler (0, SCHED_FIFO, &scp)) {
159
cerr << "Cannot use real time scheduling: " << strerror(errno) << endl;
160
// Not root. Cannot use realtime scheduling.
164
disable_interrupts = 0;
167
// When computing the delay loops, we do not want the cpu's to change.
168
// Pick the first cpu in the current allowed set.
173
if (sched_getaffinity(0, sizeof (cur_mask), &cur_mask) < 0) {
174
tcsetattr (fd, TCSANOW, &saved);
175
cerr << "Getting affinity functions do not work." << endl;
178
for (int cpuno = 0; cpuno < CPU_SETSIZE; ++cpuno)
179
if (CPU_ISSET (cpuno, &cur_mask)) {
180
CPU_SET (cpuno, &new_mask);
181
sched_getaffinity (0, sizeof (new_mask), &new_mask);
182
// We want to print informative line only if we really
183
// have multiple cpu's.
184
for (int cpuno1 = cpuno+1; cpuno1 < CPU_SETSIZE; ++cpuno1)
185
if (CPU_ISSET (cpuno1, &cur_mask)) {
186
cerr << "Bound to CPU " << cpuno << endl;
190
#endif // CPU_SETSIZE
193
if (!nordtsc && !use_nanosleep && !tsc_1000ns) {
194
// Read /proc/cpuinfo for clock speed, or if that fails, try our
196
ifstream cpui ("/proc/cpuinfo");
198
unsigned int mhz = 1; // 1MHz is just a flag that tsc was found
203
// Read just the integer part. No need for the rest.
205
// Update this when we have 100 GHz CPUs.
206
if (tmp >= 4 && tmp <= 100000)
209
if ("tsc" == w && mhz) {
210
// tsc capability found. Use it.
216
// If the /proc fs did not contain clock speed but indicated
217
// tsc capability, test the approximate clock speed.
218
if (1 == tsc_1000ns) {
219
// Loop the test 20 times, and select the smallest count.
220
for (int recount = 0; recount < 20; ++recount) {
221
struct timeval tv1, tv2;
222
unsigned long a1, d1, a2, d2;
224
// Wait for when a microsecond changes
225
gettimeofday (&tv2, 0);
227
gettimeofday (&tv1, 0);
228
} while (tv2.tv_usec == tv1.tv_usec);
229
asm volatile("rdtsc":"=a" (a1), "=d" (d1));
231
if (tv1.tv_usec >= 1000000) {
232
tv1.tv_usec -= 1000000;
236
gettimeofday (&tv2, 0);
237
} while (tv2.tv_sec < tv1.tv_sec
238
|| (tv2.tv_sec == tv1.tv_sec && tv2.tv_usec < tv1.tv_usec));
239
asm volatile("rdtsc":"=a" (a2), "=d" (d2));
243
a2 &= 0xffffffff; // for x86_64
248
if (tsc_1000ns <= 1 || tsc_1000ns > a2)
251
if (tsc_1000ns <= 1) {
252
tcsetattr (fd, TCSANOW, &saved);
253
cerr << "Unable to determine CPU clock speed for delay loops." << endl;
257
if (tsc_1000ns >= 1) {
258
cout << "CPU clock speed: " << tsc_1000ns << " MHz" << endl;
263
if (tsc_1000ns > 1 && disable_interrupts)
264
cerr << "Disable interrupts during delays." << endl;
267
// Power off any microcontroller that may be running a program.
268
cerr << "Power off." << endl;
269
set_clock_data (1, 1);
271
usleep (500000); // 0.5s delay should discharge Vdd.
274
// /MCLR must go down for a while first
278
set_clock_data (0, 0);
283
// Detect delays that are needed for cable lenght
284
bool successful_echo = false;
285
for (int i = 1; i <= 100; ++i) {
286
int data_out = i & 1;
287
// toggle data, keep clock off / power on
289
modembits |= TIOCM_DTR;
291
modembits &= ~TIOCM_DTR;
292
ioctl (fd, TIOCMSET, &modembits);
295
ioctl (fd, TIOCMGET, &data_in);
296
data_in = 0 != (data_in & TIOCM_CTS);
298
successful_echo = data_out == data_in;
299
if (!successful_echo)
300
cable_delay += 100; // Another 100 ns added for cable length
301
ioctl (fd, TIOCMGET, &data_in);
302
data_in = 0 != (data_in & TIOCM_CTS);
303
if (data_out != data_in) {
304
ioctl (fd, TIOCCBRK, 0);
305
tcsetattr (fd, TCSANOW, &saved);
306
cerr << "No JDM compatible hardware detected." << endl;
310
set_clock_data (0, 0);
312
if (!successful_echo) {
313
ioctl (fd, TIOCCBRK, 0);
314
tcsetattr (fd, TCSANOW, &saved);
315
cerr << "Cable too long." << endl;
319
cable_delay += 100; // Another 100 ns added just for safety
320
if (slow && cable_delay < 10000)
322
if (1 == use_nanosleep)
323
cerr << "Using " << cable_delay << " ns delays with real time priority." << endl;
324
else if (tsc_1000ns > 1)
325
cerr << "Using " << cable_delay << " ns delays." << endl;
326
else if (cable_delay > 1000)
327
cerr << "Using " << ((cable_delay + 999) / 1000) << " µs delays." << endl;
329
cerr << "Using >1 µs delays. --rdtsc may work for faster timings." << endl;
336
tcsetattr (fd, TCSANOW, &saved);
341
void picport::reset (unsigned long reset_address)
343
set_clock_data (0, 0);
344
usleep (100); // Make sure we have the power there.
349
addr = reset_address;
352
void picport::delay (long ns)
354
if (1 == use_nanosleep) {
355
timespec ts = {ns / 1000000000, ns % 1000000000}, ts2;
356
while (nanosleep (&ts, &ts2) && EINTR == errno)
362
if (tsc_1000ns > 1) {
363
unsigned long a1, d1, a2, d2;
364
if (ns <= 10000 && disable_interrupts)
365
asm volatile("pushf; cli");
366
asm volatile("rdtsc":"=a" (a1), "=d" (d1));
369
// This is not as accurate but does not overflow
370
a2 = 0xffffffff & (a1 + 1 + (ns+999)/1000*tsc_1000ns);
372
a2 = 0xffffffff & (a1 + 1 + (ns*tsc_1000ns + 999) / 1000);
376
asm volatile("rdtsc":"=a" (a1), "=d" (d1));
377
} while (d1 < d2 || (d1 == d2 && a1 < a2));
378
if (ns <= 10000 && disable_interrupts)
379
asm volatile("popf");
382
// Fall back to gettimeofday() if tsc is not available.
383
#endif // RDTSC_WORKS
385
// Delay loop that should take more than a microsecond to execute.
386
// Check the real time clock and break out if at least the specified
387
// number of microseconds has gone.
389
struct timeval tv1, tv2;
390
gettimeofday (&tv2, 0);
391
tv2.tv_usec += 1 + (ns + 999)/1000;
392
if (tv2.tv_usec >= 1000000) {
393
tv2.tv_usec -= 1000000;
397
gettimeofday (&tv1, 0);
398
} while (tv1.tv_sec < tv2.tv_sec
399
|| (tv1.tv_sec == tv2.tv_sec && tv1.tv_usec < tv2.tv_usec));
402
void picport::p_out (int b)
404
struct timeval tv1, tv2;
405
gettimeofday (&tv1, 0);
406
if (tsc_1000ns > 1 && disable_interrupts)
407
asm volatile("pushf; cli");
408
set_clock_data (1, b); // set data, clock up
410
set_clock_data (0, b); // clock down
411
if (tsc_1000ns > 1 && disable_interrupts)
412
asm volatile("popf");
413
gettimeofday (&tv2, 0);
415
// We may have spent a long time in an interrupt or in another task
416
// with clock down, so the pic may be pretty drained for power now.
417
// Recharge at least as long as we were without power.
418
long matching_delay = (tv2.tv_sec-tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec;
419
if (matching_delay > 10) // 10 µs should be enough to charge up
421
matching_delay *= 1000;
422
if (matching_delay < cable_delay)
423
matching_delay = cable_delay;
424
delay (matching_delay);
429
struct timeval tv1, tv2;
430
gettimeofday (&tv1, 0);
431
if (tsc_1000ns > 1 && disable_interrupts)
432
asm volatile("pushf; cli");
433
set_clock_data (1, 1); // clock up
435
set_clock_data (0, 1); // set data up, clock down
436
if (tsc_1000ns > 1 && disable_interrupts)
437
asm volatile("popf");
438
gettimeofday (&tv2, 0);
440
// We may have spent a long time in an interrupt or in another task
441
// with clock down, so the pic may be pretty drained for power now.
442
// Recharge at least as long as we were without power.
443
long matching_delay = (tv2.tv_sec-tv1.tv_sec) * 1000000 + tv2.tv_usec - tv1.tv_usec;
444
if (matching_delay > 10) // 10 µs should be enough to charge up
446
matching_delay *= 1000;
447
if (matching_delay < cable_delay)
448
matching_delay = cable_delay;
449
delay (matching_delay);
453
ioctl (fd, TIOCMGET, &i);
454
i = 0 != (i & TIOCM_CTS);
455
if (hardware == k8048)
460
int picport::command18 (enum commands18 comm, int data)
463
if (nop_prog == comm) {
464
// A programming command must leave the last bit clock pulse up
468
set_clock_data (1, 0); // clock up
469
delay (1000*1000); // P9 >1 ms programming time
470
set_clock_data (0, 0); // clock down
471
// P10 >5 µs high voltage discharge time
472
// Later models listed as > 100 µs
475
for (i = 0; i < 4; i++)
476
p_out ((shift >> i) & 1);
477
set_clock_data (0, 0); // set data down
481
shift = 0; // default return value
485
// Erase cycle has delay between command and data
486
usleep (10000); // P11 5 ms + P10 5 µs erase time
491
if (0x0e00 == (data & 0xff00))
492
W[0] = data & 0x00ff;
493
else if (0x6ef8 == data)
494
addr = (addr & 0x00ffff) | (W[0] << 16);
495
else if (0x6ef7 == data)
496
addr = (addr & 0xff00ff) | (W[0] << 8);
497
else if (0x6ef6 == data)
498
addr = (addr & 0xffff00) | W[0];
512
for (i = 0; i < 16; i++)
513
p_out ((data >> i) & 1);
514
set_clock_data (0, 0); // set data down
529
for (i = 0; i < 8; i++)
532
for (i = 0; i < 8; i++)
533
shift |= p_in () << i;
534
set_clock_data (0, 0); // set data down
541
int picport::command30 (enum commands30 comm, int data)
544
for (i = 0; i < 4; i++)
545
p_out ((shift >> i) & 1);
547
shift = 0; // default return value
552
if (0x200000 == (data & 0xff0000))
553
W[data & 15] = (data & 0x0ffff0) >> 4;
554
else if (0xEB0000 == (data & 0xfff87f))
555
W[(data >> 7) & 15] = 0;
556
else if (0xBA1830 == (data & 0xfff870)) {
558
++W[(data >> 7) & 15];
560
} else if (0xBA0830 == (data & 0xfff870)) {
562
++W[(data >> 7) & 15];
564
} else if (0x880190 == (data & 0xfffff0))
565
addr = (W[data & 15] << 16) & 0xff0000;
566
addr = (addr & 0xff0000) | W[6];
568
for (i = 0; i < 24; i++)
569
p_out ((data >> i) & 1);
573
for (i = 0; i < 8; i++)
575
for (i = 0; i < 16; i++)
576
shift |= p_in () << i;
578
set_clock_data (0, 0); // set data down
583
void picport::setaddress (unsigned long a)
585
if (0 != a && addr == a)
588
command18 (instr, 0x0e00 | ((a & 0xff0000) >> 16));
589
command18 (instr, 0x6ef8);
590
command18 (instr, 0x0e00 | ((a & 0x00ff00) >> 8));
591
command18 (instr, 0x6ef7);
592
command18 (instr, 0x0e00 | (a & 0x0000ff));
593
command18 (instr, 0x6ef6);
596
void picport::setaddress30 (unsigned long a)
598
if (0 != a && addr == a)
601
command30 (SIX, 0x200000 | ((a & 0xff0000) >> 12)); // MOV #, W0
602
command30 (SIX, 0x880190); // MOV W0, TBLPAG
603
command30 (SIX, 0x200006 | ((a & 0x00ffff) << 4)); // MOV #, W6
606
// -1 == error, no programmer present
608
int picport::command (enum commands comm, int data)
612
// first, send out the command, 6 bits
615
for (i = 0; i < 6; i++)
616
p_out ((shift >> i) & 1);
617
set_clock_data (0, 0); // set data down
619
shift = 0; // default return value
624
if (data != 0) { // 12f508 and 12f509
625
if (addr >= (unsigned long)(data))
638
for (i = 0; i < 14; i++)
639
shift |= p_in () << i;
641
set_clock_data (0, 0); // set data down
643
#ifdef CHECK_START_STOP
644
// Start and stop bits must be 1. Most of the old chips at least
645
// conform to this test, but apparently pic12f635 and some other
646
// later chips do not.
648
if (!tmp1 || !tmp2) {
649
cerr << portname << ":PIC programmer missing or chip fault" << endl;
654
if (data_from_data == comm) {
656
// Check that the leftover bits were valid, all 1's.
657
// This detects if the programmer is not connected to the port.
658
// Unfortunately later chips clear these bits, so we must
659
// accept both all 1's and all 0's.
661
if ((shift & 0x3f00) != 0x3f00
662
&& (shift & 0x3f00) != 0x0000) {
663
cerr << portname << ": read value "
664
<< hex << setfill('0') << setw(4) << shift << dec
665
<< ": PIC programmer or chip fault\n"
666
"Is code protection enabled? "
667
"Use --erase option to disable code protection." << endl;
683
for (i = 0; i < 14; i++)
684
p_out ((data >> i) & 1);
686
set_clock_data (0, 0); // set data down