summaryrefslogtreecommitdiff
path: root/util/stm32mon.c
diff options
context:
space:
mode:
Diffstat (limited to 'util/stm32mon.c')
-rw-r--r--util/stm32mon.c83
1 files changed, 66 insertions, 17 deletions
diff --git a/util/stm32mon.c b/util/stm32mon.c
index e6c76f9a62..e8dd908f23 100644
--- a/util/stm32mon.c
+++ b/util/stm32mon.c
@@ -83,13 +83,14 @@ typedef struct {
} payload_t;
static int has_exterase;
+static void discard_input(int);
#define MIN(a, b) ((a) < (b) ? (a) : (b))
int open_serial(const char *port)
{
int fd, res;
- struct termios cfg;
+ struct termios cfg, cfg_copy;
fd = open(port, O_RDWR | O_NOCTTY);
if (fd == -1) {
@@ -106,18 +107,46 @@ int open_serial(const char *port)
}
cfmakeraw(&cfg);
cfsetspeed(&cfg, baudrate);
- /* serial mode is 8e1 */
+ /* serial mode should be 8e1 */
cfg.c_cflag |= PARENB;
/* 200 ms timeout */
cfg.c_cc[VTIME] = 2;
cfg.c_cc[VMIN] = 0;
- res = tcsetattr(fd, TCSANOW, &cfg);
- if (res == -1) {
- perror("Cannot set tty attributes");
+ memcpy(&cfg_copy, &cfg, sizeof(cfg_copy));
+
+ /*
+ * tcsetattr() returns success if any of the modifications succeed, so
+ * its return value of zero is not an indication of success, one needs
+ * to check the result explicitely.
+ */
+ tcsetattr(fd, TCSANOW, &cfg);
+ if (tcgetattr(fd, &cfg)) {
+ perror("Failed to re-read tty attributes");
close(fd);
return -1;
}
+ if (memcmp(&cfg, &cfg_copy, sizeof(cfg))) {
+ /*
+ * On some systems the setting which does not come through is
+ * the parity. We can try continuing without it when using
+ * certain interfaces, let's try.
+ */
+ cfg_copy.c_cflag &= ~PARENB;
+ if (memcmp(&cfg, &cfg_copy, sizeof(cfg))) {
+ /*
+ * Something other than parity failed to get set, this
+ * is an error.
+ */
+ perror("Cannot set tty attributes");
+ close(fd);
+ return -1;
+ } else {
+ fprintf(stderr, "Failed to enable parity\n");
+ }
+ }
+
+ discard_input(fd); /* in case were were invoked soon after reset */
return fd;
}
@@ -303,7 +332,6 @@ int init_monitor(int fd)
}
if (res < 0 && res != -ETIMEDOUT)
return -1;
- printf(".");
fflush(stdout);
}
printf("Done.\n");
@@ -341,6 +369,14 @@ int command_get_commands(int fd)
return -1;
}
+static int windex;
+static const char wheel[] = {'|', '/', '-', '\\' };
+static void draw_spinner(void)
+{
+ printf("%c%c", 8, wheel[windex++]);
+ windex %= sizeof(wheel);
+}
+
int command_read_mem(int fd, uint32_t address, uint32_t size, uint8_t *buffer)
{
int res;
@@ -356,7 +392,7 @@ int command_read_mem(int fd, uint32_t address, uint32_t size, uint8_t *buffer)
cnt = (remaining > PAGE_SIZE) ? PAGE_SIZE - 1 : remaining - 1;
addr_be = htonl(address);
- printf(".");
+ draw_spinner();
fflush(stdout);
res = send_command(fd, CMD_READMEM, loads, 2, buffer, cnt + 1);
if (res < 0)
@@ -389,7 +425,7 @@ int command_write_mem(int fd, uint32_t address, uint32_t size, uint8_t *buffer)
loads[1].size = cnt + 1;
memcpy(outbuf + 1, buffer, cnt);
- printf(".");
+ draw_spinner();
fflush(stdout);
res = send_command(fd, CMD_WRITEMEM, loads, 2, NULL, 0);
if (res < 0)
@@ -531,6 +567,7 @@ int command_go(int fd, uint32_t address)
return 0;
}
+/* Return zero on success, a negative error value on failures. */
int read_flash(int fd, struct stm32_def *chip, const char *filename,
uint32_t offset, uint32_t size)
{
@@ -553,7 +590,7 @@ int read_flash(int fd, struct stm32_def *chip, const char *filename,
if (!size)
size = chip->flash_size;
offset += chip->flash_start;
- printf("Reading %d bytes at 0x%08x ", size, offset);
+ printf("Reading %d bytes at 0x%08x ", size, offset);
res = command_read_mem(fd, offset, size, buffer);
if (res > 0) {
if (fwrite(buffer, res, 1, hnd) != 1)
@@ -563,9 +600,10 @@ int read_flash(int fd, struct stm32_def *chip, const char *filename,
fclose(hnd);
free(buffer);
- return res;
+ return (res < 0) ? res : 0;
}
+/* Return zero on success, a negative error value on failures. */
int write_flash(int fd, struct stm32_def *chip, const char *filename,
uint32_t offset)
{
@@ -587,19 +625,23 @@ int write_flash(int fd, struct stm32_def *chip, const char *filename,
}
if ((res = fread(buffer, 1, size, hnd)) <= 0) {
fprintf(stderr, "Cannot read %s\n", filename);
+ free(buffer);
return -EIO;
}
fclose(hnd);
offset += chip->flash_start;
- printf("Writing %d bytes at 0x%08x ", res, offset);
+ printf("Writing %d bytes at 0x%08x ", res, offset);
written = command_write_mem(fd, offset, res, buffer);
- if (written != res)
+ if (written != res) {
fprintf(stderr, "Error writing to flash\n");
+ free(buffer);
+ return -EIO;
+ }
printf("Done.\n");
free(buffer);
- return written;
+ return 0;
}
static const struct option longopts[] = {
@@ -739,11 +781,18 @@ int main(int argc, char **argv)
}
}
- if (input_filename)
- read_flash(ser, chip, input_filename, 0, chip->flash_size);
+ if (input_filename) {
+ ret = read_flash(ser, chip, input_filename,
+ 0, chip->flash_size);
+ if (ret)
+ goto terminate;
+ }
- if (output_filename)
- write_flash(ser, chip, output_filename, 0);
+ if (output_filename) {
+ ret = write_flash(ser, chip, output_filename, 0);
+ if (ret)
+ goto terminate;
+ }
/* Run the program from flash */
if (flags & FLAG_GO)