1 --- /dev/null 2009-08-02 22:44:47.000000000 +0200
2 +++ serjtag.c 2009-08-02 21:56:45.000000000 +0200
5 + * avrdude - A Downloader/Uploader for AVR device programmers
6 + * Copyright (C) 2003-2004 Theodore A. Roth <troth@openavr.org>
8 + * This program is free software; you can redistribute it and/or modify
9 + * it under the terms of the GNU General Public License as published by
10 + * the Free Software Foundation; either version 2 of the License, or
11 + * (at your option) any later version.
13 + * This program is distributed in the hope that it will be useful,
14 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 + * GNU General Public License for more details.
18 + * You should have received a copy of the GNU General Public License
19 + * along with this program; if not, write to the Free Software
20 + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 +/* serjtag -- Serial Jtag Cable (using AVR) */
33 +#include <sys/time.h>
41 +#define SERJTAG_DEBUG 0
43 +extern char * progname;
44 +extern int do_cycles;
48 +static int serjtag_send(PROGRAMMER * pgm, char * buf, size_t len)
50 + return serial_send(&pgm->fd, (unsigned char *)buf, len);
54 +static int serjtag_recv(PROGRAMMER * pgm, char * buf, size_t len)
58 + rv = serial_recv(&pgm->fd, (unsigned char *)buf, len);
61 + "%s: serjtag_recv(): programmer is not responding\n",
69 +static int serjtag_drain(PROGRAMMER * pgm, int display)
71 + return serial_drain(&pgm->fd, display);
74 +static int serjtag_chip_erase(PROGRAMMER * pgm, AVRPART * p)
76 + unsigned char cmd[4];
77 + unsigned char res[4];
79 + if (p->op[AVR_OP_CHIP_ERASE] == NULL) {
80 + fprintf(stderr, "chip erase instruction not defined for part \"%s\"\n",
85 + memset(cmd, 0, sizeof(cmd));
87 + avr_set_bits(p->op[AVR_OP_CHIP_ERASE], cmd);
88 + pgm->cmd(pgm, cmd, res);
89 + usleep(p->chip_erase_delay);
90 + pgm->initialize(pgm, p);
95 +#if SERJTAG_DEBUG == 1
96 +static void serjtag_check(PROGRAMMER * pgm) {
100 +fprintf(stderr,"check response\n");
106 + serjtag_send(pgm, buf, i);
107 + serjtag_recv(pgm, buf, 1);
108 +fprintf(stderr,"\tCommonad = 0x%02x %c\n",buf[0],buf[0]);
109 + serjtag_recv(pgm, buf+1, 1);
110 +fprintf(stderr,"\tFlags = 0x%02x\n",buf[1]);
111 + serjtag_recv(pgm, buf+2, 1);
112 +fprintf(stderr,"\tBytes = 0x%02x\n",buf[2]);
114 + if (buf[1] & JTAG_BITS) bytes++;
116 + fprintf(stderr,"\t");
117 + for (i=0; i<bytes; i++) {
118 + serjtag_recv(pgm, buf+2+i, 1);
119 + fprintf(stderr,"%02x ",buf[2+i]);
121 + fprintf(stderr,"\n");
126 +static int serjtag_recv_j(PROGRAMMER * pgm, char * buf, size_t len, int verbose)
129 + serjtag_recv(pgm, buf, 3); /* header */
132 + fprintf(stderr,"recv_j(0) %c 0x%02x %d :",buf[0],buf[1],buf[2]);
136 + if (buf[1] & JTAG_BITS) {
140 + if (len >= bytes) {
141 + serjtag_recv(pgm, buf+3, bytes);
145 + serjtag_recv(pgm, buf+3, len);
146 + for (i=0; i< bytes - len; i++) {
147 + serjtag_recv(pgm, tmp, 1);
152 + fprintf(stderr,"recv_j %c 0x%02x %d :",buf[0],buf[1],buf[2]);
153 + for (i=0; i<bytes; i++) {
154 + fprintf(stderr,"%02x ",buf[3+i]&0xff);
156 + fprintf(stderr,"\n");
161 +static int delay_param = 3;
162 +static int use_delay = JTAG_USE_DELAY;
163 +static unsigned char saved_signature[3];
165 +static void serjtag_set_delay(PROGRAMMER * pgm) {
166 + use_delay = JTAG_USE_DELAY;
167 + if (pgm->bitclock == 0.0) { // using default
169 + } else if (pgm->bitclock >= 4.0) {
173 + delay_param = (int)((2.26/3.0) / pgm->bitclock);
174 + if (delay_param > 15) delay_param = 15;
176 + if ((verbose>=1) || SERJTAG_DEBUG) {
177 + fprintf(stderr," serjtag:delay %d (%s) ( bitclk %.3f )\n"
178 + ,delay_param, use_delay? "enabled":"disabled", pgm->bitclock);
183 + * issue the 'program enable' command to the AVR device
185 +static int serjtag_program_enable(PROGRAMMER * pgm, AVRPART * p)
189 + int retry_count = 0;
191 + serjtag_set_delay(pgm);
193 + serjtag_send(pgm, "j", 1); // enter jtag mode
194 + serjtag_recv(pgm, buf, 1);
195 + if (buf[0] != 'Y') {
198 +#if SERJTAG_DEBUG == 1
199 +fprintf(stderr," Enter jtag mode .. success \n");
204 + buf[i++] = 's'; /* Set Port */
205 + buf[i++] = 0; /* flags */
206 + buf[i++] = 1; /* bytes */
207 + buf[i++] = 0; /* TDI(MOSI) = 0, TMS(RESET) = 0, TCK(SCK) = 0 */
208 + serjtag_send(pgm, buf, i);
209 + usleep(5000); // 5ms
211 + buf[i++] = 's'; /* Set Port */
212 + buf[i++] = 0; /* flags */
213 + buf[i++] = 1; /* bytes */
214 + buf[i++] = JTAG_SET_TMS; /* TDI(MOSI) = 0, TMS(RESET) = 1, TCK(SCK) = 0 */
215 + serjtag_send(pgm, buf, i);
216 + usleep(5000); // 5ms
218 + buf[i++] = 's'; /* Set Port */
219 + buf[i++] = 0; /* flags */
220 + buf[i++] = 1; /* bytes */
221 + buf[i++] = delay_param & JTAG_SET_DELAY; /* TMS(RESET) = 0, set delay */
222 + serjtag_send(pgm, buf, i);
223 + usleep(5000); // 5ms
226 + buf[i++] = 'd'; /* PUT TDI Stream */
227 + buf[i++] = JTAG_RECIEVE | JTAG_USE_DELAY;
228 + buf[i++] = 0; /* bytes : set after*/
249 + buf[2] = i - 3; /* set bytes */
250 + buf[i++] = 'r'; /* Request Recieved Data */
251 + buf[i++] = 0; /* flags */
252 + buf[i++] = 0; /* bytes */
253 + serjtag_send(pgm, buf, i);
254 +#if SERJTAG_DEBUG == 1
255 + fprintf(stderr,"enabling program delay %d retry %d\n",delay_param,retry_count);
257 + serjtag_recv_j(pgm, buf, 3+4*4, SERJTAG_DEBUG?1:0);
259 + saved_signature[0] = buf[3+4*1 +3];
260 + saved_signature[1] = buf[3+4*2 +3];
261 + saved_signature[2] = buf[3+4*3 +3];
262 +#if SERJTAG_DEBUG == 1
263 + fprintf(stderr,"saved_signature %02x %02x %02x\n"
264 + , saved_signature[0]
265 + , saved_signature[1]
266 + , saved_signature[2]);
268 + if ((buf[3+2] == 0x53) && (saved_signature[0] == 0x1e)) // success
272 + if (retry_count < 5) {
279 +static int serjtag_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
281 + m->buf[0] = saved_signature[0];
282 + m->buf[1] = saved_signature[1];
283 + m->buf[2] = saved_signature[2];
288 + * initialize the AVR device and prepare it to accept commands
290 +static int serjtag_initialize(PROGRAMMER * pgm, AVRPART * p)
295 + /* Get the programmer identifier. Programmer returns exactly 7 chars
296 + _without_ the null.*/
298 + serjtag_send(pgm, "S", 1);
299 + serjtag_recv(pgm, id, 7);
302 + /* Get the HW and SW versions to see if the programmer is present. */
304 + serjtag_send(pgm, "V", 1);
305 + serjtag_recv(pgm, sw, 2);
308 + fprintf(stderr, "Found programmer: Id = \"%s\"; Revison = %s\n", id, sw);
310 + if (strncmp(id, "SERJTAG", 7) && strncmp(id, "USB910A", 7)
311 + && strncmp(id, "USB910A", 7) )
313 + fprintf(stderr, "\tserjtag protocol not supported.\n");
316 + return serjtag_program_enable(pgm, p);
319 +static void serjtag_disable(PROGRAMMER * pgm)
322 + serjtag_send(pgm, "V", 1);
323 + serjtag_recv(pgm, buf, 2);
329 +static void serjtag_enable(PROGRAMMER * pgm)
338 + * transmit an AVR device command and return the results; 'cmd' and
339 + * 'res' must point to at least a 4 byte data buffer
341 +static int serjtag_cmd(PROGRAMMER * pgm, unsigned char cmd[4],
342 + unsigned char res[4])
346 + /* FIXME: Insert version check here */
348 + buf[0] = 'd'; /* PUT TDI Stream */
349 + buf[1] = JTAG_RECIEVE | use_delay;
350 + buf[2] = 4; /* bytes */
355 + buf[7] = 'r'; /* Request Recieved Data */
359 + serjtag_send (pgm, buf, 10);
360 + serjtag_recv (pgm, buf, 7);
362 + res[0] = 0x00; /* Dummy value */
371 +static int serjtag_open(PROGRAMMER * pgm, char * port)
374 + * If baudrate was not specified use 19.200 Baud
376 + if(pgm->baudrate == 0) {
377 + pgm->baudrate = 19200;
380 + strcpy(pgm->port, port);
381 + serial_open(port, pgm->baudrate, &pgm->fd);
384 + * drain any extraneous input
386 + serjtag_drain (pgm, 0);
391 +static void serjtag_close(PROGRAMMER * pgm)
393 + serial_close(&pgm->fd);
398 +static void serjtag_display(PROGRAMMER * pgm, char * p)
403 +static int serjtag_paged_write_gen(PROGRAMMER * pgm, AVRPART * p,
404 + AVRMEM * m, int page_size, int n_bytes)
408 + for (i=0; i<n_bytes; i++) {
409 + report_progress(i, n_bytes, NULL);
411 + rc = avr_write_byte_default(pgm, p, m, i, m->buf[i]);
418 + * check to see if it is time to flush the page with a page
421 + if (((i % m->page_size) == m->page_size-1) || (i == n_bytes-1)) {
422 + rc = avr_write_page(pgm, p, m, i);
432 +#define SERJTAG_BUFFERD_WRITE
434 +#ifdef SERJTAG_BUFFERD_WRITE
435 +#define SERJTAG_BUF_SIZE 1024
436 +unsigned char *serjtag_buf;
437 +int serjtag_buf_len;
439 +static void serjtag_flush(PROGRAMMER * pgm) {
440 + if (!serjtag_buf || (serjtag_buf_len == 0)) return;
441 + serjtag_send(pgm, serjtag_buf, serjtag_buf_len);
442 + serjtag_buf_len = 0;
445 +static void serjtag_write(PROGRAMMER * pgm, unsigned char *buf, int size) {
446 + if (!serjtag_buf) {
447 + serjtag_buf = malloc(SERJTAG_BUF_SIZE);
448 + if (!serjtag_buf) {
449 + fprintf(stderr, "can't alloc memory\n");
453 + if (SERJTAG_BUF_SIZE < serjtag_buf_len + size) {
454 + serjtag_flush(pgm);
456 + memcpy(serjtag_buf + serjtag_buf_len, buf, size);
457 + serjtag_buf_len += size;
460 +static void serjtag_flush(PROGRAMMER * pgm) {
462 +static void serjtag_write(PROGRAMMER * pgm, unsigned char *buf, int size) {
463 + serjtag_send(pgm, buf, size);
467 +#define USE_INLINE_WRITE_PAGE
469 +static int serjtag_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
470 + int page_size, int n_bytes)
473 + int addr,addr_save,buf_pos,do_page_write;
477 + for (i=0; i<n_bytes; ) {
480 + buf[buf_pos++] = 'd'; /* PUT TDI Stream */
481 + buf[buf_pos++] = use_delay;
482 + buf[buf_pos++] = 0; /* bytes : set after */
484 + for (j=0; j<(JTAG_BUFSIZE-3)/4; j++) { // 15 bytes
485 + buf[buf_pos++] = (addr & 1)?0x48:0x40;
486 + buf[buf_pos++] = (addr >> 9) & 0xff;
487 + buf[buf_pos++] = (addr >> 1) & 0xff;
488 + buf[buf_pos++] = m->buf[i];
492 + (((i % m->page_size) == 0) || (i == n_bytes))) {
497 + buf[2] = buf_pos - 3;
498 +#ifdef USE_INLINE_WRITE_PAGE
499 + if (do_page_write) {
500 + int addr_wk = addr_save - (addr_save % m->page_size);
501 + /* If this device has a "load extended address" command, issue it. */
502 + if (m->op[AVR_OP_LOAD_EXT_ADDR]) {
503 + OPCODE *lext = m->op[AVR_OP_LOAD_EXT_ADDR];
505 + buf[buf_pos++] = 'd'; /* PUT TDI Stream */
506 + buf[buf_pos++] = JTAG_RECIEVE | use_delay;
507 + buf[buf_pos++] = 4; /* bytes */
509 + memset(buf+buf_pos, 0, 4);
510 + avr_set_bits(lext, buf+buf_pos);
511 + avr_set_addr(lext, buf+buf_pos, addr/2);
514 + buf[buf_pos++] = 'd'; /* PUT TDI Stream */
515 + buf[buf_pos++] = JTAG_RECIEVE | use_delay;
516 + buf[buf_pos++] = 4; /* bytes */
517 + buf[buf_pos++] = 0x4C; /* Issue Page Write */
518 + buf[buf_pos++] = (addr_wk >> 9) & 0xff;
519 + buf[buf_pos++] = (addr_wk >> 1) & 0xff;
520 + buf[buf_pos++] = 0;
521 + buf[buf_pos++] = 'r'; /* Request Recieved Data */
522 + buf[buf_pos++] = 0;
523 + buf[buf_pos++] = 0;
526 + serjtag_write(pgm, buf, buf_pos);
528 +fprintf(stderr, "send addr 0x%04x size %d bufsize %d i %d page_write %d\n",
529 + addr_wk,buf[2],buf_pos,i,do_page_write);
531 + if (do_page_write) {
532 +#ifdef USE_INLINE_WRITE_PAGE
533 + serjtag_flush(pgm);
534 + usleep(m->max_write_delay);
535 + serjtag_recv_j(pgm, buf, 4 + 3, 0);
538 + serjtag_flush(pgm);
539 + addr_wk = (i-1) / m->page_size * m->page_size;
540 + rc = avr_write_page(pgm, p, m, addr_wk);
546 + report_progress(i, n_bytes, NULL);
548 + serjtag_flush(pgm);
553 +static int serjtag_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
554 + int page_size, int n_bytes)
556 + if (strcmp(m->desc, "flash") == 0) {
557 + return serjtag_paged_write_flash(pgm, p, m, page_size, n_bytes);
559 + else if (strcmp(m->desc, "eeprom") == 0) {
560 + return serjtag_paged_write_gen(pgm, p, m, page_size, n_bytes);
568 +static int serjtag_paged_load_gen(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
569 + int page_size, int n_bytes)
571 + unsigned char rbyte;
575 + for (i=0; i<n_bytes; i++) {
576 + rc = avr_read_byte_default(pgm, p, m, i, &rbyte);
581 + report_progress(i, n_bytes, NULL);
587 +static struct serjtag_request {
591 + struct serjtag_request *next;
592 +} *req_head,*req_tail,*req_pool;
594 +static void put_request(int addr, int bytes, int n)
596 + struct serjtag_request *p;
599 + req_pool = p->next;
601 + p = malloc(sizeof(struct serjtag_request));
603 + fprintf(stderr, "can't alloc memory\n");
607 + memset(p, 0, sizeof(struct serjtag_request));
612 + req_tail->next = p;
615 + req_head = req_tail = p;
619 +static int do_request(PROGRAMMER * pgm, AVRMEM *m)
621 + struct serjtag_request *p;
622 + int addr, bytes, j, n;
625 + if (!req_head) return 0;
627 + req_head = p->next;
628 + if (!req_head) req_tail = req_head;
633 + memset(p, 0, sizeof(struct serjtag_request));
634 + p->next = req_pool;
637 + serjtag_recv_j(pgm, buf, bytes + 3, 0);
638 + for (j=0; j<n; j++) {
639 + m->buf[addr++] = buf[3 + 4*j + 3];
644 +#define REQ_OUTSTANDINGS 10
645 +static int serjtag_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
646 + int page_size, int n_bytes)
648 + unsigned long i,j,n;
650 + int addr,addr_save,bytes,buf_pos;
655 + for (i=0; i<n_bytes; ) {
657 + buf[buf_pos++] = 'd'; /* PUT TDI Stream */
658 + buf[buf_pos++] = JTAG_RECIEVE | use_delay;
659 + buf[buf_pos++] = 0; /* bytes : set after */
661 + for (j=0; j<(JTAG_BUFSIZE-3*2)/4; j++) { // 14 bytes
662 + if (i >= n_bytes) break;
663 + buf[buf_pos++] = (addr & 1)?0x28:0x20;
664 + buf[buf_pos++] = (addr >> 9) & 0xff;
665 + buf[buf_pos++] = (addr >> 1) & 0xff;
666 + buf[buf_pos++] = 0;
671 + buf[2] = bytes = buf_pos - 3;
672 + buf[buf_pos++] = 'r'; /* Request Recieved Data */
673 + buf[buf_pos++] = 0;
674 + buf[buf_pos++] = 0;
675 + serjtag_send(pgm, buf, buf_pos);
676 + put_request(addr_save, bytes, n);
678 + if (req_count > REQ_OUTSTANDINGS)
679 + do_request(pgm, m);
680 + report_progress(i, n_bytes, NULL);
682 + while (do_request(pgm, m))
687 +static int serjtag_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m,
688 + int page_size, int n_bytes)
690 + if (strcmp(m->desc, "flash") == 0) {
691 + return serjtag_paged_load_flash(pgm, p, m, page_size, n_bytes);
693 + else if (strcmp(m->desc, "eeprom") == 0) {
694 + return serjtag_paged_load_gen(pgm, p, m, page_size, n_bytes);
701 +void serjtag_initpgm(PROGRAMMER * pgm)
703 + strcpy(pgm->type, "serjtag");
706 + * mandatory functions
708 + pgm->initialize = serjtag_initialize;
709 + pgm->display = serjtag_display;
710 + pgm->enable = serjtag_enable;
711 + pgm->disable = serjtag_disable;
712 + pgm->program_enable = serjtag_program_enable;
713 + pgm->chip_erase = serjtag_chip_erase;
714 + pgm->cmd = serjtag_cmd;
715 + pgm->open = serjtag_open;
716 + pgm->close = serjtag_close;
717 + pgm->read_byte = avr_read_byte_default;
718 + pgm->write_byte = avr_write_byte_default;
721 + * optional functions
724 + pgm->paged_write = serjtag_paged_write;
725 + pgm->paged_load = serjtag_paged_load;
726 + pgm->read_sig_bytes = serjtag_read_sig_bytes;