diff options
Diffstat (limited to 'xs/src')
-rw-r--r-- | xs/src/avrdude/arduino.c | 51 | ||||
-rw-r--r-- | xs/src/avrdude/stk500.c | 123 | ||||
-rw-r--r-- | xs/src/slic3r/GUI/FirmwareDialog.cpp | 12 |
3 files changed, 138 insertions, 48 deletions
diff --git a/xs/src/avrdude/arduino.c b/xs/src/avrdude/arduino.c index 566f56abd..886a43f0b 100644 --- a/xs/src/avrdude/arduino.c +++ b/xs/src/avrdude/arduino.c @@ -102,6 +102,57 @@ static int arduino_open(PROGRAMMER * pgm, char * port) */ stk500_drain(pgm, 0); +{ + //FIXME initialization sequence for programming the external FLASH. + const char entry_magic_send [] = "start\n"; + const char entry_magic_receive[] = "w25x20cl_enter\n"; + const char entry_magic_cfm [] = "w25x20cl_cfm\n"; + const char *entry_magic_ptr = entry_magic_send; + struct timeval tv; + double tstart, tnow; + char c; + gettimeofday(&tv, NULL); + tstart = tv.tv_sec; + while (*entry_magic_ptr != 0) { + if (serial_recv(&pgm->fd, &c, 1) < 0) + goto timedout; + printf("Received: %c (%d)\n", c, (int)c); + if (c != *entry_magic_ptr ++) { + avrdude_message(MSG_INFO, "%s: stk500v2_recv(): MK3 printer emited incorrect start code\n", progname); + return -1; + } + gettimeofday(&tv, NULL); + tnow = tv.tv_sec; + if (tnow-tstart > 2.) { // wuff - signed/unsigned/overflow + timedout: + avrdude_message(MSG_INFO, "%s: stk500v2_recv(): MK3 printer did not boot up on time\n", progname); + return -1; + } + } + if (serial_send(&pgm->fd, entry_magic_receive, strlen(entry_magic_receive)) < 0) { + avrdude_message(MSG_INFO, "%s: stk500v2_send(): failed to send command to serial port\n",progname); + return -1; + } + + entry_magic_ptr = entry_magic_cfm; + while (*entry_magic_ptr != 0) { + if (serial_recv(&pgm->fd, &c, 1) < 0) + goto timedout2; + printf("Received: %c (%d)\n", c, (int)c); + if (c != *entry_magic_ptr++) { + avrdude_message(MSG_INFO, "%s: stk500v2_recv(): MK3 printer emited incorrect start code\n", progname); + return -1; + } + gettimeofday(&tv, NULL); + tnow = tv.tv_sec; + if (tnow - tstart > 2.) { // wuff - signed/unsigned/overflow + timedout2: + avrdude_message(MSG_INFO, "%s: stk500v2_recv(): MK3 printer did not boot up on time\n", progname); + return -1; + } + } +} + if (stk500_getsync(pgm) < 0) return -1; diff --git a/xs/src/avrdude/stk500.c b/xs/src/avrdude/stk500.c index 5d2d3c1df..63deb228f 100644 --- a/xs/src/avrdude/stk500.c +++ b/xs/src/avrdude/stk500.c @@ -716,11 +716,14 @@ static int stk500_loadaddr(PROGRAMMER * pgm, AVRMEM * mem, unsigned int addr) } buf[0] = Cmnd_STK_LOAD_ADDRESS; - buf[1] = addr & 0xff; - buf[2] = (addr >> 8) & 0xff; - buf[3] = Sync_CRC_EOP; - - stk500_send(pgm, buf, 4); + // Workaround for the infamous ';' bug in the Prusa3D usb to serial converter. + // Send the binary data by nibbles to avoid transmitting the ';' character. + buf[1] = addr & 0x0f; + buf[2] = addr & 0xf0; + buf[3] = (addr >> 8) & 0x0f; + buf[4] = (addr >> 8) & 0xf0; + buf[5] = Sync_CRC_EOP; + stk500_send(pgm, buf, 6); if (stk500_recv(pgm, buf, 1) < 0) return -1; @@ -765,7 +768,9 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, int block_size; int tries; unsigned int n; - unsigned int i; + unsigned int i, j; + unsigned int prusa3d_semicolon_workaround_round = 0; + bool has_semicolon = false; if (strcmp(m->desc, "flash") == 0) { memtype = 'F'; @@ -806,44 +811,64 @@ static int stk500_paged_write(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, tries++; stk500_loadaddr(pgm, m, addr/a_div); - /* build command block and avoid multiple send commands as it leads to a crash - of the silabs usb serial driver on mac os x */ - i = 0; - buf[i++] = Cmnd_STK_PROG_PAGE; - buf[i++] = (block_size >> 8) & 0xff; - buf[i++] = block_size & 0xff; - buf[i++] = memtype; - memcpy(&buf[i], &m->buf[addr], block_size); - i += block_size; - buf[i++] = Sync_CRC_EOP; - stk500_send( pgm, buf, i); + for (i = 0; i < n_bytes; ++ i) + if (m->buf[addr + i] == ';') { + has_semicolon = true; + break; + } - if (stk500_recv(pgm, buf, 1) < 0) - return -1; - if (buf[0] == Resp_STK_NOSYNC) { - if (tries > 33) { - avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): can't get into sync\n", - progname); - return -3; + for (prusa3d_semicolon_workaround_round = 0; prusa3d_semicolon_workaround_round < (has_semicolon ? 2 : 1); ++ prusa3d_semicolon_workaround_round) { + /* build command block and avoid multiple send commands as it leads to a crash + of the silabs usb serial driver on mac os x */ + i = 0; + buf[i++] = Cmnd_STK_PROG_PAGE; + // Workaround for the infamous ';' bug in the Prusa3D usb to serial converter. + // Send the binary data by nibbles to avoid transmitting the ';' character. + buf[i++] = (block_size >> 8) & 0xf0; + buf[i++] = (block_size >> 8) & 0x0f; + buf[i++] = block_size & 0xf0; + buf[i++] = block_size & 0x0f; + buf[i++] = memtype; + if (has_semicolon) { + for (j = 0; j < block_size; ++i, ++ j) { + buf[i] = m->buf[addr + j]; + if (buf[i] == ';') + buf[i] |= (prusa3d_semicolon_workaround_round ? 0xf0 : 0x0f); + } + } else { + memcpy(&buf[i], &m->buf[addr], block_size); + i += block_size; + } + buf[i++] = Sync_CRC_EOP; + stk500_send( pgm, buf, i); + + if (stk500_recv(pgm, buf, 1) < 0) + return -1; + if (buf[0] == Resp_STK_NOSYNC) { + if (tries > 33) { + avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): can't get into sync\n", + progname); + return -3; + } + if (stk500_getsync(pgm) < 0) + return -1; + goto retry; + } + else if (buf[0] != Resp_STK_INSYNC) { + avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -4; + } + + if (stk500_recv(pgm, buf, 1) < 0) + return -1; + if (buf[0] != Resp_STK_OK) { + avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): (a) protocol error, " + "expect=0x%02x, resp=0x%02x\n", + progname, Resp_STK_INSYNC, buf[0]); + return -5; } - if (stk500_getsync(pgm) < 0) - return -1; - goto retry; - } - else if (buf[0] != Resp_STK_INSYNC) { - avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): (a) protocol error, " - "expect=0x%02x, resp=0x%02x\n", - progname, Resp_STK_INSYNC, buf[0]); - return -4; - } - - if (stk500_recv(pgm, buf, 1) < 0) - return -1; - if (buf[0] != Resp_STK_OK) { - avrdude_message(MSG_INFO, "\n%s: stk500_paged_write(): (a) protocol error, " - "expect=0x%02x, resp=0x%02x\n", - progname, Resp_STK_INSYNC, buf[0]); - return -5; } } @@ -893,11 +918,15 @@ static int stk500_paged_load(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m, tries++; stk500_loadaddr(pgm, m, addr/a_div); buf[0] = Cmnd_STK_READ_PAGE; - buf[1] = (block_size >> 8) & 0xff; - buf[2] = block_size & 0xff; - buf[3] = memtype; - buf[4] = Sync_CRC_EOP; - stk500_send(pgm, buf, 5); + // Workaround for the infamous ';' bug in the Prusa3D usb to serial converter. + // Send the binary data by nibbles to avoid transmitting the ';' character. + buf[1] = (block_size >> 8) & 0xf0; + buf[2] = (block_size >> 8) & 0x0f; + buf[3] = block_size & 0xf0; + buf[4] = block_size & 0x0f; + buf[5] = memtype; + buf[6] = Sync_CRC_EOP; + stk500_send(pgm, buf, 7); if (stk500_recv(pgm, buf, 1) < 0) return -1; diff --git a/xs/src/slic3r/GUI/FirmwareDialog.cpp b/xs/src/slic3r/GUI/FirmwareDialog.cpp index bbb00e445..136b17af6 100644 --- a/xs/src/slic3r/GUI/FirmwareDialog.cpp +++ b/xs/src/slic3r/GUI/FirmwareDialog.cpp @@ -171,11 +171,19 @@ void FirmwareDialog::priv::perform_upload() std::vector<std::string> args {{ "-v", "-p", "atmega2560", - "-c", "wiring", + // Using the "Wiring" mode to program Rambo or Einsy, using the STK500v2 protocol (not the STK500). + // The Prusa's avrdude is patched to never send semicolons inside the data packets, as the USB to serial chip + // is flashed with a buggy firmware. +// "-c", "wiring", + // Using the "Arduino" mode to program Einsy's external flash with languages, using the STK500 protocol (not the STK500v2). + // The Prusa's avrdude is patched again to never send semicolons inside the data packets. + "-c", "arduino", "-P", port, "-b", "115200", // XXX: is this ok to hardcode? "-D", + "-u", // disable safe mode "-U", (boost::format("flash:w:%1%:i") % filename_utf8.data()).str() +// "-v", "-v", "-v", "-v", "-v", // enable super verbose mode, logging each serial line exchange }}; BOOST_LOG_TRIVIAL(info) << "Invoking avrdude, arguments: " @@ -192,6 +200,8 @@ void FirmwareDialog::priv::perform_upload() .args(args) .on_run([]() { /* TODO: needed? */ }) .on_message(std::move([q](const char *msg, unsigned /* size */) { + // Debugging output to console, useful when avrdude is executed in a super verbose mode (with -v -v -v). + // printf("%s", msg); auto evt = new wxCommandEvent(EVT_AVRDUDE, q->GetId()); auto wxmsg = wxString::FromUTF8(msg); evt->SetExtraLong(AE_MESSAGE); |