static void buspirate_reset_from_binmode(struct programmer_t *pgm) { char buf[10]; buf[0] = 0x00; /* BinMode: revert to HiZ */ buspirate_send_bin(pgm, buf, 1); buf[0] = 0x0F; /* BinMode: reset */ buspirate_send_bin(pgm, buf, 1); /* read back all output */ memset(buf, '\0', sizeof(buf)); for (;;) { int rc; rc = buspirate_recv_bin(pgm, buf, sizeof(buf) - 1); if (buspirate_is_prompt(buf)) { pgm->flag &= ~BP_FLAG_IN_BINMODE; break; } if (rc == EOF) break; memset(buf, '\0', sizeof(buf)); } if (pgm->flag & BP_FLAG_IN_BINMODE) { fprintf(stderr, "BusPirate reset failed. You may need to powercycle it.\n"); exit(1); } if (verbose) fprintf(stderr, "BusPirate is back in the text mode\n"); }
static int buspirate_start_spi_mode_bin(struct programmer_t *pgm) { char buf[20] = { '\0' }; /* == Switch to binmode - send 20x '\0' == */ buspirate_send_bin(pgm, buf, sizeof(buf)); /* Expecting 'BBIOx' reply */ memset(buf, 0, sizeof(buf)); buspirate_recv_bin(pgm, buf, 5); if (sscanf(buf, "BBIO%d", &PDATA(pgm)->binmode_version) != 1) { fprintf(stderr, "Binary mode not confirmed: '%s'\n", buf); buspirate_reset_from_binmode(pgm); return -1; } if (verbose) fprintf(stderr, "BusPirate binmode version: %d\n", PDATA(pgm)->binmode_version); pgm->flag |= BP_FLAG_IN_BINMODE; /* == Enter SPI mode == */ buf[0] = 0x01; /* Enter raw SPI mode */ buspirate_send_bin(pgm, buf, 1); memset(buf, 0, sizeof(buf)); buspirate_recv_bin(pgm, buf, 4); if (sscanf(buf, "SPI%d", &PDATA(pgm)->bin_spi_version) != 1) { fprintf(stderr, "SPI mode not confirmed: '%s'\n", buf); buspirate_reset_from_binmode(pgm); return -1; } if (verbose) fprintf(stderr, "BusPirate SPI version: %d\n", PDATA(pgm)->bin_spi_version); /* 0b0100wxyz - Configure peripherals w=power, x=pull-ups/aux2, y=AUX, z=CS * we want power (0x48) and all reset pins high. */ PDATA(pgm)->current_peripherals_config = 0x48; PDATA(pgm)->current_peripherals_config |= BP_RESET_CS; PDATA(pgm)->current_peripherals_config |= BP_RESET_AUX; if (buspirate_has_aux2(pgm)) PDATA(pgm)->current_peripherals_config |= BP_RESET_AUX2; buspirate_expect_bin_byte(pgm, PDATA(pgm)->current_peripherals_config, 0x01); usleep(50000); // sleep for 50ms after power up /* 01100xxx - SPI speed * xxx = 000=30kHz, 001=125kHz, 010=250kHz, 011=1MHz, * 100=2MHz, 101=2.6MHz, 110=4MHz, 111=8MHz * use 30kHz = 0x60 */ buspirate_expect_bin_byte(pgm, 0x60 | PDATA(pgm)->spifreq, 0x01); /* 1000wxyz - SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample * we want: 3.3V(1), idle low(0), data change on trailing edge (1), * sample in the middle of the pulse (0) * => 0b10001010 = 0x8a */ buspirate_expect_bin_byte(pgm, 0x8A, 0x01); return 0; }
static int buspirate_cmd_bin(struct programmer_t *pgm, unsigned char cmd[4], unsigned char res[4]) { /* 0001xxxx - Bulk SPI transfer, send/read 1-16 bytes (0=1byte!) * we are sending 4 bytes -> 0x13 */ if (!buspirate_expect_bin_byte(pgm, 0x13, 0x01)) return -1; buspirate_send_bin(pgm, (char *)cmd, 4); buspirate_recv_bin(pgm, (char *)res, 4); return 0; }
static int buspirate_expect_bin(struct programmer_t *pgm, char *send_data, size_t send_len, char *expect_data, size_t expect_len) { char *recv_buf = alloca(expect_len); if (!pgm->flag & BP_FLAG_IN_BINMODE) { fprintf(stderr, "BusPirate: Internal error: buspirate_send_bin() called from ascii mode"); exit(1); } buspirate_send_bin(pgm, send_data, send_len); buspirate_recv_bin(pgm, recv_buf, expect_len); if (memcmp(expect_data, recv_buf, expect_len) != 0) return 0; return 1; }
/* Paged write function which utilizes the Bus Pirate's "Write then Read" binary SPI instruction */ static int buspirate_paged_write(struct programmer_t *pgm, AVRPART *p, AVRMEM *m, unsigned int page_size, unsigned int base_addr, unsigned int n_data_bytes) { int page, i; int addr = base_addr; int n_page_writes; int this_page_size; char cmd_buf[4096] = {'\0'}; char send_byte, recv_byte; if (!(pgm->flag & BP_FLAG_IN_BINMODE)) { /* Return if we are not in binary mode. */ return -1; } if (pgm->flag & BP_FLAG_NOPAGEDWRITE) { /* Return if we've nominated not to use paged writes. */ return -1; } if (page_size>1024) { /* Page sizes greater than 1kB not yet supported. */ return -1; } if (strcmp(m->desc,"flash") != 0) { /* Only flash memory currently supported. */ return -1; } /* pre-check opcodes */ if (m->op[AVR_OP_LOADPAGE_LO] == NULL) { fprintf(stderr, "%s failure: %s command not defined for %s\n", progname, "AVR_OP_LOADPAGE_LO", p->desc); return -1; } if (m->op[AVR_OP_LOADPAGE_HI] == NULL) { fprintf(stderr, "%s failure: %s command not defined for %s\n", progname, "AVR_OP_LOADPAGE_HI", p->desc); return -1; } /* Calculate total number of page writes needed: */ n_page_writes = n_data_bytes/page_size; if (n_data_bytes%page_size >0) n_page_writes++; /* Ensure error LED is off: */ pgm->err_led(pgm, OFF); /* Loop over pages: */ for (page=0; page<n_page_writes; page++) { /* Determine bytes to write in this page: */ this_page_size = page_size; if (page == n_page_writes-1) this_page_size = n_data_bytes - page_size*page; /* Set up command buffer: */ memset(cmd_buf, 0, 4*this_page_size); for (i=0; i<this_page_size; i++) { addr = base_addr + page*page_size + i; if (i%2 == 0) { avr_set_bits(m->op[AVR_OP_LOADPAGE_LO], &(cmd_buf[4*i])); avr_set_addr(m->op[AVR_OP_LOADPAGE_LO], &(cmd_buf[4*i]), addr/2); avr_set_input(m->op[AVR_OP_LOADPAGE_LO], &(cmd_buf[4*i]), m->buf[addr]); } else { avr_set_bits(m->op[AVR_OP_LOADPAGE_HI], &(cmd_buf[4*i])); avr_set_addr(m->op[AVR_OP_LOADPAGE_HI], &(cmd_buf[4*i]), addr/2); avr_set_input(m->op[AVR_OP_LOADPAGE_HI], &(cmd_buf[4*i]), m->buf[addr]); } } /* 00000100 - Write then read */ send_byte = 0x05; buspirate_send_bin(pgm, &send_byte, 1); /* Number of bytes to write: */ send_byte = (4*this_page_size)/0x100; buspirate_send_bin(pgm, &send_byte, 1); /* High byte */ send_byte = (4*this_page_size)%0x100; buspirate_send_bin(pgm, &send_byte, 1); /* Low byte */ /* Number of bytes to read: */ send_byte = 0x0; buspirate_send_bin(pgm, &send_byte, 1); /* High byte */ buspirate_send_bin(pgm, &send_byte, 1); /* Low byte */ /* Set programming LED: */ pgm->pgm_led(pgm, ON); /* Send command buffer: */ buspirate_send_bin(pgm, cmd_buf, 4*this_page_size); /* Check for write failure: */ if ((buspirate_recv_bin(pgm, &recv_byte, 1) == EOF) || (recv_byte != 0x01)) { fprintf(stderr, "BusPirate: Fatal error: Write Then Read did not succeed.\n"); pgm->pgm_led(pgm, OFF); pgm->err_led(pgm, ON); exit(1); } /* Unset programming LED: */ pgm->pgm_led(pgm, OFF); /* Write loaded page to flash: */ avr_write_page(pgm, p, m, addr); } return n_data_bytes; }
static void buspirate_enable(struct programmer_t *pgm) { unsigned char *reset_str = "#\n"; unsigned char *accept_str = "y\n"; char *rcvd; int rc, print_banner = 0; /* Ensure configuration is self-consistant: */ if (buspirate_verifyconfig(pgm)<0) exit(1); /* Attempt to start binary SPI mode unless explicitly told otherwise: */ if (!buspirate_uses_ascii(pgm)) { fprintf(stderr, "Attempting to initiate BusPirate binary mode...\n"); /* Send two CRs to ensure we're not in a sub-menu of the UI if we're in ASCII mode: */ buspirate_send_bin(pgm, "\n\n", 2); /* Clear input buffer: */ serial_drain(&pgm->fd, 0); /* Attempt to enter binary mode: */ if (buspirate_start_spi_mode_bin(pgm) >= 0) return; else fprintf(stderr, "%s: Failed to start binary SPI mode, falling back to ASCII...\n", progname); } fprintf(stderr, "Attempting to initiate BusPirate ASCII mode...\n"); /* Call buspirate_send_bin() instead of buspirate_send() * because we don't know if BP is in text or bin mode */ rc = buspirate_send_bin(pgm, reset_str, strlen(reset_str)); if (rc) { fprintf(stderr, "BusPirate is not responding. Serial port error: %d\n", rc); exit(1); } while(1) { rcvd = buspirate_readline_noexit(pgm, NULL, 0); if (! rcvd) { fprintf(stderr, "%s: Fatal: Programmer is not responding.\n", progname); exit(1); } if (strncmp(rcvd, "Are you sure?", 13) == 0) { buspirate_send_bin(pgm, accept_str, strlen(accept_str)); } if (strncmp(rcvd, "RESET", 5) == 0) { print_banner = 1; continue; } if (buspirate_is_prompt(rcvd)) { puts("**"); break; } if (print_banner) fprintf(stderr, "** %s", rcvd); } if (!(pgm->flag & BP_FLAG_IN_BINMODE)) { fprintf(stderr, "BusPirate: using ASCII mode\n"); if (buspirate_start_spi_mode_ascii(pgm) < 0) { fprintf(stderr, "%s: Failed to start ascii SPI mode\n", progname); exit(1); } } }
static int buspirate_start_spi_mode_bin(struct programmer_t *pgm) { char buf[20] = { '\0' }; /* == Switch to binmode - send 20x '\0' == */ buspirate_send_bin(pgm, buf, sizeof(buf)); /* Expecting 'BBIOx' reply */ memset(buf, 0, sizeof(buf)); buspirate_recv_bin(pgm, buf, 5); if (sscanf(buf, "BBIO%d", &PDATA(pgm)->binmode_version) != 1) { fprintf(stderr, "Binary mode not confirmed: '%s'\n", buf); buspirate_reset_from_binmode(pgm); return -1; } if (verbose) fprintf(stderr, "BusPirate binmode version: %d\n", PDATA(pgm)->binmode_version); pgm->flag |= BP_FLAG_IN_BINMODE; /* == Enter SPI mode == */ buf[0] = 0x01; /* Enter raw SPI mode */ buspirate_send_bin(pgm, buf, 1); memset(buf, 0, sizeof(buf)); buspirate_recv_bin(pgm, buf, 4); if (sscanf(buf, "SPI%d", &PDATA(pgm)->bin_spi_version) != 1) { fprintf(stderr, "SPI mode not confirmed: '%s'\n", buf); buspirate_reset_from_binmode(pgm); return -1; } if (verbose) fprintf(stderr, "BusPirate SPI version: %d\n", PDATA(pgm)->bin_spi_version); if (pgm->flag & BP_FLAG_NOPAGEDWRITE) { if (verbose) fprintf(stderr, "%s: Paged flash write disabled.\n", progname); } else { /* Check for write-then-read without !CS/CS and disable paged_write if absent: */ strncpy(buf, "\x5\x0\x0\x0\x0", 5); buspirate_send_bin(pgm, buf, 5); buspirate_recv_bin(pgm, buf, 1); if (buf[0] != 0x01) { /* Disable paged write: */ pgm->flag |= BP_FLAG_NOPAGEDWRITE; /* Return to SPI mode (0x00s have landed us back in binary bitbang mode): */ buf[0] = 0x1; buspirate_send_bin(pgm, buf, 1); if (verbose) fprintf(stderr, "%s: Disabling paged flash write. (Need BusPirate firmware >=v5.10.)\n", progname); /* Flush serial buffer: */ serial_drain(&pgm->fd, 0); } else { if (verbose) fprintf(stderr, "%s: Paged flash write enabled.\n", progname); } } /* 0b0100wxyz - Configure peripherals w=power, x=pull-ups/aux2, y=AUX, z=CS * we want power (0x48) and all reset pins high. */ PDATA(pgm)->current_peripherals_config = 0x48 | PDATA(pgm)->reset; buspirate_expect_bin_byte(pgm, PDATA(pgm)->current_peripherals_config, 0x01); usleep(50000); // sleep for 50ms after power up /* 01100xxx - SPI speed * xxx = 000=30kHz, 001=125kHz, 010=250kHz, 011=1MHz, * 100=2MHz, 101=2.6MHz, 110=4MHz, 111=8MHz * use 30kHz = 0x60 */ buspirate_expect_bin_byte(pgm, 0x60 | PDATA(pgm)->spifreq, 0x01); /* 1000wxyz - SPI config, w=HiZ(0)/3.3v(1), x=CLK idle, y=CLK edge, z=SMP sample * we want: 3.3V(1), idle low(0), data change on trailing edge (1), * sample in the middle of the pulse (0) * => 0b10001010 = 0x8a */ buspirate_expect_bin_byte(pgm, 0x8A, 0x01); return 0; }
static void buspirate_enable(struct programmer_t *pgm) { unsigned char *reset_str = "#\n"; unsigned char *accept_str = "y\n"; char *rcvd; int fw_v1 = 0, fw_v2 = 0; int rc, print_banner = 0; fprintf(stderr, "Detecting BusPirate...\n"); /* Call buspirate_send_bin() instead of buspirate_send() * because we don't know if BP is in text or bin mode */ rc = buspirate_send_bin(pgm, reset_str, strlen(reset_str)); if (rc) { fprintf(stderr, "BusPirate is not responding. Serial port error: %d\n", rc); exit(1); } while(1) { rcvd = buspirate_readline_noexit(pgm, NULL, 0); if (! rcvd) { fprintf(stderr, "BusPirate is not responding. Attempting reset.\n"); buspirate_reset_from_binmode(pgm); /* re-run buspirate_enable() */ buspirate_enable(pgm); return; } if (strncmp(rcvd, "Are you sure?", 13) == 0) { buspirate_send_bin(pgm, accept_str, strlen(accept_str)); } if (strncmp(rcvd, "RESET", 5) == 0) { print_banner = 1; continue; } if (buspirate_is_prompt(rcvd)) { puts("**"); break; } sscanf(rcvd, "Bus Pirate %9s", PDATA(pgm)->hw_version); sscanf(rcvd, "Firmware v%d.%d", &fw_v1, &fw_v2); if (print_banner) fprintf(stderr, "** %s", rcvd); } PDATA(pgm)->fw_version = 100 * fw_v1 + fw_v2; if (PDATA(pgm)->hw_version[0] == 0 || PDATA(pgm)->fw_version == 0) { fprintf(stderr, "BusPirate not detected. Aborting.\n"); exit(1); } if (buspirate_verifyconfig(pgm) < 0) exit(1); if (PDATA(pgm)->fw_version >= FW_BINMODE_VER && !(pgm->flag & BP_FLAG_XPARM_FORCE_ASCII)) { fprintf(stderr, "BusPirate: using BINARY mode\n"); if (buspirate_start_spi_mode_bin(pgm) < 0) fprintf(stderr, "%s: Failed to start binary SPI mode\n", progname); } if (!pgm->flag & BP_FLAG_IN_BINMODE) { fprintf(stderr, "BusPirate: using ASCII mode\n"); if (buspirate_start_spi_mode_ascii(pgm) < 0) { fprintf(stderr, "%s: Failed to start ascii SPI mode\n", progname); exit(1); } } }