From b6422f3a7aa7f4f5d64636b2297ec87e896e7c2c Mon Sep 17 00:00:00 2001 From: Frank Hunleth Date: Tue, 17 Nov 2020 15:11:18 -0500 Subject: [PATCH] Retry waking up ATECC on unexpected response The original code had intentions of retrying the wake up processor, but it never used it. I.e., the default number of retries was 1. This changes the default to 4 and adds a 500 ms wait in between tries. The logic for this is that wakeup errors can happen for many reasons especially since it's possible for other programs to access to ATECC simultaneously. This is definitely a problem with OpenSSL engines since they're independent of this library. The strategy for this library is to minimize calls to the ATECC via caching of responses to read-only data, but it still happens and retries are needed. 4 retries separated by 500 ms was picked since 1. it's still well under the 5 second default Erlang timer on calls, so function calls shouldn't time out, and 2. 500 ms is longer than most ATECC ops, so there's a good change that whatever conflicted is done. --- lib/atecc508a/transport/i2c_server.ex | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/atecc508a/transport/i2c_server.ex b/lib/atecc508a/transport/i2c_server.ex index 73efcba..8b1eb8b 100644 --- a/lib/atecc508a/transport/i2c_server.ex +++ b/lib/atecc508a/transport/i2c_server.ex @@ -10,6 +10,8 @@ defmodule ATECC508A.Transport.I2CServer do @atecc508a_wake_delay_ms 2 @atecc508a_signature <<0x04, 0x11, 0x33, 0x43>> @atecc508a_poll_interval_ms 2 + @atecc508a_retry_wakeup_ms 500 + @atecc508a_default_wakeup_retries 4 @spec start_link(keyword()) :: :ignore | {:error, any()} | {:ok, pid()} def start_link([bus_name, address, process_name]) do @@ -164,7 +166,7 @@ defmodule ATECC508A.Transport.I2CServer do end end - defp wakeup(i2c, address, retries \\ 1) + defp wakeup(i2c, address, retries \\ @atecc508a_default_wakeup_retries) defp wakeup(_i2c, _address, 0) do {:error, :unexpected_wakeup_response} @@ -188,10 +190,12 @@ defmodule ATECC508A.Transport.I2CServer do :ok {:ok, something_else} -> - _ = sleep(i2c, address) - - Logger.warn("Unexpected wakeup response: #{inspect(something_else)}. Retrying.") + Logger.warn( + "Unexpected wakeup response: #{inspect(something_else)}. #{retries - 1} retries remaining." + ) + Process.sleep(@atecc508a_retry_wakeup_ms) + _ = sleep(i2c, address) wakeup(i2c, address, retries - 1) error ->