Example #1
0
        /// <summary>
        /// Asynchronously updates the firmware of the Harp device on the specified port.
        /// </summary>
        /// <param name="portName">The name of the serial port used to communicate with the Harp device.</param>
        /// <param name="firmware">The binary firmware image to upload to the device.</param>
        /// <param name="forceUpdate">
        /// <b>true</b> to indicate that the firmware should be uploaded even if the device reports unsupported hardware,
        /// or is in bootloader mode; <b>false</b> to throw an exception if the firmware is not supported, or the device
        /// is in an invalid state.
        /// </param>
        /// <param name="progress">The optional <see cref="IProgress{Int32}"/> object used to report update progress.</param>
        /// <returns>
        /// The task object representing the asynchronous firmware update operation.
        /// </returns>
        public static async Task UpdateFirmwareAsync(string portName, DeviceFirmware firmware, bool forceUpdate, IProgress <int> progress = default)
        {
            var flushDelay = TimeSpan.FromMilliseconds(FlushDelayMilliseconds);

            using (var device = new AsyncDevice(portName))
            {
                try
                {
                    var hardwareVersion = await device.ReadHardwareVersionAsync().WithTimeout(FlushDelayMilliseconds);

                    var deviceName = await device.ReadDeviceNameAsync().WithTimeout(FlushDelayMilliseconds);

                    if (!firmware.Metadata.Supports(deviceName, hardwareVersion) && !forceUpdate)
                    {
                        throw new ArgumentException("The specified firmware is not supported.", nameof(firmware));
                    }

                    const byte BootEeprom   = 0x80;
                    const byte BootDefault  = 0x40;
                    const byte ResetDefault = 0x1;
                    const byte ResetEeprom  = 0x2;
                    var        reset        = await device.ReadByteAsync(Registers.Reset);

                    if ((reset & BootEeprom) != 0)
                    {
                        await device.WriteByteAsync(Registers.Reset, ResetEeprom);
                    }
                    else if ((reset & BootDefault) != 0)
                    {
                        await device.WriteByteAsync(Registers.Reset, ResetDefault);
                    }
                    else
                    {
                        throw new HarpException("The device is in an unexpected boot mode.");
                    }
                    await Observable.Timer(flushDelay);

                    progress?.Report(20);
                }
                catch (TimeoutException)
                {
                    if (!forceUpdate)
                    {
                        throw;
                    }
                }
            }

            const int DefaultBaudRate = 1000000;

            using (var bootloader = new SerialPort(portName, DefaultBaudRate, Parity.None, 8, StopBits.One))
            {
                bootloader.Handshake = Handshake.None;
                bootloader.Open();
                await Observable.Timer(flushDelay);

                var pageSize = await ReadPageSizeAsync(bootloader.BaseStream);

                progress?.Report(40);

                var bytesWritten = 0;
                var reportSize   = pageSize * 8;
                var dataMessage  = new byte[pageSize + HeaderSize];
                while (bytesWritten < firmware.Data.Length)
                {
                    CreateBootloaderMessage(dataMessage, WritePage, bytesWritten, firmware.Data, bytesWritten, pageSize);
                    await BootloaderCommandAsync(bootloader.BaseStream, dataMessage);

                    bytesWritten += pageSize;
                    if (bytesWritten % reportSize == 0)
                    {
                        progress?.Report(40 + bytesWritten * 50 / firmware.Data.Length);
                    }
                }

                progress?.Report(90);
                CreateBootloaderMessage(dataMessage, ExitBootloader, 0, firmware.Data, 0, pageSize);
                await BootloaderCommandAsync(bootloader.BaseStream, dataMessage);

                progress?.Report(100);
            };
        }
Example #2
0
 /// <summary>
 /// Asynchronously updates the firmware of the Harp device on the specified port.
 /// </summary>
 /// <param name="portName">The name of the serial port used to communicate with the Harp device.</param>
 /// <param name="firmware">The binary firmware image to upload to the device.</param>
 /// <param name="progress">The optional <see cref="IProgress{Int32}"/> object used to report update progress.</param>
 /// <returns>
 /// The task object representing the asynchronous firmware update operation.
 /// </returns>
 public static Task UpdateFirmwareAsync(string portName, DeviceFirmware firmware, IProgress <int> progress = default)
 {
     return(UpdateFirmwareAsync(portName, firmware, forceUpdate: false, progress: progress));
 }