summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNamyoon Woo <namyoon@chromium.org>2019-03-26 15:19:24 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-04-12 14:50:00 -0700
commita256570f5fbe9605500f66aaf1b2484c09229d96 (patch)
treef312586b08b59d01bc911213d26e2c59bd0f61b6
parent985924cb008d94e811a1adf15a311e41ca9992e6 (diff)
downloadchrome-ec-a256570f5fbe9605500f66aaf1b2484c09229d96.tar.gz
stm32mon: retry on damaged ACK, NACK or timeout
BUG=b:112837404 BRANCH=None TEST=manually ran stm32mon or flash_ec on scarlet and DragonTalon. 1. stm32mon via Servo V4 type-C at 57600 bps on scarlet. $ ./util/flash_ec --board scarlet --image ${IMG} \ --bitbang_rate 57600 --verbose 2. stm32mon via Servo V4 type-C at 9600 bps on scarlet. which tends to fail for NACK or timeout. $ ./util/flash_ec --board scarlet --image ${IMG} \ --bitbang_rate 9600 --verbose 3. flash_ec via Servo Micro on scarlet $ ./util/flash_ec --board scarlet --image ${IMG} --verbose 4. flash_ec on DragonTalon via Servo V2 and Servo Micro respectively. $ ./util/flash_ec --board hatch_fp --image ${IMG} --verbose Full log can be found at http://gpaste/5439133910564864 Change-Id: I3c8e8c81d9d12475f5722eaacc932dc1244625d5 Signed-off-by: Namyoon Woo <namyoon@chromium.org> Reviewed-on: https://chromium-review.googlesource.com/1540496 Commit-Ready: ChromeOS CL Exonerator Bot <chromiumos-cl-exonerator@appspot.gserviceaccount.com> Reviewed-by: Matthew Blecker <matthewb@chromium.org>
-rw-r--r--util/stm32mon.c379
1 files changed, 253 insertions, 126 deletions
diff --git a/util/stm32mon.c b/util/stm32mon.c
index 601a53238e..05788b9189 100644
--- a/util/stm32mon.c
+++ b/util/stm32mon.c
@@ -20,6 +20,7 @@
#define _BSD_SOURCE /* Older glibc */
#include <arpa/inet.h>
+#include <compile_time_macros.h>
#include <errno.h>
#include <fcntl.h>
#include <getopt.h>
@@ -63,9 +64,10 @@
#define CMD_RP 0x82 /* Enables the read protection */
#define CMD_RU 0x92 /* Disables the read protection */
-#define RESP_NACK 0x1f
-#define RESP_ACK 0x79
-#define RESP_BUSY 0x76
+#define RESP_NACK 0x1f
+#define RESP_ACK 0x79 /* 0b 0111 1001 */
+#define RESP_BUSY 0x76
+#define RESP_DAMAGED_ACK 0xBC /* 0b 1011 1100, 1 bit shifted REST_ACK */
/* SPI Start of Frame */
#define SOF 0x5A
@@ -204,6 +206,8 @@ struct stm32_def {
#define DEFAULT_BAUDRATE B38400
#define PAGE_SIZE 256
#define INVALID_I2C_ADAPTER -1
+#define MAX_ACK_RETRY_COUNT (EXT_ERASE_TIMEOUT / DEFAULT_TIMEOUT)
+#define MAX_RETRY_COUNT 3
enum interface_mode {
MODE_SERIAL,
@@ -227,6 +231,20 @@ const char *serial_port = "/dev/ttyUSB1";
const char *input_filename;
const char *output_filename;
uint32_t offset = 0x08000000, length = 0;
+int retry_on_damaged_ack;
+
+/* STM32MON function return values */
+enum {
+ STM32_SUCCESS = 0,
+ STM32_EIO = -1, /* IO error */
+ STM32_EINVAL = -2, /* Got a faulty response from device */
+ STM32_ETIMEDOUT = -3, /* Device didn't respond in a time window. */
+ STM32_ENOMEM = -4, /* Failed to allocate memory. */
+ STM32_ENACK = -5, /* Got NACK. */
+ STM32_EDACK = -6, /* Got a damanged ACK. */
+};
+BUILD_ASSERT(STM32_SUCCESS == 0);
+#define IS_STM32_ERROR(res) ((res) < STM32_SUCCESS)
/* optional command flags */
enum {
@@ -257,6 +275,29 @@ static void discard_input(int);
/* On user request save all data exchange with the target in this log file. */
static FILE *log_file;
+/* Statistic data structure for response kind. */
+struct {
+ const char * const event_name;
+ uint32_t event_count;
+} stat_resp[] = {
+ { "RESP_ACK", 0 },
+ { "RESP_NACK", 0 },
+ { "RESP_BUSY", 0 },
+ { "RESP_DAMAGED_ACK", 0 },
+ { "JUNK", 0 },
+};
+
+enum {
+ RESP_ACK_IDX = 0,
+ RESP_NACK_IDX,
+ RESP_BUSY_IDX,
+ RESP_DAMAGED_ACK_IDX,
+ JUNK_IDX,
+ MAX_EVENT_IDX
+};
+
+BUILD_ASSERT(ARRAY_SIZE(stat_resp) == MAX_EVENT_IDX);
+
/*
* Print data into the log file, in hex, 16 bytes per line, prefix the first
* line with the value supplied by the caller (usually 'r' or 'w' for
@@ -305,6 +346,7 @@ static ssize_t write_wrapper(int fd, const void *buf, size_t count)
return rv;
}
+
int open_serial(const char *port, int cr50_mode)
{
int fd, res;
@@ -472,39 +514,62 @@ int wait_for_ack(int fd)
uint8_t resp;
int res;
time_t deadline = time(NULL) + DEFAULT_TIMEOUT;
- uint8_t ack = RESP_ACK;
+ const uint8_t ack = RESP_ACK;
while (time(NULL) < deadline) {
res = read_wrapper(fd, &resp, 1);
if ((res < 0) && (errno != EAGAIN)) {
perror("Failed to read answer");
- return -EIO;
+ return STM32_EIO;
}
- if (res == 1) {
- if (resp == RESP_ACK) {
- if (mode == MODE_SPI) /* Ack the ACK */
- if (write_wrapper(fd, &ack, 1) != 1)
- return -EIO;
- return 0;
- } else if (resp == RESP_NACK) {
- fprintf(stderr, "NACK\n");
- if (mode == MODE_SPI) /* Ack the NACK */
- if (write_wrapper(fd, &ack, 1) != 1)
- return -EIO;
- discard_input(fd);
- return -EINVAL;
- } else if (resp == RESP_BUSY) {
- /* I2C Boot protocol 1.1 */
- deadline = time(NULL) + DEFAULT_TIMEOUT;
- } else {
- if (mode == MODE_SERIAL)
- fprintf(stderr, "Receive junk: %02x\n",
- resp);
+
+ if (res != 1)
+ continue;
+
+ switch (resp) {
+ case RESP_ACK:
+ stat_resp[RESP_ACK_IDX].event_count++;
+ if (mode == MODE_SPI) /* Ack the ACK */
+ if (write_wrapper(fd, &ack, 1) != 1)
+ return STM32_EIO;
+ return STM32_SUCCESS;
+
+ case RESP_NACK:
+ stat_resp[RESP_NACK_IDX].event_count++;
+ fprintf(stderr, "NACK\n");
+ if (mode == MODE_SPI) /* Ack the NACK */
+ if (write_wrapper(fd, &ack, 1) != 1)
+ return STM32_EIO;
+ discard_input(fd);
+ return STM32_ENACK;
+
+ case RESP_BUSY:
+ stat_resp[RESP_BUSY_IDX].event_count++;
+ /* I2C Boot protocol 1.1 */
+ deadline = time(NULL) + DEFAULT_TIMEOUT;
+ break;
+
+ case RESP_DAMAGED_ACK:
+ if (retry_on_damaged_ack) {
+ /* It is a damaged ACK. However, device is
+ * likely to believe it sent ACK, so let's not
+ * treat it as junk.
+ */
+ stat_resp[RESP_DAMAGED_ACK_IDX].event_count++;
+ fprintf(stderr, "DAMAGED_ACK\n");
+ return STM32_EDACK;
}
+
+ /* Do not break so that it can be handled as junk */
+ default:
+ stat_resp[JUNK_IDX].event_count++;
+ if (mode == MODE_SERIAL)
+ fprintf(stderr, "Receive junk: %02x\n", resp);
+ break;
}
}
fprintf(stderr, "Timeout\n");
- return -ETIMEDOUT;
+ return STM32_ETIMEDOUT;
}
int send_command(int fd, uint8_t cmd, payload_t *loads, int cnt,
@@ -516,19 +581,23 @@ int send_command(int fd, uint8_t cmd, payload_t *loads, int cnt,
uint8_t cmd_frame[] = { SOF, cmd, 0xff ^ cmd }; /* XOR checksum */
/* only the SPI mode needs the Start Of Frame byte */
int cmd_off = mode == MODE_SPI ? 0 : 1;
+ int count_damaged_ack = 0;
/* Send the command index */
res = write_wrapper(fd, cmd_frame + cmd_off,
sizeof(cmd_frame) - cmd_off);
if (res <= 0) {
perror("Failed to write command frame");
- return -1;
+ return STM32_EIO;
}
/* Wait for the ACK */
- if (wait_for_ack(fd) < 0) {
+ res = wait_for_ack(fd);
+ if (res == STM32_EDACK) {
+ ++count_damaged_ack;
+ } else if (IS_STM32_ERROR(res)) {
fprintf(stderr, "Failed to get command 0x%02x ACK\n", cmd);
- return -1;
+ return res;
}
/* Send the command payloads */
@@ -540,7 +609,7 @@ int send_command(int fd, uint8_t cmd, payload_t *loads, int cnt,
if (data == NULL) {
fprintf(stderr,
"Failed to allocate memory for load %d\n", c);
- return -ENOMEM;
+ return STM32_ENOMEM;
}
memcpy(data, p->data, size);
for (i = 0; i < size; i++)
@@ -555,35 +624,36 @@ int send_command(int fd, uint8_t cmd, payload_t *loads, int cnt,
if (res < 0) {
perror("Failed to write command payload");
free(data);
- return -1;
+ return STM32_EIO;
}
size -= res;
data_ptr += res;
}
+ free(data);
/* Wait for the ACK */
res = wait_for_ack(fd);
- if (res < 0) {
- if (res != -ETIMEDOUT)
+ if (res == STM32_EDACK) {
+ ++count_damaged_ack;
+ } else if (IS_STM32_ERROR(res)) {
+ if (res != STM32_ETIMEDOUT)
fprintf(stderr,
"payload %d ACK failed for CMD%02x\n",
c, cmd);
- free(data);
return res;
}
- free(data);
}
/* Read the answer payload */
if (resp) {
if (mode == MODE_SPI) /* ignore dummy byte */
if (read_wrapper(fd, resp, 1) < 0)
- return -1;
+ return STM32_EIO;
while ((resp_size > 0) &&
(res = read_wrapper(fd, resp, resp_size))) {
if (res < 0) {
perror("Failed to read payload");
- return -1;
+ return STM32_EIO;
}
readcnt += res;
resp += res;
@@ -592,17 +662,48 @@ int send_command(int fd, uint8_t cmd, payload_t *loads, int cnt,
/* Wait for the ACK */
if (ack_requested) {
- if (wait_for_ack(fd) < 0) {
+ res = wait_for_ack(fd);
+ if (res == STM32_EDACK) {
+ ++count_damaged_ack;
+ } else if (IS_STM32_ERROR(res)) {
fprintf(stderr,
- "Failed to get response to command 0x%02x ACK\n",
- cmd);
- return -1;
+ "Failed to get response to command"
+ " 0x%02x ACK\n", cmd);
+ return res;
}
}
}
+
+ if (count_damaged_ack)
+ return STM32_EDACK;
+
return readcnt;
}
+int send_command_retry(int fd, uint8_t cmd, payload_t *loads,
+ int cnt, uint8_t *resp, int resp_size, int ack_requested)
+{
+ int res;
+ int retries = MAX_RETRY_COUNT;
+
+ do {
+ int ack_tries = MAX_ACK_RETRY_COUNT;
+
+ res = send_command(fd, cmd, loads, cnt, resp, resp_size,
+ ack_requested);
+
+ while (res == STM32_ETIMEDOUT && ack_tries--) {
+ if (cmd == CMD_WRITEMEM) {
+ /* send garbage byte */
+ write_wrapper(fd, loads->data, 1);
+ }
+ res = wait_for_ack(fd);
+ }
+ } while ((res == STM32_ENACK || res == STM32_EDACK) && retries--);
+
+ return res;
+}
+
struct stm32_def *command_get_id(int fd)
{
int res;
@@ -637,7 +738,7 @@ int init_monitor(int fd)
/* Skip in i2c mode */
if (mode == MODE_I2C)
- return 0;
+ return STM32_SUCCESS;
printf("Waiting for the monitor startup ...");
fflush(stdout);
@@ -647,23 +748,23 @@ int init_monitor(int fd)
res = write_wrapper(fd, &init, 1);
if (res <= 0) {
perror("Failed to write command");
- return -1;
+ return STM32_EIO;
}
/* Wait for the ACK */
res = wait_for_ack(fd);
- if (res == 0)
+ if (res == STM32_SUCCESS)
break;
- if (res == -EINVAL) {
+ if (res == STM32_ENACK) {
/* we got NACK'ed, the loader might be already started
* let's ping it to check
*/
if (command_get_id(fd)) {
printf("Monitor already started.\n");
- return 0;
+ return STM32_SUCCESS;
}
}
- if (res < 0 && res != -ETIMEDOUT)
- return -1;
+ if (IS_STM32_ERROR(res) && res != STM32_ETIMEDOUT)
+ return res;
fflush(stdout);
}
printf("Done.\n");
@@ -671,7 +772,7 @@ int init_monitor(int fd)
/* read trailing chars */
discard_input(fd);
- return 0;
+ return STM32_SUCCESS;
}
int command_get_commands(int fd, struct stm32_def *chip)
@@ -688,7 +789,7 @@ int command_get_commands(int fd, struct stm32_def *chip)
if (cmds[0] > sizeof(cmds) - 2) {
fprintf(stderr, "invalid GET answer (%02x...)\n",
cmds[0]);
- return -1;
+ return STM32_EINVAL;
}
printf("Bootloader v%d.%d, commands : ",
cmds[1] >> 4, cmds[1] & 0xf);
@@ -705,11 +806,11 @@ int command_get_commands(int fd, struct stm32_def *chip)
erase = command_erase_i2c;
printf("\n");
- return 0;
+ return STM32_SUCCESS;
}
fprintf(stderr, "Cannot get bootloader command list.\n");
- return -1;
+ return STM32_EINVAL;
}
static int use_progressbar;
@@ -729,6 +830,7 @@ static void draw_spinner(uint32_t remaining, uint32_t size)
printf("\r%c%3d%%", wheel[windex++], percent);
windex %= sizeof(wheel);
}
+ fflush(stdout);
}
int command_read_mem(int fd, uint32_t address, uint32_t size, uint8_t *buffer)
@@ -743,18 +845,21 @@ int command_read_mem(int fd, uint32_t address, uint32_t size, uint8_t *buffer)
};
while (remaining) {
- cnt = (remaining > PAGE_SIZE) ? PAGE_SIZE - 1 : remaining - 1;
+ uint32_t bytes = MIN(remaining, PAGE_SIZE);
+
+ cnt = (uint8_t) (bytes - 1);
addr_be = htonl(address);
draw_spinner(remaining, size);
- fflush(stdout);
- res = send_command(fd, CMD_READMEM, loads, 2, buffer, cnt + 1,
- 0);
- if (res < 0)
- return -EIO;
- buffer += cnt + 1;
- address += cnt + 1;
- remaining -= cnt + 1;
+
+ res = send_command_retry(fd, CMD_READMEM, loads, 2, buffer,
+ bytes, 0);
+ if (IS_STM32_ERROR(res))
+ return STM32_EIO;
+
+ buffer += bytes;
+ address += bytes;
+ remaining -= bytes;
}
return size;
@@ -774,7 +879,7 @@ int command_write_mem(int fd, uint32_t address, uint32_t size, uint8_t *buffer)
};
while (remaining) {
- cnt = (remaining > PAGE_SIZE) ? PAGE_SIZE : remaining;
+ cnt = MIN(remaining, PAGE_SIZE);
/* skip empty blocks to save time */
for (i = 0; i < cnt && buffer[i] == 0xff; i++)
;
@@ -785,11 +890,11 @@ int command_write_mem(int fd, uint32_t address, uint32_t size, uint8_t *buffer)
memcpy(outbuf + 1, buffer, cnt);
draw_spinner(remaining, size);
- fflush(stdout);
- res = send_command(fd, CMD_WRITEMEM, loads, 2,
+
+ res = send_command_retry(fd, CMD_WRITEMEM, loads, 2,
NULL, 0, 1);
- if (res < 0)
- return -EIO;
+ if (IS_STM32_ERROR(res))
+ return STM32_EIO;
}
buffer += cnt;
address += cnt;
@@ -805,7 +910,6 @@ int command_ext_erase(int fd, uint16_t count, uint16_t start)
uint16_t count_be = htons(count);
payload_t load = { 2, (uint8_t *)&count_be };
uint16_t *pages = NULL;
- int retries = EXT_ERASE_TIMEOUT / DEFAULT_TIMEOUT;
if (count < 0xfff0) {
int i;
@@ -813,7 +917,7 @@ int command_ext_erase(int fd, uint16_t count, uint16_t start)
load.size = 2 * (count + 1);
pages = malloc(load.size);
if (!pages)
- return -ENOMEM;
+ return STM32_ENOMEM;
load.data = (uint8_t *)pages;
pages[0] = htons(count - 1);
for (i = 0; i < count; i++)
@@ -821,11 +925,8 @@ int command_ext_erase(int fd, uint16_t count, uint16_t start)
}
printf("Erasing...\n");
- res = send_command(fd, CMD_EXTERASE, &load, 1, NULL, 0, 1);
- /* Erase can take long time (e.g. 13s+ on STM32H7) */
- while ((res == -ETIMEDOUT) && --retries)
- res = wait_for_ack(fd);
- if (res >= 0)
+ res = send_command_retry(fd, CMD_EXTERASE, &load, 1, NULL, 0, 1);
+ if (!IS_STM32_ERROR(res))
printf("Flash erased.\n");
if (pages)
@@ -857,20 +958,19 @@ int command_erase_i2c(int fd, uint16_t count, uint16_t start)
load[1].size = 2 * count;
pages = malloc(load[1].size);
if (!pages)
- return -ENOMEM;
+ return STM32_ENOMEM;
load[1].data = (uint8_t *)pages;
count_be = htons(count - 1);
for (i = 0; i < count; i++)
pages[i] = htons(start + i);
- } else {
- load_cnt = 1;
}
- erase_cmd = (boot_loader_version == 0x10 ? CMD_EXTERASE :
- CMD_NO_STRETCH_ERASE);
- res = send_command(fd, erase_cmd, load, load_cnt,
- NULL, 0, 1);
- if (res >= 0)
+ erase_cmd = (boot_loader_version == 0x10) ? CMD_EXTERASE :
+ CMD_NO_STRETCH_ERASE;
+
+ printf("Erasing...\n");
+ res = send_command(fd, erase_cmd, load, load_cnt, NULL, 0, 1);
+ if (!IS_STM32_ERROR(res))
printf("Flash erased.\n");
if (pages)
@@ -892,15 +992,16 @@ int command_erase(int fd, uint16_t count, uint16_t start)
load.size = count + 1;
pages = malloc(load.size);
if (!pages)
- return -ENOMEM;
+ return STM32_ENOMEM;
load.data = (uint8_t *)pages;
pages[0] = count - 1;
for (i = 0; i < count; i++)
pages[i+1] = start + i;
}
+ printf("Erasing...\n");
res = send_command(fd, CMD_ERASE, &load, 1, NULL, 0, 1);
- if (res >= 0)
+ if (!IS_STM32_ERROR(res))
printf("Flash erased.\n");
if (pages)
@@ -911,7 +1012,7 @@ int command_erase(int fd, uint16_t count, uint16_t start)
int command_read_unprotect(int fd)
{
int res;
- int retries = EXT_ERASE_TIMEOUT / DEFAULT_TIMEOUT;
+ int retries = MAX_RETRY_COUNT;
printf("Unprotecting flash read...\n");
@@ -922,9 +1023,9 @@ int command_read_unprotect(int fd)
*/
do {
res = wait_for_ack(fd);
- } while ((res == -ETIMEDOUT) && --retries);
+ } while ((res == STM32_ETIMEDOUT) && --retries);
- if (res < 0) {
+ if (IS_STM32_ERROR(res)) {
fprintf(stderr, "Failed to get read-protect ACK\n");
return res;
}
@@ -939,10 +1040,10 @@ int command_read_unprotect(int fd)
usleep(MAX_DELAY_REBOOT);
if (init_monitor(fd) < 0) {
fprintf(stderr, "Cannot recover after RU reset\n");
- return -EIO;
+ return STM32_EIO;
}
- return 0;
+ return STM32_SUCCESS;
}
int command_write_unprotect(int fd)
@@ -950,13 +1051,13 @@ int command_write_unprotect(int fd)
int res;
res = send_command(fd, CMD_WU, NULL, 0, NULL, 0, 1);
- if (res < 0)
- return -EIO;
+ if (IS_STM32_ERROR(res))
+ return STM32_EIO;
/* Wait for the ACK */
if (wait_for_ack(fd) < 0) {
fprintf(stderr, "Failed to get write-protect ACK\n");
- return -EINVAL;
+ return STM32_EINVAL;
}
printf("Flash write unprotected.\n");
@@ -969,10 +1070,10 @@ int command_write_unprotect(int fd)
usleep(MAX_DELAY_REBOOT);
if (init_monitor(fd) < 0) {
fprintf(stderr, "Cannot recover after WP reset\n");
- return -EIO;
+ return STM32_EIO;
}
- return 0;
+ return STM32_SUCCESS;
}
int command_go(int fd, uint32_t address)
@@ -982,8 +1083,8 @@ int command_go(int fd, uint32_t address)
payload_t load = { 4, (uint8_t *)&addr_be };
res = send_command(fd, CMD_GO, &load, 1, NULL, 0, 1);
- if (res < 0)
- return -EIO;
+ if (IS_STM32_ERROR(res))
+ return STM32_EIO;
#if 0 /* this ACK should exist according to the documentation ... */
/* Wait for the ACK */
@@ -994,7 +1095,7 @@ int command_go(int fd, uint32_t address)
#endif
printf("Program started at 0x%08x.\n", address);
- return 0;
+ return STM32_SUCCESS;
}
/*
@@ -1031,13 +1132,13 @@ int read_device_signature_register(int fd, const struct stm32_def *chip,
if (!otp.addr) {
fprintf(stderr, "No otp_area.addr specified for given chip.\n");
- return -EINVAL;
+ return STM32_EINVAL;
}
if (addr <= otp_end_addr) {
fprintf(stderr, "Attempting to read from invalid address: "
"%08X\n", addr);
- return -EINVAL;
+ return STM32_EINVAL;
}
/*
@@ -1052,14 +1153,14 @@ int read_device_signature_register(int fd, const struct stm32_def *chip,
fprintf(stderr,
"Requested register 0x%08X is outside read range.\n",
addr);
- return -EINVAL;
+ return STM32_EINVAL;
}
buffer = malloc(read_size_bytes);
if (!buffer) {
fprintf(stderr, "Cannot allocate %" PRIu32 " bytes\n",
read_size_bytes);
- return -ENOMEM;
+ return STM32_ENOMEM;
}
res = command_read_mem(fd, otp_end_addr, read_size_bytes, buffer);
@@ -1071,7 +1172,7 @@ int read_device_signature_register(int fd, const struct stm32_def *chip,
read_size_bytes, otp_end_addr);
free(buffer);
- return (res < 0) ? res : 0;
+ return IS_STM32_ERROR(res) ? res : STM32_SUCCESS;
}
/* Return zero on success, a negative error value on failures. */
@@ -1082,13 +1183,13 @@ int read_flash_size_register(int fd, struct stm32_def *chip,
uint32_t flash_size_addr = chip->device_signature.flash_size_addr;
if (!flash_size_addr)
- return -EINVAL;
+ return STM32_EINVAL;
res = read_device_signature_register(fd, chip,
flash_size_addr, sizeof(*flash_size_kbytes),
(uint8_t *)flash_size_kbytes);
- if (!res)
+ if (!IS_STM32_ERROR(res))
printf("Flash size: %" PRIu16 " KB\n", *flash_size_kbytes);
else
fprintf(stderr,
@@ -1108,12 +1209,12 @@ int read_unique_device_id_register(int fd, struct stm32_def *chip,
chip->device_signature.unique_device_id_addr;
if (!unique_device_id_addr)
- return -EINVAL;
+ return STM32_EINVAL;
res = read_device_signature_register(fd, chip, unique_device_id_addr,
STM32_UNIQUE_ID_SIZE_BYTES, device_id);
- if (!res) {
+ if (!IS_STM32_ERROR(res)) {
printf("Unique Device ID: 0x");
for (i = STM32_UNIQUE_ID_SIZE_BYTES - 1; i >= 0; i--)
printf("%02X", device_id[i]);
@@ -1136,13 +1237,13 @@ int read_package_data_register(int fd, struct stm32_def *chip,
uint32_t package_data_addr = chip->device_signature.package_data_addr;
if (!package_data_addr)
- return -EINVAL;
+ return STM32_EINVAL;
res = read_device_signature_register(fd, chip, package_data_addr,
sizeof(*package_data),
(uint8_t *)package_data);
- if (!res)
+ if (!IS_STM32_ERROR(res))
printf("Package data register: %04X\n", *package_data);
else
fprintf(stderr,
@@ -1165,14 +1266,14 @@ int read_flash(int fd, struct stm32_def *chip, const char *filename,
buffer = malloc(size);
if (!buffer) {
fprintf(stderr, "Cannot allocate %d bytes\n", size);
- return -ENOMEM;
+ return STM32_ENOMEM;
}
hnd = fopen(filename, "w");
if (!hnd) {
fprintf(stderr, "Cannot open file %s for writing\n", filename);
free(buffer);
- return -EIO;
+ return STM32_EIO;
}
printf("Reading %d bytes at 0x%08x\n", size, offset);
@@ -1185,7 +1286,7 @@ int read_flash(int fd, struct stm32_def *chip, const char *filename,
fclose(hnd);
free(buffer);
- return (res < 0) ? res : 0;
+ return IS_STM32_ERROR(res) ? res : STM32_SUCCESS;
}
/* Return zero on success, a negative error value on failures. */
@@ -1199,7 +1300,7 @@ int write_flash(int fd, struct stm32_def *chip, const char *filename,
if (!buffer) {
fprintf(stderr, "Cannot allocate %d bytes\n", size);
- return -ENOMEM;
+ return STM32_ENOMEM;
}
if (!strncmp(filename, "-", sizeof("-")))
@@ -1209,16 +1310,15 @@ int write_flash(int fd, struct stm32_def *chip, const char *filename,
if (!hnd) {
fprintf(stderr, "Cannot open file %s for reading\n", filename);
free(buffer);
- return -EIO;
+ return STM32_EIO;
}
res = fread(buffer, 1, size, hnd);
+ fclose(hnd);
if (res <= 0) {
fprintf(stderr, "Cannot read %s\n", filename);
free(buffer);
- fclose(hnd);
- return -EIO;
+ return STM32_EIO;
}
- fclose(hnd);
/* faster write: skip empty trailing space */
while (res && buffer[res - 1] == 0xff)
@@ -1231,12 +1331,12 @@ int write_flash(int fd, struct stm32_def *chip, const char *filename,
if (written != res) {
fprintf(stderr, "Error writing to flash\n");
free(buffer);
- return -EIO;
+ return STM32_EIO;
}
- printf("\rDone.\n");
+ printf("\r %d bytes written.\n", written);
free(buffer);
- return 0;
+ return STM32_SUCCESS;
}
static const struct option longopts[] = {
@@ -1397,11 +1497,25 @@ int parse_parameters(int argc, char **argv)
return flags;
}
+static void display_stat_response(void)
+{
+ uint32_t total_events = MAX_EVENT_IDX;
+ uint32_t idx;
+
+ printf("--\n");
+ for (idx = 0; idx < total_events; ++idx) {
+ printf("%-18s %d\n", stat_resp[idx].event_name,
+ stat_resp[idx].event_count);
+ }
+ printf("--\n");
+}
+
int main(int argc, char **argv)
{
int ser;
struct stm32_def *chip;
- int ret = 1;
+ int ret = STM32_EIO;
+ int res;
int flags;
uint16_t flash_size_kbytes = 0;
uint8_t unique_device_id[STM32_UNIQUE_ID_SIZE_BYTES] = { 0 };
@@ -1410,6 +1524,8 @@ int main(int argc, char **argv)
/* Parse command line options */
flags = parse_parameters(argc, argv);
+ retry_on_damaged_ack = !!(flags & FLAG_CR50_MODE);
+
switch (mode) {
case MODE_SPI:
ser = open_spi(spi_adapter);
@@ -1437,7 +1553,8 @@ int main(int argc, char **argv)
* have the same chip ID, but different flash sizes based on the
* package.
*/
- if (!read_flash_size_register(ser, chip, &flash_size_kbytes))
+ res = read_flash_size_register(ser, chip, &flash_size_kbytes);
+ if (!IS_STM32_ERROR(res))
chip->flash_size = flash_size_kbytes * KBYTES_TO_BYTES;
/*
@@ -1468,25 +1585,25 @@ int main(int argc, char **argv)
for (i = 0; i < page_count; i += 128) {
int count = MIN(128, page_count - i);
ret = erase(ser, count, i);
- if (ret)
+ if (IS_STM32_ERROR(ret))
goto terminate;
}
} else {
ret = erase(ser, 0xFFFF, 0);
- if (ret)
+ if (IS_STM32_ERROR(ret))
goto terminate;
}
}
if (input_filename) {
ret = read_flash(ser, chip, input_filename, offset, length);
- if (ret)
+ if (IS_STM32_ERROR(ret))
goto terminate;
}
if (output_filename) {
ret = write_flash(ser, chip, output_filename, offset);
- if (ret)
+ if (IS_STM32_ERROR(ret))
goto terminate;
}
@@ -1495,12 +1612,22 @@ int main(int argc, char **argv)
command_go(ser, offset);
/* Normal exit */
- ret = 0;
+ ret = STM32_SUCCESS;
terminate:
if (log_file)
fclose(log_file);
/* Close serial port */
close(ser);
- return ret;
+
+ if (retry_on_damaged_ack)
+ display_stat_response();
+
+ if (IS_STM32_ERROR(ret)) {
+ fprintf(stderr, "Failed: %d\n", ret);
+ return 1;
+ }
+
+ printf("Done.\n");
+ return 0;
}