static int set_reset(PROGRAMMER * pgm, int val) { unsigned char buf[1]; buf[0] = 0; if (val) buf[0] |= ft245r_reset; ft245r_send (pgm, buf, 1); ft245r_recv (pgm, buf, 1); return 0; }
static int set_pin(PROGRAMMER * pgm, int pinname, int val) { unsigned char buf[1]; if (pgm->pin[pinname].mask[0] == 0) { // ignore not defined pins (might be the led or vcc or buff if not needed) return 0; } ft245r_out = SET_BITS_0(ft245r_out,pgm,pinname,val); buf[0] = ft245r_out; ft245r_send (pgm, buf, 1); ft245r_recv (pgm, buf, 1); return 0; }
/* * transmit an AVR device command and return the results; 'cmd' and * 'res' must point to at least a 4 byte data buffer */ static int ft245r_cmd(PROGRAMMER * pgm, const unsigned char *cmd, unsigned char *res) { int i,buf_pos; unsigned char buf[128]; buf_pos = 0; for (i=0; i<4; i++) { buf_pos += set_data(pgm, buf+buf_pos, cmd[i]); } buf[buf_pos] = 0; buf_pos++; ft245r_send (pgm, buf, buf_pos); ft245r_recv (pgm, buf, buf_pos); res[0] = extract_data(pgm, buf, 0); res[1] = extract_data(pgm, buf, 1); res[2] = extract_data(pgm, buf, 2); res[3] = extract_data(pgm, buf, 3); return 0; }
static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes) { unsigned long i,j,n; //int rc; int addr,addr_save,buf_pos; int req_count = 0; char buf[FT245R_FRAGMENT_SIZE+1]; addr = 0; for (i=0; i<n_bytes; ) { buf_pos = 0; addr_save = addr; for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) { if (i >= n_bytes) break; buf_pos += set_data(buf+buf_pos, (addr & 1)?0x28:0x20 ); buf_pos += set_data(buf+buf_pos, (addr >> 9) & 0xff ); buf_pos += set_data(buf+buf_pos, (addr >> 1) & 0xff ); buf_pos += set_data(buf+buf_pos, 0); addr ++; i++; } if (i >= n_bytes) { buf[buf_pos++] = 0; // sck down } n = j; ft245r_send(pgm, buf, buf_pos); put_request(addr_save, buf_pos, n); req_count++; if (req_count > REQ_OUTSTANDINGS) do_request(pgm, m); report_progress(i, n_bytes, NULL); } while (do_request(pgm, m)) ; return 0; }
static int ft245r_paged_load_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, unsigned int page_size, unsigned int addr, unsigned int n_bytes) { unsigned long i,j,n; int addr_save,buf_pos; int req_count = 0; unsigned char buf[FT245R_FRAGMENT_SIZE+1]; for (i=0; i<n_bytes; ) { buf_pos = 0; addr_save = addr; for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) { if (i >= n_bytes) break; buf_pos += set_data(pgm, buf+buf_pos, (addr & 1)?0x28:0x20 ); buf_pos += set_data(pgm, buf+buf_pos, (addr >> 9) & 0xff ); buf_pos += set_data(pgm, buf+buf_pos, (addr >> 1) & 0xff ); buf_pos += set_data(pgm, buf+buf_pos, 0); addr ++; i++; } if (i >= n_bytes) { ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); // sck down buf[buf_pos++] = ft245r_out; } n = j; ft245r_send(pgm, buf, buf_pos); put_request(addr_save, buf_pos, n); req_count++; if (req_count > REQ_OUTSTANDINGS) do_request(pgm, m); } while (do_request(pgm, m)) ; return 0; }
static int ft245r_paged_write_flash(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int page_size, int n_bytes) { unsigned int i,j; int addr,addr_save,buf_pos,do_page_write,req_count; char buf[FT245R_FRAGMENT_SIZE+1+128]; req_count = 0; addr = 0; for (i=0; i<n_bytes; ) { addr_save = addr; buf_pos = 0; do_page_write = 0; for (j=0; j< FT245R_FRAGMENT_SIZE/8/FT245R_CYCLES/4; j++) { buf_pos += set_data(buf+buf_pos, (addr & 1)?0x48:0x40 ); buf_pos += set_data(buf+buf_pos, (addr >> 9) & 0xff ); buf_pos += set_data(buf+buf_pos, (addr >> 1) & 0xff ); buf_pos += set_data(buf+buf_pos, m->buf[i]); addr ++; i++; if ( (m->paged) && (((i % m->page_size) == 0) || (i == n_bytes))) { do_page_write = 1; break; } } #if defined(USE_INLINE_WRITE_PAGE) if (do_page_write) { int addr_wk = addr_save - (addr_save % m->page_size); /* If this device has a "load extended address" command, issue it. */ if (m->op[AVR_OP_LOAD_EXT_ADDR]) { unsigned char cmd[4]; OPCODE *lext = m->op[AVR_OP_LOAD_EXT_ADDR]; memset(cmd, 0, 4); avr_set_bits(lext, cmd); avr_set_addr(lext, cmd, addr_wk/2); buf_pos += set_data(buf+buf_pos, cmd[0]); buf_pos += set_data(buf+buf_pos, cmd[1]); buf_pos += set_data(buf+buf_pos, cmd[2]); buf_pos += set_data(buf+buf_pos, cmd[3]); } buf_pos += set_data(buf+buf_pos, 0x4C); /* Issue Page Write */ buf_pos += set_data(buf+buf_pos,(addr_wk >> 9) & 0xff); buf_pos += set_data(buf+buf_pos,(addr_wk >> 1) & 0xff); buf_pos += set_data(buf+buf_pos, 0); } #endif if (i >= n_bytes) { buf[buf_pos++] = 0; // sck down } ft245r_send(pgm, buf, buf_pos); put_request(addr_save, buf_pos, 0); //ft245r_sync(pgm); #if 0 fprintf(stderr, "send addr 0x%04x bufsize %d [%02x %02x] page_write %d\n", addr_save,buf_pos, extract_data_out(buf , (0*4 + 3) ), extract_data_out(buf , (1*4 + 3) ), do_page_write); #endif req_count++; if (req_count > REQ_OUTSTANDINGS) do_request(pgm, m); if (do_page_write) { #if defined(USE_INLINE_WRITE_PAGE) while (do_request(pgm, m)) ; usleep(m->max_write_delay); #else int addr_wk = addr_save - (addr_save % m->page_size); int rc; while (do_request(pgm, m)) ; rc = avr_write_page(pgm, p, m, addr_wk); if (rc != 0) { return -2; } #endif req_count = 0; } report_progress(i, n_bytes, NULL); } while (do_request(pgm, m)) ; return i; }
static int ft245r_open(PROGRAMMER * pgm, char * port) { int rv; int devnum = -1; rv = pins_check(pgm,pin_checklist,sizeof(pin_checklist)/sizeof(pin_checklist[0]), true); if(rv) { pgm->display(pgm, progbuf); return rv; } strcpy(pgm->port, port); if (strcmp(port,DEFAULT_USB) != 0) { if (strncasecmp("ft", port, 2) == 0) { char *startptr = port + 2; char *endptr = NULL; devnum = strtol(startptr,&endptr,10); if ((startptr==endptr) || (*endptr != '\0')) { devnum = -1; } } if (devnum < 0) { avrdude_message(MSG_INFO, "%s: invalid portname '%s': use 'ft[0-9]+'\n", progname,port); return -1; } } else { devnum = 0; } handle = malloc (sizeof (struct ftdi_context)); ftdi_init(handle); LNODEID usbpid = lfirst(pgm->usbpid); int pid; if (usbpid) { pid = *(int *)(ldata(usbpid)); if (lnext(usbpid)) avrdude_message(MSG_INFO, "%s: Warning: using PID 0x%04x, ignoring remaining PIDs in list\n", progname, pid); } else { pid = USB_DEVICE_FT245; } rv = ftdi_usb_open_desc_index(handle, pgm->usbvid?pgm->usbvid:USB_VENDOR_FTDI, pid, pgm->usbproduct[0]?pgm->usbproduct:NULL, pgm->usbsn[0]?pgm->usbsn:NULL, devnum); if (rv) { avrdude_message(MSG_INFO, "can't open ftdi device %d. (%s)\n", devnum, ftdi_get_error_string(handle)); goto cleanup_no_usb; } ft245r_ddr = pgm->pin[PIN_AVR_SCK].mask[0] | pgm->pin[PIN_AVR_MOSI].mask[0] | pgm->pin[PIN_AVR_RESET].mask[0] | pgm->pin[PPI_AVR_BUFF].mask[0] | pgm->pin[PPI_AVR_VCC].mask[0] | pgm->pin[PIN_LED_ERR].mask[0] | pgm->pin[PIN_LED_RDY].mask[0] | pgm->pin[PIN_LED_PGM].mask[0] | pgm->pin[PIN_LED_VFY].mask[0]; /* set initial values for outputs, no reset everything else is off */ ft245r_out = 0; ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_RESET,1); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_SCK,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_AVR_MOSI,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PPI_AVR_BUFF,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PPI_AVR_VCC,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_ERR,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_RDY,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_PGM,0); ft245r_out = SET_BITS_0(ft245r_out,pgm,PIN_LED_VFY,0); rv = ftdi_set_bitmode(handle, ft245r_ddr, BITMODE_SYNCBB); // set Synchronous BitBang if (rv) { avrdude_message(MSG_INFO, "%s: Synchronous BitBangMode is not supported (%s)\n", progname, ftdi_get_error_string(handle)); goto cleanup; } rv = ft245r_set_bitclock(pgm); if (rv) { goto cleanup; } /* We start a new thread to read the output from the FTDI. This is * necessary because otherwise we'll deadlock. We cannot finish * writing because the ftdi cannot send the results because we * haven't provided a read buffer yet. */ sem_init (&buf_data, 0, 0); sem_init (&buf_space, 0, BUFSIZE); pthread_create (&readerthread, NULL, reader, handle); /* * drain any extraneous input */ ft245r_drain (pgm, 0); ft245r_send (pgm, &ft245r_out, 1); ft245r_recv (pgm, &ft245r_in, 1); return 0; cleanup: ftdi_usb_close(handle); cleanup_no_usb: ftdi_deinit (handle); free(handle); handle = NULL; return -1; }