Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/prusa3d/PrusaSlicer.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbubnikv <bubnikv@gmail.com>2018-07-16 18:07:49 +0300
committerbubnikv <bubnikv@gmail.com>2018-07-16 18:07:49 +0300
commit6dc1bf5c08b7935dfbc55d35dea31148d09732f8 (patch)
tree862e4d4149e6cd7fceb03208c3f3bcbfa1625301 /xs/src/avrdude
parent0bbd1dbc4f80ee4909f84d91931c13d757ba0af7 (diff)
parentd99b484ac6e67f00666530a1d7b78e7506e2ce6c (diff)
Merge branch 'master' into stable
Diffstat (limited to 'xs/src/avrdude')
-rw-r--r--xs/src/avrdude/arduino.c56
-rw-r--r--xs/src/avrdude/avrdude-slic3r.cpp48
-rw-r--r--xs/src/avrdude/avrdude-slic3r.hpp23
-rw-r--r--xs/src/avrdude/avrpart.c10
-rw-r--r--xs/src/avrdude/fileio.c69
-rw-r--r--xs/src/avrdude/libavrdude.h7
-rw-r--r--xs/src/avrdude/main.c4
-rw-r--r--xs/src/avrdude/ser_posix.c4
-rw-r--r--xs/src/avrdude/stk500.c123
-rw-r--r--xs/src/avrdude/stk500v2.c17
-rw-r--r--xs/src/avrdude/update.c37
11 files changed, 286 insertions, 112 deletions
diff --git a/xs/src/avrdude/arduino.c b/xs/src/avrdude/arduino.c
index 566f56abd..5a9cb465e 100644
--- a/xs/src/avrdude/arduino.c
+++ b/xs/src/avrdude/arduino.c
@@ -80,6 +80,49 @@ static int arduino_read_sig_bytes(PROGRAMMER * pgm, AVRPART * p, AVRMEM * m)
return 3;
}
+static int prusa_init_external_flash(PROGRAMMER * pgm)
+{
+ // Note: send/receive as in _the firmare_ send & receives
+ const char entry_magic_send [] = "start\n";
+ const char entry_magic_receive[] = "w25x20cl_enter\n";
+ const char entry_magic_cfm [] = "w25x20cl_cfm\n";
+ const size_t buffer_len = 32; // Should be large enough for the above messages
+
+ int res;
+ size_t recv_size;
+ char *buffer = alloca(buffer_len);
+
+ // 1. receive the "start" command
+ recv_size = sizeof(entry_magic_send) - 1;
+ res = serial_recv(&pgm->fd, buffer, recv_size);
+ if (res < 0) {
+ avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname);
+ return -1;
+ } else if (strncmp(buffer, entry_magic_send, recv_size) != 0) {
+ avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect start code: `%*s`\n", progname, recv_size, buffer);
+ return -1;
+ }
+
+ // 2. Send the external flash programmer enter command
+ if (serial_send(&pgm->fd, entry_magic_receive, sizeof(entry_magic_receive) - 1) < 0) {
+ avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): Failed to send command to the printer\n",progname);
+ return -1;
+ }
+
+ // 3. Receive the entry confirmation command
+ recv_size = sizeof(entry_magic_cfm) - 1;
+ res = serial_recv(&pgm->fd, buffer, recv_size);
+ if (res < 0) {
+ avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer did not boot up on time or serial communication failed\n", progname);
+ return -1;
+ } else if (strncmp(buffer, entry_magic_cfm, recv_size) != 0) {
+ avrdude_message(MSG_INFO, "%s: prusa_init_external_flash(): MK3 printer emitted incorrect cfm code: `%*s`\n", progname, recv_size, buffer);
+ return -1;
+ }
+
+ return 0;
+}
+
static int arduino_open(PROGRAMMER * pgm, char * port)
{
union pinfo pinfo;
@@ -97,11 +140,24 @@ static int arduino_open(PROGRAMMER * pgm, char * port)
serial_set_dtr_rts(&pgm->fd, 1);
usleep(50*1000);
+ // Sometimes there may be line noise generating input on the printer's USB-to-serial IC
+ // Here we try to clean its input buffer with a sequence of newlines (a minimum of 9 is needed):
+ const char cleanup_newlines[] = "\n\n\n\n\n\n\n\n\n\n";
+ if (serial_send(&pgm->fd, cleanup_newlines, sizeof(cleanup_newlines) - 1) < 0) {
+ return -1;
+ }
+
/*
* drain any extraneous input
*/
stk500_drain(pgm, 0);
+ // Initialization sequence for programming the external FLASH on the Prusa MK3
+ if (prusa_init_external_flash(pgm) < 0) {
+ avrdude_message(MSG_INFO, "%s: arduino_open(): Failed to initialize MK3 external flash programming mode\n", progname);
+ return -1;
+ }
+
if (stk500_getsync(pgm) < 0)
return -1;
diff --git a/xs/src/avrdude/avrdude-slic3r.cpp b/xs/src/avrdude/avrdude-slic3r.cpp
index a859200fb..030353413 100644
--- a/xs/src/avrdude/avrdude-slic3r.cpp
+++ b/xs/src/avrdude/avrdude-slic3r.cpp
@@ -1,5 +1,6 @@
#include "avrdude-slic3r.hpp"
+#include <deque>
#include <thread>
extern "C" {
@@ -33,17 +34,22 @@ static void avrdude_progress_handler_closure(const char *task, unsigned progress
struct AvrDude::priv
{
std::string sys_config;
- std::vector<std::string> args;
+ std::deque<std::vector<std::string>> args;
+ size_t current_args_set = 0;
+ RunFn run_fn;
MessageFn message_fn;
ProgressFn progress_fn;
CompleteFn complete_fn;
std::thread avrdude_thread;
+ priv(std::string &&sys_config) : sys_config(sys_config) {}
+
+ int run_one(const std::vector<std::string> &args);
int run();
};
-int AvrDude::priv::run() {
+int AvrDude::priv::run_one(const std::vector<std::string> &args) {
std::vector<char*> c_args {{ const_cast<char*>(PACKAGE_NAME) }};
for (const auto &arg : args) {
c_args.push_back(const_cast<char*>(arg.data()));
@@ -68,10 +74,22 @@ int AvrDude::priv::run() {
return res;
}
+int AvrDude::priv::run() {
+ for (; args.size() > 0; current_args_set++) {
+ int res = run_one(args.front());
+ args.pop_front();
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ return 0;
+}
+
// Public
-AvrDude::AvrDude() : p(new priv()) {}
+AvrDude::AvrDude(std::string sys_config) : p(new priv(std::move(sys_config))) {}
AvrDude::AvrDude(AvrDude &&other) : p(std::move(other.p)) {}
@@ -82,15 +100,15 @@ AvrDude::~AvrDude()
}
}
-AvrDude& AvrDude::sys_config(std::string sys_config)
+AvrDude& AvrDude::push_args(std::vector<std::string> args)
{
- if (p) { p->sys_config = std::move(sys_config); }
+ if (p) { p->args.push_back(std::move(args)); }
return *this;
}
-AvrDude& AvrDude::args(std::vector<std::string> args)
+AvrDude& AvrDude::on_run(RunFn fn)
{
- if (p) { p->args = std::move(args); }
+ if (p) { p->run_fn = std::move(fn); }
return *this;
}
@@ -123,11 +141,17 @@ AvrDude::Ptr AvrDude::run()
if (self->p) {
auto avrdude_thread = std::thread([self]() {
- auto res = self->p->run();
- if (self->p->complete_fn) {
- self->p->complete_fn(res);
- }
- });
+ if (self->p->run_fn) {
+ self->p->run_fn();
+ }
+
+ auto res = self->p->run();
+
+ if (self->p->complete_fn) {
+ self->p->complete_fn(res, self->p->current_args_set);
+ }
+ });
+
self->p->avrdude_thread = std::move(avrdude_thread);
}
diff --git a/xs/src/avrdude/avrdude-slic3r.hpp b/xs/src/avrdude/avrdude-slic3r.hpp
index 8d881b094..273aa2378 100644
--- a/xs/src/avrdude/avrdude-slic3r.hpp
+++ b/xs/src/avrdude/avrdude-slic3r.hpp
@@ -12,22 +12,28 @@ class AvrDude
{
public:
typedef std::shared_ptr<AvrDude> Ptr;
+ typedef std::function<void()> RunFn;
typedef std::function<void(const char * /* msg */, unsigned /* size */)> MessageFn;
typedef std::function<void(const char * /* task */, unsigned /* progress */)> ProgressFn;
- typedef std::function<void(int /* exit status */)> CompleteFn;
+ typedef std::function<void(int /* exit status */, size_t /* args_id */)> CompleteFn;
- AvrDude();
+ // Main c-tor, sys_config is the location of avrdude's main configuration file
+ AvrDude(std::string sys_config);
AvrDude(AvrDude &&);
AvrDude(const AvrDude &) = delete;
AvrDude &operator=(AvrDude &&) = delete;
AvrDude &operator=(const AvrDude &) = delete;
~AvrDude();
- // Set location of avrdude's main configuration file
- AvrDude& sys_config(std::string sys_config);
+ // Push a set of avrdude cli arguments
+ // Each set makes one avrdude invocation - use this method multiple times to push
+ // more than one avrdude invocations.
+ AvrDude& push_args(std::vector<std::string> args);
- // Set avrdude cli arguments
- AvrDude& args(std::vector<std::string> args);
+ // Set a callback to be called just after run() before avrdude is ran
+ // This can be used to perform any needed setup tasks from the background thread.
+ // This has no effect when using run_sync().
+ AvrDude& on_run(RunFn fn);
// Set message output callback
AvrDude& on_message(MessageFn fn);
@@ -36,7 +42,10 @@ public:
// Progress is reported per each task (reading / writing) in percents.
AvrDude& on_progress(ProgressFn fn);
- // Called when avrdude's main function finishes
+ // Called when the last avrdude invocation finishes with the exit status of zero,
+ // or earlier, if one of the invocations return a non-zero status.
+ // The second argument contains the sequential id of the last avrdude invocation argument set.
+ // This has no effect when using run_sync().
AvrDude& on_complete(CompleteFn fn);
int run_sync();
diff --git a/xs/src/avrdude/avrpart.c b/xs/src/avrdude/avrpart.c
index 621a85b98..b04851ac1 100644
--- a/xs/src/avrdude/avrpart.c
+++ b/xs/src/avrdude/avrpart.c
@@ -378,7 +378,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type,
char * optr;
if (m == NULL) {
- fprintf(f,
+ avrdude_message(MSG_INFO,
"%s Block Poll Page Polled\n"
"%sMemory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
"%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
@@ -386,13 +386,13 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type,
}
else {
if (verbose > 2) {
- fprintf(f,
+ avrdude_message(MSG_INFO,
"%s Block Poll Page Polled\n"
"%sMemory Type Mode Delay Size Indx Paged Size Size #Pages MinW MaxW ReadBack\n"
"%s----------- ---- ----- ----- ---- ------ ------ ---- ------ ----- ----- ---------\n",
prefix, prefix, prefix);
}
- fprintf(f,
+ avrdude_message(MSG_INFO,
"%s%-11s %4d %5d %5d %4d %-6s %6d %4d %6d %5d %5d 0x%02x 0x%02x\n",
prefix, m->desc, m->mode, m->delay, m->blocksize, m->pollindex,
m->paged ? "yes" : "no",
@@ -415,7 +415,7 @@ void avr_mem_display(const char * prefix, FILE * f, AVRMEM * m, int type,
optr = avr_op_str(i);
else
optr = " ";
- fprintf(f,
+ avrdude_message(MSG_INFO,
"%s %-11s %8d %8s %5d %5d\n",
prefix, optr, j,
bittype(m->op[i]->bit[j].type),
@@ -620,7 +620,7 @@ void avr_display(FILE * f, AVRPART * p, const char * prefix, int verbose)
LNODEID ln;
AVRMEM * m;
- fprintf(f,
+ avrdude_message(MSG_INFO,
"%sAVR Part : %s\n"
"%sChip Erase delay : %d us\n"
"%sPAGEL : P%02X\n"
diff --git a/xs/src/avrdude/fileio.c b/xs/src/avrdude/fileio.c
index f2d617823..aa57f5587 100644
--- a/xs/src/avrdude/fileio.c
+++ b/xs/src/avrdude/fileio.c
@@ -45,6 +45,8 @@
#define MAX_LINE_LEN 256 /* max line length for ASCII format input files */
+#define MAX_MODE_LEN 32 // For fopen_and_seek()
+
struct ihexrec {
unsigned char reclen;
@@ -96,8 +98,40 @@ static int fileio_num(struct fioparms * fio,
char * filename, FILE * f, AVRMEM * mem, int size,
FILEFMT fmt);
-static int fmt_autodetect(char * fname);
+static int fmt_autodetect(char * fname, size_t offset);
+
+
+
+static FILE *fopen_and_seek(const char *filename, const char *mode, size_t offset)
+{
+ FILE *file;
+ // On Windows we need to convert the filename to UTF-16
+#if defined(WIN32NATIVE)
+ static wchar_t fname_buffer[PATH_MAX];
+ static wchar_t mode_buffer[MAX_MODE_LEN];
+
+ if (MultiByteToWideChar(CP_UTF8, 0, filename, -1, fname_buffer, PATH_MAX) == 0) { return NULL; }
+ if (MultiByteToWideChar(CP_ACP, 0, mode, -1, mode_buffer, MAX_MODE_LEN) == 0) { return NULL; }
+
+ file = _wfopen(fname_buffer, mode_buffer);
+#else
+ file = fopen(filename, mode);
+#endif
+
+ if (file != NULL) {
+ // Some systems allow seeking past the end of file, so we need check for that first and disallow
+ if (fseek(file, 0, SEEK_END) != 0
+ || offset >= ftell(file)
+ || fseek(file, offset, SEEK_SET) != 0
+ ) {
+ fclose(file);
+ file = NULL;
+ errno = EINVAL;
+ }
+ }
+ return file;
+}
char * fmtstr(FILEFMT format)
@@ -1358,7 +1392,7 @@ int fileio_setparms(int op, struct fioparms * fp,
-static int fmt_autodetect(char * fname)
+static int fmt_autodetect(char * fname, size_t offset)
{
FILE * f;
unsigned char buf[MAX_LINE_LEN];
@@ -1368,10 +1402,11 @@ static int fmt_autodetect(char * fname)
int first = 1;
#if defined(WIN32NATIVE)
- f = fopen(fname, "r");
+ f = fopen_and_seek(fname, "r", offset);
#else
- f = fopen(fname, "rb");
+ f = fopen_and_seek(fname, "rb", offset);
#endif
+
if (f == NULL) {
avrdude_message(MSG_INFO, "%s: error opening %s: %s\n",
progname, fname, strerror(errno));
@@ -1445,7 +1480,7 @@ static int fmt_autodetect(char * fname)
int fileio(int op, char * filename, FILEFMT format,
- struct avrpart * p, char * memtype, int size)
+ struct avrpart * p, char * memtype, int size, size_t offset)
{
int rc;
FILE * f;
@@ -1477,15 +1512,17 @@ int fileio(int op, char * filename, FILEFMT format,
using_stdio = 0;
if (strcmp(filename, "-")==0) {
- if (fio.op == FIO_READ) {
- fname = "<stdin>";
- f = stdin;
- }
- else {
- fname = "<stdout>";
- f = stdout;
- }
- using_stdio = 1;
+ return -1;
+ // Note: we don't want to read stdin or write to stdout as part of Slic3r
+ // if (fio.op == FIO_READ) {
+ // fname = "<stdin>";
+ // f = stdin;
+ // }
+ // else {
+ // fname = "<stdout>";
+ // f = stdout;
+ // }
+ // using_stdio = 1;
}
else {
fname = filename;
@@ -1502,7 +1539,7 @@ int fileio(int op, char * filename, FILEFMT format,
return -1;
}
- format_detect = fmt_autodetect(fname);
+ format_detect = fmt_autodetect(fname, offset);
if (format_detect < 0) {
avrdude_message(MSG_INFO, "%s: can't determine file format for %s, specify explicitly\n",
progname, fname);
@@ -1533,7 +1570,7 @@ int fileio(int op, char * filename, FILEFMT format,
if (format != FMT_IMM) {
if (!using_stdio) {
- f = fopen(fname, fio.mode);
+ f = fopen_and_seek(fname, fio.mode, offset);
if (f == NULL) {
avrdude_message(MSG_INFO, "%s: can't open %s file %s: %s\n",
progname, fio.iodesc, fname, strerror(errno));
diff --git a/xs/src/avrdude/libavrdude.h b/xs/src/avrdude/libavrdude.h
index e8197f9c2..536f1a2f7 100644
--- a/xs/src/avrdude/libavrdude.h
+++ b/xs/src/avrdude/libavrdude.h
@@ -737,7 +737,7 @@ extern bool cancel_flag;
#define RETURN_IF_CANCEL() \
do { \
if (cancel_flag) { \
- avrdude_message(MSG_INFO, "%s(): Cancelled, exiting...\n", __func__); \
+ avrdude_message(MSG_INFO, "avrdude: %s(): Cancelled, exiting...\n", __func__); \
return -99; \
} \
} while (0)
@@ -821,7 +821,7 @@ extern "C" {
char * fmtstr(FILEFMT format);
int fileio(int op, char * filename, FILEFMT format,
- struct avrpart * p, char * memtype, int size);
+ struct avrpart * p, char * memtype, int size, size_t offset);
#ifdef __cplusplus
}
@@ -870,6 +870,7 @@ enum updateflags {
typedef struct update_t {
char * memtype;
int op;
+ size_t offset;
char * filename;
int format;
} UPDATE;
@@ -881,7 +882,7 @@ extern "C" {
extern UPDATE * parse_op(char * s);
extern UPDATE * dup_update(UPDATE * upd);
extern UPDATE * new_update(int op, char * memtype, int filefmt,
- char * filename);
+ char * filename, size_t offset);
extern void free_update(UPDATE * upd);
extern int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd,
enum updateflags flags);
diff --git a/xs/src/avrdude/main.c b/xs/src/avrdude/main.c
index 0550ceff1..d4c34fe44 100644
--- a/xs/src/avrdude/main.c
+++ b/xs/src/avrdude/main.c
@@ -194,7 +194,7 @@ static void usage(void)
" -F Override invalid signature check.\n"
" -e Perform a chip erase.\n"
" -O Perform RC oscillator calibration (see AVR053). \n"
- " -U <memtype>:r|w|v:<filename>[:format]\n"
+ " -U <memtype>:r|w|v:<offset>:<filename>[:format]\n"
" Memory operation specification.\n"
" Multiple -U options are allowed, each request\n"
" is performed in the order specified.\n"
@@ -374,7 +374,7 @@ static void list_parts(FILE * f, const char *prefix, LISTID avrparts)
static int cleanup_main(int status)
{
- if (pgm_setup && pgm->teardown) {
+ if (pgm_setup && pgm != NULL && pgm->teardown) {
pgm->teardown(pgm);
}
diff --git a/xs/src/avrdude/ser_posix.c b/xs/src/avrdude/ser_posix.c
index 91b18e945..cb0fc0385 100644
--- a/xs/src/avrdude/ser_posix.c
+++ b/xs/src/avrdude/ser_posix.c
@@ -376,6 +376,10 @@ static int ser_recv(union filedescriptor *fd, unsigned char * buf, size_t buflen
FD_SET(fd->ifd, &rfds);
nfds = select(fd->ifd + 1, &rfds, NULL, NULL, &to2);
+ // FIXME: The timeout has different behaviour on Linux vs other Unices
+ // On Linux, the timeout is modified by subtracting the time spent,
+ // on OS X (for example), it is not modified.
+ // POSIX recommends re-initializing it before selecting.
if (nfds == 0) {
avrdude_message(MSG_NOTICE2, "%s: ser_recv(): programmer is not responding\n",
progname);
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/avrdude/stk500v2.c b/xs/src/avrdude/stk500v2.c
index d3acb639c..4d62640c0 100644
--- a/xs/src/avrdude/stk500v2.c
+++ b/xs/src/avrdude/stk500v2.c
@@ -79,7 +79,7 @@
#define SERIAL_TIMEOUT 2
// Retry count
-#define RETRIES 5
+#define RETRIES 0
#if 0
#define DEBUG(...) avrdude_message(MSG_INFO, __VA_ARGS__)
@@ -745,7 +745,7 @@ static int stk500v2_recv(PROGRAMMER * pgm, unsigned char *msg, size_t maxsize) {
-static int stk500v2_getsync_internal(PROGRAMMER * pgm, int retries) {
+int stk500v2_getsync(PROGRAMMER * pgm) {
int tries = 0;
unsigned char buf[1], resp[32];
int status;
@@ -804,7 +804,7 @@ retry:
progname, pgmname[PDATA(pgm)->pgmtype]);
return 0;
} else {
- if (tries > retries) {
+ if (tries > RETRIES) {
avrdude_message(MSG_INFO, "%s: stk500v2_getsync(): can't communicate with device: resp=0x%02x\n",
progname, resp[0]);
return -6;
@@ -814,7 +814,7 @@ retry:
// or if we got a timeout
} else if (status == -1) {
- if (tries > retries) {
+ if (tries > RETRIES) {
avrdude_message(MSG_INFO, "%s: stk500v2_getsync(): timeout communicating with programmer\n",
progname);
return -1;
@@ -823,7 +823,7 @@ retry:
// or any other error
} else {
- if (tries > retries) {
+ if (tries > RETRIES) {
avrdude_message(MSG_INFO, "%s: stk500v2_getsync(): error communicating with programmer: (%d)\n",
progname,status);
} else
@@ -833,11 +833,6 @@ retry:
return 0;
}
-int stk500v2_getsync(PROGRAMMER * pgm) {
- // This is to avoid applying RETRIES exponentially
- return stk500v2_getsync_internal(pgm, RETRIES);
-}
-
static int stk500v2_command(PROGRAMMER * pgm, unsigned char * buf,
size_t len, size_t maxlen) {
int i;
@@ -947,7 +942,7 @@ retry:
}
// otherwise try to sync up again
- status = stk500v2_getsync_internal(pgm, 1);
+ status = stk500v2_getsync(pgm);
if (status != 0) {
if (tries > RETRIES) {
avrdude_message(MSG_INFO, "%s: stk500v2_command(): failed miserably to execute command 0x%02x\n",
diff --git a/xs/src/avrdude/update.c b/xs/src/avrdude/update.c
index a73461dfa..e9dd6e325 100644
--- a/xs/src/avrdude/update.c
+++ b/xs/src/avrdude/update.c
@@ -101,6 +101,24 @@ UPDATE * parse_op(char * s)
p++;
+ // Extension: Parse file contents offset
+ size_t offset = 0;
+
+ for (; *p != ':'; p++) {
+ if (*p >= '0' && *p <= '9') {
+ offset *= 10;
+ offset += *p - 0x30;
+ } else {
+ avrdude_message(MSG_INFO, "%s: invalid update specification: offset is not a number\n", progname);
+ free(upd->memtype);
+ free(upd);
+ return NULL;
+ }
+ }
+
+ upd->offset = offset;
+ p++;
+
/*
* Now, parse the filename component. Instead of looking for the
* leftmost possible colon delimiter, we look for the rightmost one.
@@ -176,7 +194,7 @@ UPDATE * dup_update(UPDATE * upd)
return u;
}
-UPDATE * new_update(int op, char * memtype, int filefmt, char * filename)
+UPDATE * new_update(int op, char * memtype, int filefmt, char * filename, size_t offset)
{
UPDATE * u;
@@ -190,6 +208,7 @@ UPDATE * new_update(int op, char * memtype, int filefmt, char * filename)
u->filename = strdup(filename);
u->op = op;
u->format = filefmt;
+ u->offset = offset;
return u;
}
@@ -250,7 +269,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
progname,
strcmp(upd->filename, "-")==0 ? "<stdout>" : upd->filename);
}
- rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size);
+ rc = fileio(FIO_WRITE, upd->filename, upd->format, p, upd->memtype, size, 0);
if (rc < 0) {
avrdude_message(MSG_INFO, "%s: write to file '%s' failed\n",
progname, upd->filename);
@@ -267,7 +286,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
progname,
strcmp(upd->filename, "-")==0 ? "<stdin>" : upd->filename);
}
- rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1);
+ rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset);
if (rc < 0) {
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
progname, upd->filename);
@@ -296,11 +315,11 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
report_progress(1,1,NULL);
}
else {
- /*
- * test mode, don't actually write to the chip, output the buffer
- * to stdout in intel hex instead
- */
- rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size);
+ // /*
+ // * test mode, don't actually write to the chip, output the buffer
+ // * to stdout in intel hex instead
+ // */
+ // rc = fileio(FIO_WRITE, "-", FMT_IHEX, p, upd->memtype, size, 0);
}
if (rc < 0) {
@@ -332,7 +351,7 @@ int do_op(PROGRAMMER * pgm, struct avrpart * p, UPDATE * upd, enum updateflags f
progname, mem->desc, upd->filename);
}
- rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1);
+ rc = fileio(FIO_READ, upd->filename, upd->format, p, upd->memtype, -1, upd->offset);
if (rc < 0) {
avrdude_message(MSG_INFO, "%s: read from file '%s' failed\n",
progname, upd->filename);