From 158fcca200a0499aecdefd61d7a8c5b7b5e5ef78 Mon Sep 17 00:00:00 2001 From: Diego Escalona Date: Tue, 15 Oct 2024 14:01:38 +0200 Subject: [PATCH] gpm: fix an issue during the 'Verify and install' firmware step - If the connection with the device is Bluetooth, the device could be reset without receiving an ACK when the install firmware API packet is issued on the write characterisitic. This causes an exception different than the expected in the 'Verify and install' firmware step, making the overall process to fail. - Issue the 'Verify and install' packet in first instance and send the 'Verify' packet only if the previous one fails and the cause is not a timeout waiting for the answer. Signed-off-by: Diego Escalona --- XBeeLibrary.Core/Models/GpmManager.cs | 43 +++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/XBeeLibrary.Core/Models/GpmManager.cs b/XBeeLibrary.Core/Models/GpmManager.cs index 4439084..3f87971 100644 --- a/XBeeLibrary.Core/Models/GpmManager.cs +++ b/XBeeLibrary.Core/Models/GpmManager.cs @@ -20,6 +20,7 @@ using System.IO; using System.Linq; using System.Threading; +using System.Threading.Tasks; using XBeeLibrary.Core.Events; using XBeeLibrary.Core.Exceptions; using XBeeLibrary.Core.Packet; @@ -59,6 +60,7 @@ public class GpmManager private static readonly string ERROR_VERIFY_INSTALL_ERROR_PROCESS = "Image transferred to device is not valid."; private static readonly string ERROR_PLATFORM_INFO_ERROR_PROCESS = "An error occurred getting the platform information."; private static readonly string ERROR_NO_MODEM_RESET = "No modem reset frame detected after {0} seconds."; + private static readonly string ERROR_PREFIX_TIMEOUT = "timeout"; public static readonly string TASK_GET_PLATFORM_INFO = "Getting platform info"; public static readonly string TASK_ERASE = "Erasing flash"; @@ -157,10 +159,33 @@ public void UpdateFirmware() TransferFirmware(pageSize); // Step 5: Verify and install the transferred firmware image. - VerifyFlashImage(); - VerifyAndInstallFlashImage(); + try + { + VerifyAndInstallFlashImage(); + } + catch (GpmException e) + { + // The image could be correct on the target device. So, verify it + // and retry the install. + if (!e.Message.Contains(ERROR_RX_TIMEOUT)) + { + VerifyFlashImage(); + VerifyAndInstallFlashImage(); + } + else + { + // A timeout exception means that the device rebooted to install the firmware, + // which is expected. + // TODO: This should just return, or return a boolean (true). The code calling + // this method should not be checking the type of exception thrown to + // determine if the update was success or not. + throw e; + } + } - // Step 6: Wait for the device to reboot after the firmware update. + // Step 6: Wait for the device to reboot after the firmware update. In Bluetooth this + // step is never reached as the BLE connection is lost when the device is reset + // to install the firmware. WaitForDeviceToUpgrade(); logger.Info("Device firmware updated successfully"); @@ -440,6 +465,18 @@ private void VerifyAndInstallFlashImage() (byte)BROADCAST_RADIUS_MAXIMUM, (byte)TRANSMIT_OPTIONS_NONE, verifyAndInstallPayload); // Send the packet. string errorString = SendGPMAPIPacket(verifyInstallPacket, timeout); + // When the connection with the device is via Bluetooth, the device could reset before + // receiving the ACK for the write characteristic. This causes a timeout when writing to + // the TX characteristic. The firmware is being applied, but we need to wait some time + // for it to start and make the firmware update process think there was a timeout waiting + // for the GPM response, which would be the expected behavior. + if (errorString != null + && errorString.ToLower().StartsWith(ERROR_PREFIX_TIMEOUT) + && !errorString.Equals(ERROR_RX_TIMEOUT)) + { + Task.Delay(timeout).Wait(); + errorString = ERROR_RX_TIMEOUT; + } if (errorString != null) errorString = ERROR_SEND_PACKET_EXTENDED + errorString; else if (gpmAnswerPayload.Length < 8)