diff options
-rw-r--r-- | raiden_debug_spi.c | 50 |
1 files changed, 42 insertions, 8 deletions
diff --git a/raiden_debug_spi.c b/raiden_debug_spi.c index 08f8928b..1f30b6a2 100644 --- a/raiden_debug_spi.c +++ b/raiden_debug_spi.c @@ -133,6 +133,16 @@ enum raiden_debug_spi_request { #define PAYLOAD_SIZE (MAX_PACKET_SIZE - PACKET_HEADER_SIZE) /* + * Servo Micro has an error where it is capable of acknowledging USB packets + * without loading it into the USB endpoint buffers or triggering interrupts. + * See crbug.com/952494. Retry mechanisms have been implemented to recover + * from these rare failures allowing the process to continue. + */ +#define WRITE_RETY_ATTEMPTS (3) +#define READ_RETY_ATTEMPTS (3) +#define RETY_INTERVAL_US (100 * 1000) + +/* * This timeout is so large because the Raiden SPI timeout is 800ms. */ #define TRANSFER_TIMEOUT_MS (200 + 800) @@ -245,16 +255,40 @@ static int send_command(struct flashctx *flash, { int status = -1; - status = write_command(flash, write_count, read_count, - write_buffer, read_buffer); - - if (status) { - return status; - } + for (int write_attempt = 0; write_attempt < WRITE_RETY_ATTEMPTS; + write_attempt++) { - status = read_response(flash, write_count, read_count, - write_buffer, read_buffer); + status = write_command(flash, write_count, read_count, + write_buffer, read_buffer); + if (status) { + /* Write operation failed. */ + msg_perr("Raiden: Write command failed\n" + "Write attempt = %d\n" + "status = %d\n", + write_attempt + 1, status); + programmer_delay(RETY_INTERVAL_US); + continue; + } + for (int read_attempt = 0; read_attempt < READ_RETY_ATTEMPTS; read_attempt++) { + + status = read_response(flash, write_count, read_count, + write_buffer, read_buffer); + + if (status != 0) { + /* Read operation failed. */ + msg_perr("Raiden: Read response failed\n" + "Write attempt = %d\n" + "Read attempt = %d\n" + "status = %d\n", + write_attempt + 1, read_attempt + 1, status); + programmer_delay(RETY_INTERVAL_US); + } else { + /* We were successful at performing the SPI transfer. */ + return status; + } + } + } return status; } |