예제 #1
0
        /// <summary>
        /// Erases the module via a USBasp device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="eraseEeprom">Flag indicating if the EEPROM should be erased.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task <bool> EraseFlash(FlashMulti flashMulti, bool eraseEeprom)
        {
            // Path to the flashing tool, stm32flash.exe
            string command = ".\\tools\\avrdude.exe";

            // Arguments for the command line
            string commandArgs;

            // Variable to keep the return code from executed commands
            int returnCode = -1;

            // First step in flash process
            flashMulti.FlashStep = 1;

            // Avrdude command arguments
            if (eraseEeprom)
            {
                flashMulti.FlashSteps = 6;
                commandArgs           = $"-C.\\tools\\avrdude.conf -patmega328p -cusbasp -Ulock:w:{UnlockBits}:m -Uefuse:w:{ExtendedFuses}:m -Uhfuse:w:{HighFusesNoBoot}:m -Ulfuse:w:{LowFuses}:m -Uflash:w:.\\tools\\erase32.bin:a -Ueeprom:w:.\\tools\\erase1.bin:r";
            }
            else
            {
                flashMulti.FlashSteps = 4;
                commandArgs           = $"-C.\\tools\\avrdude.conf -patmega328p -cusbasp -Ulock:w:{UnlockBits}:m -Uefuse:w:{ExtendedFuses}:m -Uhfuse:w:{HighFusesNoBoot}:m -Ulfuse:w:{LowFuses}:m -Uflash:w:.\\tools\\erase32.bin:a";
            }

            // Write to the log
            flashMulti.AppendLog($"{Strings.modeErasing} {Strings.viaUSBasp}\r\n");

            // Run the command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog($"\r\n{Strings.failedtoEraseModule}");
                MessageBox.Show(Strings.failedtoEraseModule, Strings.dialogTitleErase, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return(false);
            }

            flashMulti.AppendLog($"\r\n{Strings.succeededErasing}");
            flashMulti.EnableControls(true);
            return(true);
        }
예제 #2
0
        /// <summary>
        /// Reads the firmware via a USBasp device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="firmwareFileName">The path of the file to save the firmware in.</param>
        /// <param name="eepromFilename">The path of the file to save the EEPROM in.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task <bool> ReadFlash(FlashMulti flashMulti, string firmwareFileName, string eepromFilename)
        {
            // Path to the flashing tool, stm32flash.exe
            string command = ".\\tools\\avrdude.exe";

            // Arguments for the command line
            string commandArgs = $"-C.\\tools\\avrdude.conf -patmega328p -cusbasp -Uflash:r:{firmwareFileName}:r -Ueeprom:r:{eepromFilename}:r";

            // Variable to keep the return code from executed commands
            int returnCode = -1;

            // First step in flash process
            flashMulti.FlashStep = 1;

            // Total number of steps in flash process
            flashMulti.FlashSteps = 2;

            // Write to the log
            flashMulti.AppendLog($"{Strings.modeReading} {Strings.viaUSBasp}\r\n");

            // Run the command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog($"\r\n{Strings.failedToReadModule}");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show(Strings.failedToReadModule, Strings.dialogTitleRead, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                return(false);
            }

            flashMulti.AppendLog("\r\n");
            flashMulti.EnableControls(true);
            return(true);
        }
예제 #3
0
        /// <summary>
        /// Writes the EEPROM via a USBasp device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the WWPROM file to flash.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task WriteEeprom(FlashMulti flashMulti, string fileName)
        {
            // Path to the flashing tool, stm32flash.exe
            string command = ".\\tools\\avrdude.exe";

            // Arguments for the command line - will vary at each step of the process
            string commandArgs;

            // Variable to keep the return code from executed commands
            int returnCode = -1;

            // First step in flash process
            flashMulti.FlashStep = 1;

            // Total number of steps in flash process
            flashMulti.FlashSteps = 2;

            // Avrdude command arguments
            commandArgs = $"-C.\\tools\\avrdude.conf -patmega328p -cusbasp -Ueeprom:w:{fileName}:r";

            // Write to the log
            flashMulti.AppendLog($"{Strings.modeWriting} {Strings.viaUSBasp}\r\n");

            // Run the command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.AppendLog($"\r\n{Strings.failedToWriteEeprom}");
                MessageBox.Show(Strings.failedToWriteEeprom, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                flashMulti.EnableControls(true);
                return;
            }

            flashMulti.AppendLog($"\r\n{Strings.succeededWritingEeprom}");
            MessageBox.Show(Strings.succeededWritingEeprom, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Information);
            flashMulti.EnableControls(true);
        }
예제 #4
0
        /// <summary>
        /// Writes the firmware to a Maple serial or DFU device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the file to flash.</param>
        /// <param name="comPort">The COM port where the Maple USB device can be found.</param>
        public static async void WriteFlash(FlashMulti flashMulti, string fileName, string comPort)
        {
            string command;
            string commandArgs;
            int    returnCode = -1;

            flashMulti.AppendLog("Starting Multimodule update\r\n");

            string mapleMode = MapleDevice.FindMaple().Mode;

            if (mapleMode == "USB")
            {
                flashMulti.AppendLog("Switching Multimodule into DFU mode ...");
                command     = ".\\tools\\maple-reset.exe";
                commandArgs = comPort;
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                if (returnCode != 0)
                {
                    flashMulti.EnableControls(true);
                    flashMulti.AppendLog(" failed!");
                    MessageBox.Show("Failed to get module to DFU mode.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                flashMulti.AppendLog(" done\r\n");

                // Check for a Maple DFU device
                flashMulti.AppendLog("Waiting for DFU device ...");
                bool dfuCheck = false;

                await Task.Run(() => { dfuCheck = WaitForDFU(2000); });

                if (dfuCheck)
                {
                    flashMulti.AppendLog(" got it\r\n");
                }
                else
                {
                    flashMulti.AppendLog(" failed!\r\n");
                    flashMulti.AppendLog("Attempting DFU Recovery Mode.\r\n");

                    // Show the recovery mode dialog
                    DfuRecoveryDialog recoveryDialog = new DfuRecoveryDialog(flashMulti);
                    var recoveryResult = recoveryDialog.ShowDialog();

                    // Error out if we didn't made it into recovery mode
                    if (recoveryResult != DialogResult.OK)
                    {
                        flashMulti.AppendLog("DFU Recovery Mode failed.");
                        flashMulti.EnableControls(true);
                        return;
                    }
                }
            }

            // First attempt to flash the firmware
            flashMulti.AppendLog("Writing firmware to Multimodule ...");
            command     = ".\\tools\\dfu-util.exe";
            commandArgs = string.Format("-R -a 2 -d 1EAF:0003 -D \"{0}\"", fileName, comPort);

            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            if (returnCode != 0)
            {
                // First attempt failed so we need to try bootloader recovery
                flashMulti.AppendLog(" failed!\r\n");

                flashMulti.AppendLog("Attempting DFU Recovery Mode.\r\n");

                // Show the recovery mode dialog
                DfuRecoveryDialog recoveryDialog = new DfuRecoveryDialog(flashMulti);
                var recoveryResult = recoveryDialog.ShowDialog();

                // If we made it into recovyer mode, flash the module
                if (recoveryResult == DialogResult.OK)
                {
                    // Run the recovery flash command
                    flashMulti.AppendLog("Writing firmware to Multimodule ...");
                    await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                    if (returnCode != 0)
                    {
                        flashMulti.EnableControls(true);
                        flashMulti.AppendLog(" failed!\r\n");
                        MessageBox.Show("Failed to write the firmware.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }
                else
                {
                    flashMulti.AppendLog("DFU Recovery Mode failed.");
                    flashMulti.EnableControls(true);
                    return;
                }
            }

            flashMulti.AppendLog(" done\r\n");
            flashMulti.AppendLog("\r\nMultimodule updated sucessfully");

            MessageBox.Show("Multimodule updated sucessfully.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
            flashMulti.EnableControls(true);
        }
예제 #5
0
        /// <summary>
        /// Writes the firmware to a Maple serial or DFU device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the file to flash.</param>
        /// <param name="comPort">The COM port where the Maple USB device can be found.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task WriteFlash(FlashMulti flashMulti, string fileName, string comPort)
        {
            string command;
            string commandArgs;
            int    returnCode = -1;

            flashMulti.AppendLog("Starting Multimodule update via native USB\r\n");

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor          = null;
            bool          reconnectSerialMonitor = false;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    reconnectSerialMonitor = true;
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");

                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog(string.Format("Couldn't open port {0}", comPort));
                MessageBox.Show(string.Format("Couldn't open port {0}", comPort), "Write Firmware", MessageBoxButtons.OK, MessageBoxIcon.Error);
                flashMulti.EnableControls(true);
                return;
            }

            string mapleMode = MapleDevice.FindMaple().Mode;

            if (mapleMode == "USB")
            {
                flashMulti.AppendLog("Switching Multimodule into DFU mode ...");
                command     = ".\\tools\\maple-reset.exe";
                commandArgs = comPort;
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                if (returnCode != 0)
                {
                    flashMulti.EnableControls(true);
                    flashMulti.AppendLog(" failed!");
                    MessageBox.Show("Failed to get module to DFU mode.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                flashMulti.AppendLog(" done\r\n");

                // Check for a Maple DFU device
                flashMulti.AppendLog("Waiting for DFU device ...");
                bool dfuCheck = false;

                await Task.Run(() => { dfuCheck = WaitForDFU(2000); });

                if (dfuCheck)
                {
                    flashMulti.AppendLog(" got it\r\n");
                }
                else
                {
                    flashMulti.AppendLog(" failed!\r\n");
                    flashMulti.AppendLog("Attempting DFU Recovery Mode.\r\n");

                    // Show the recovery mode dialog
                    DfuRecoveryDialog recoveryDialog = new DfuRecoveryDialog(flashMulti);
                    var recoveryResult = recoveryDialog.ShowDialog();

                    // Stop if we didn't made it into recovery mode
                    if (recoveryResult == DialogResult.Cancel)
                    {
                        flashMulti.AppendLog("DFU Recovery cancelled.");
                        flashMulti.EnableControls(true);
                        return;
                    }
                    else if (recoveryResult == DialogResult.Abort)
                    {
                        flashMulti.AppendLog("DFU Recovery failed.");
                        flashMulti.EnableControls(true);
                        return;
                    }
                }
            }

            // First attempt to flash the firmware
            flashMulti.AppendLog("Writing firmware to Multimodule ...");
            command     = ".\\tools\\dfu-util.exe";
            commandArgs = string.Format("-R -a 2 -d 1EAF:0003 -D \"{0}\"", fileName, comPort);

            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            if (returnCode != 0)
            {
                // First attempt failed so we need to try bootloader recovery
                flashMulti.AppendLog(" failed!\r\n");

                flashMulti.AppendLog("Attempting DFU Recovery Mode.\r\n");

                // Show the recovery mode dialog
                DfuRecoveryDialog recoveryDialog = new DfuRecoveryDialog(flashMulti);
                var recoveryResult = recoveryDialog.ShowDialog();

                // If we made it into recovery mode, flash the module
                if (recoveryResult == DialogResult.OK)
                {
                    // Run the recovery flash command
                    flashMulti.AppendLog("Writing firmware to Multimodule ...");
                    await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                    if (returnCode != 0)
                    {
                        flashMulti.AppendLog(" failed!\r\n");
                        MessageBox.Show("Failed to write the firmware.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        flashMulti.EnableControls(true);
                        return;
                    }
                }
                else if (recoveryResult == DialogResult.Cancel)
                {
                    flashMulti.AppendLog("DFU Recovery cancelled.");
                    flashMulti.EnableControls(true);
                    return;
                }
                else
                {
                    flashMulti.AppendLog("DFU Recovery failed.");
                    flashMulti.EnableControls(true);
                    return;
                }
            }

            flashMulti.AppendLog(" done\r\n");
            flashMulti.AppendLog("\r\nMultimodule updated sucessfully");

            // Reconnect the serial monitor
            if (serialMonitor != null && reconnectSerialMonitor)
            {
                Thread.Sleep(1000);
                serialMonitor.SerialConnect(comPort);
            }

            MessageBox.Show("Multimodule updated sucessfully.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
            flashMulti.EnableControls(true);
        }
예제 #6
0
        /// <summary>
        /// Resets the Maple USB Serial device to DFU mode.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="comPort">The COM port where the Maple USB device can be found.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task <bool> ResetToDfuMode(FlashMulti flashMulti, string comPort)
        {
            string command;
            string commandArgs;
            int    returnCode = -1;

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor = null;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");

                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog($"{Strings.failedToOpenPort} {comPort}");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show($"{Strings.failedToOpenPort} {comPort}", Strings.dialogTitleRead, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                flashMulti.EnableControls(true);
                return(false);
            }

            string mapleMode = MapleDevice.FindMaple().Mode;

            if (mapleMode == "USB")
            {
                flashMulti.AppendLog($"{Strings.progressSwitchingToDfuMode}");
                command     = ".\\tools\\maple-reset.exe";
                commandArgs = $"{comPort} 2000";
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                if (returnCode == 0)
                {
                    flashMulti.AppendLog($" {Strings.done}\r\n");
                    flashMulti.AppendVerbose(string.Empty);
                }
                else
                {
                    if (MapleDevice.FindMaple().DfuMode == false)
                    {
                        flashMulti.AppendLog($" {Strings.failed}\r\n");
                        using (new CenterWinDialog(flashMulti))
                        {
                            MessageBox.Show(Strings.failedToReadModule, Strings.dialogTitleRead, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        flashMulti.EnableControls(true);
                        return(false);
                    }
                }
            }

            return(true);
        }
예제 #7
0
        /// <summary>
        /// Upgrades the bootloader of a Maple serial or DFU device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="comPort">The COM port where the Maple USB device can be found.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task <bool> UpgradeBootloader(FlashMulti flashMulti, string comPort)
        {
            string command;
            string commandArgs;
            int    returnCode = -1;

            flashMulti.AppendLog($"{Strings.modeBootloaderUpgrade} {Strings.viaNativeUSB}\r\n");

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor = null;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");
                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog($"{Strings.failedToOpenPort} {comPort}");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show($"{Strings.failedToOpenPort} {comPort}", Strings.dialogTitleBootloaderUpgrade, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                flashMulti.EnableControls(true);
                return(false);
            }

            string mapleMode = MapleDevice.FindMaple().Mode;

            if (mapleMode == "USB")
            {
                flashMulti.AppendLog(Strings.progressSwitchingToDfuMode);
                command     = ".\\tools\\maple-reset.exe";
                commandArgs = $"{comPort} 2000";
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                if (returnCode == 0)
                {
                    flashMulti.AppendLog($" {Strings.done}\r\n");
                    flashMulti.AppendVerbose(string.Empty);
                }
                else
                {
                    if (MapleDevice.FindMaple().DfuMode == false)
                    {
                        flashMulti.AppendLog($"  {Strings.failed}\r\n");
                        using (new CenterWinDialog(flashMulti))
                        {
                            MessageBox.Show(Strings.failedToWriteBootReloader, Strings.dialogTitleBootloaderUpgrade, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        flashMulti.EnableControls(true);
                        return(false);
                    }
                }
            }

            // The bootreloader.bin file
            string fileName;

            if (Properties.Settings.Default.ErrorIfNoUSB)
            {
                fileName = ".\\tools\\bootreloader_legacy.bin";
            }
            else
            {
                fileName = ".\\tools\\bootreloader_stickydfu.bin";
            }

            // Erase the the flash
            flashMulti.AppendLog(Strings.progressWritingBootReloader);
            command     = ".\\tools\\dfu-util-multi.exe";
            commandArgs = string.Format("-a 2 -d 1EAF:0003 -D \"{0}\" -v -R", fileName, comPort);

            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            if (returnCode != 0)
            {
                // First attempt failed so we need to try bootloader recovery
                flashMulti.AppendLog($" {Strings.failed}\r\n");

                flashMulti.AppendLog($"{Strings.dfuAttemptingRecovery}\r\n");

                // Show the recovery mode dialog
                DfuRecoveryDialog recoveryDialog = new DfuRecoveryDialog(flashMulti);
                var recoveryResult = recoveryDialog.ShowDialog();

                // If we made it into recovery mode, flash the module
                if (recoveryResult == DialogResult.OK)
                {
                    // Run the recovery flash command
                    flashMulti.AppendLog(Strings.progressWritingBootReloader);
                    await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                    if (returnCode != 0)
                    {
                        flashMulti.AppendLog($" {Strings.failed}!\r\n");
                        using (new CenterWinDialog(flashMulti))
                        {
                            MessageBox.Show(Strings.failedToWriteFirmware, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        flashMulti.EnableControls(true);
                        return(false);
                    }
                }
                else if (recoveryResult == DialogResult.Cancel)
                {
                    flashMulti.AppendLog(Strings.dfuRecoveryCancelled);
                    flashMulti.EnableControls(true);
                    return(false);
                }
                else
                {
                    flashMulti.AppendLog(Strings.dfuRecoveryFailed);
                    flashMulti.EnableControls(true);
                    return(false);
                }
            }

            // Write a success message to the log
            flashMulti.AppendLog($" {Strings.done}\r\n");
            flashMulti.AppendLog($"\r\n{Strings.succeededWritingBootReloader}");

            // Re-enable the form controls
            flashMulti.EnableControls(true);

            return(true);
        }
예제 #8
0
        /// <summary>
        /// Writes the firmware to a Maple serial or DFU device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the file to flash.</param>
        /// <param name="comPort">The COM port where the Maple USB device can be found.</param>
        /// <param name="runAfterUpload">Indicates if the firmware should be run when the upload is finished.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task WriteFlash(FlashMulti flashMulti, string fileName, string comPort, bool runAfterUpload)
        {
            string command;
            string commandArgs;
            int    returnCode = -1;

            flashMulti.AppendLog($"{Strings.modeWriting} {Strings.viaNativeUSB}\r\n");

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor          = null;
            bool          reconnectSerialMonitor = false;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    reconnectSerialMonitor = true;
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");

                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog($"{Strings.failedToOpenPort} {comPort}");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show($"{Strings.failedToOpenPort} {comPort}", Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                flashMulti.EnableControls(true);
                return;
            }

            string mapleMode = MapleDevice.FindMaple().Mode;

            if (mapleMode == "USB")
            {
                flashMulti.AppendLog(Strings.progressSwitchingToDfuMode);
                command     = ".\\tools\\maple-reset.exe";
                commandArgs = $"{comPort} 2000";
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                if (returnCode == 0)
                {
                    flashMulti.AppendLog($" {Strings.done}\r\n");
                    flashMulti.AppendVerbose(string.Empty);
                }
                else
                {
                    if (MapleDevice.FindMaple().DfuMode == false)
                    {
                        flashMulti.AppendLog($" {Strings.failed}\r\n");
                        flashMulti.AppendLog($"{Strings.dfuAttemptingRecovery}\r\n");

                        // Show the recovery mode dialog
                        DfuRecoveryDialog recoveryDialog = new DfuRecoveryDialog(flashMulti);
                        var recoveryResult = recoveryDialog.ShowDialog();

                        // Stop if we didn't make it into recovery mode
                        if (recoveryResult == DialogResult.Cancel)
                        {
                            flashMulti.AppendLog(Strings.dfuRecoveryCancelled);
                            flashMulti.EnableControls(true);
                            return;
                        }
                        else if (recoveryResult == DialogResult.Abort)
                        {
                            flashMulti.AppendLog(Strings.dfuRecoveryFailed);
                            flashMulti.EnableControls(true);
                            return;
                        }
                    }
                    else
                    {
                        flashMulti.AppendLog($" {Strings.done}\r\n");
                        flashMulti.AppendVerbose(string.Empty);
                    }
                }
            }

            if (!Properties.Settings.Default.DisableFlashVerification)
            {
                // Check that the STM32 MCU supports 128KB
                flashMulti.AppendLog($"{Strings.progressCheckingFlashSize}");

                // Create a temporary file name to read into
                string tempFileName = Path.GetTempFileName();

                // Read the flash memory into a temp file
                command     = ".\\tools\\dfu-util-multi.exe";
                commandArgs = string.Format("-a 2 -d 1EAF:0003 -U \"{0}\" -v", tempFileName, comPort);
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                // If we failed we need to try DFU Recovery Mode
                if (returnCode != 0)
                {
                    // First attempt failed so we need to try bootloader recovery
                    flashMulti.AppendLog($" {Strings.failed}\r\n");

                    flashMulti.AppendLog($"{Strings.dfuAttemptingRecovery}\r\n");

                    // Show the recovery mode dialog
                    DfuRecoveryDialog recoveryDialog = new DfuRecoveryDialog(flashMulti);
                    var recoveryResult = recoveryDialog.ShowDialog();

                    // If we made it into recovery mode, flash the module
                    if (recoveryResult == DialogResult.OK)
                    {
                        // Run the recovery flash command
                        flashMulti.AppendLog(Strings.progressCheckingFlashSize);
                        await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                        if (returnCode != 0)
                        {
                            flashMulti.AppendLog($" {Strings.failed}!\r\n");
                            using (new CenterWinDialog(flashMulti))
                            {
                                MessageBox.Show(Strings.failedToWriteFirmware, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                            }

                            flashMulti.EnableControls(true);
                            return;
                        }
                    }
                    else if (recoveryResult == DialogResult.Cancel)
                    {
                        flashMulti.AppendLog(Strings.dfuRecoveryCancelled);
                        flashMulti.EnableControls(true);
                        return;
                    }
                    else
                    {
                        flashMulti.AppendLog(Strings.dfuRecoveryFailed);
                        flashMulti.EnableControls(true);
                        return;
                    }
                }

                flashMulti.AppendLog($" {Strings.done}\r\n");

                // Get the file size
                long length = new FileInfo(tempFileName).Length;

                // Compare the size of the data we read to the size we expect
                if (length < 122880)
                {
                    // Throw a message and stop
                    flashMulti.EnableControls(true);
                    using (new CenterWinDialog(flashMulti))
                    {
                        MessageBox.Show(Strings.failedToVerifyMcuFlash, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                    return;
                }
            }

            // First attempt to flash the firmware
            flashMulti.AppendLog(Strings.progressWritingFirmware);
            command     = ".\\tools\\dfu-util-multi.exe";
            commandArgs = string.Format("-a 2 -d 1EAF:0003 -D \"{0}\" -v", fileName, comPort);

            if (runAfterUpload)
            {
                commandArgs += " -R";
            }

            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            if (returnCode != 0)
            {
                // First attempt failed so we need to try bootloader recovery
                flashMulti.AppendLog($" {Strings.failed}\r\n");

                flashMulti.AppendLog($"{Strings.dfuAttemptingRecovery}\r\n");

                // Show the recovery mode dialog
                DfuRecoveryDialog recoveryDialog = new DfuRecoveryDialog(flashMulti);
                var recoveryResult = recoveryDialog.ShowDialog();

                // If we made it into recovery mode, flash the module
                if (recoveryResult == DialogResult.OK)
                {
                    // Run the recovery flash command
                    flashMulti.AppendLog(Strings.progressWritingFirmware);
                    await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                    if (returnCode != 0)
                    {
                        flashMulti.AppendLog($" {Strings.failed}!\r\n");
                        using (new CenterWinDialog(flashMulti))
                        {
                            MessageBox.Show(Strings.failedToWriteFirmware, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        flashMulti.EnableControls(true);
                        return;
                    }
                }
                else if (recoveryResult == DialogResult.Cancel)
                {
                    flashMulti.AppendLog(Strings.dfuRecoveryCancelled);
                    flashMulti.EnableControls(true);
                    return;
                }
                else
                {
                    flashMulti.AppendLog(Strings.dfuRecoveryFailed);
                    flashMulti.EnableControls(true);
                    return;
                }
            }

            flashMulti.AppendLog($" {Strings.done}\r\n");
            flashMulti.AppendLog($"\r\n{Strings.succeededWritingFirmware}");

            // Reconnect the serial monitor
            if (serialMonitor != null && reconnectSerialMonitor)
            {
                Thread.Sleep(1000);
                serialMonitor.SerialConnect(comPort);
            }

            // Re-enable the form controls
            flashMulti.EnableControls(true);

            // Show a success message box
            using (new CenterWinDialog(flashMulti))
            {
                MessageBox.Show(Strings.succeededWritingFirmware, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
예제 #9
0
        /// <summary>
        /// Reads the flash memory of a Maple USB device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the file to write to.</param>
        /// <param name="comPort">The COM port where the Maple USB device can be found.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task <bool> ReadFlash(FlashMulti flashMulti, string fileName, string comPort)
        {
            string command;
            string commandArgs;
            int    returnCode = -1;

            flashMulti.AppendLog($"{Strings.modeReading} {Strings.viaNativeUSB}\r\n");

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor          = null;
            bool          reconnectSerialMonitor = false;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    reconnectSerialMonitor = true;
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");

                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog($"{Strings.failedToOpenPort} {comPort}");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show($"{Strings.failedToOpenPort} {comPort}", Strings.dialogTitleRead, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                flashMulti.EnableControls(true);
                return(false);
            }

            string mapleMode = MapleDevice.FindMaple().Mode;

            if (mapleMode == "USB")
            {
                flashMulti.AppendLog($"{Strings.progressSwitchingToDfuMode}");
                command     = ".\\tools\\maple-reset.exe";
                commandArgs = $"{comPort} 2000";
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                if (returnCode == 0)
                {
                    flashMulti.AppendLog($" {Strings.done}\r\n");
                    flashMulti.AppendVerbose(string.Empty);
                }
                else
                {
                    if (MapleDevice.FindMaple().DfuMode == false)
                    {
                        flashMulti.AppendLog($" {Strings.failed}\r\n");
                        using (new CenterWinDialog(flashMulti))
                        {
                            MessageBox.Show(Strings.failedToReadModule, Strings.dialogTitleRead, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        flashMulti.EnableControls(true);
                        return(false);
                    }
                }
            }

            // Read the flash memory
            flashMulti.AppendLog(Strings.progressReadingFlash);
            command     = ".\\tools\\dfu-util-multi.exe";
            commandArgs = string.Format("-a 2 -d 1EAF:0003 -U \"{0}\" -v", fileName, comPort);
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            if (returnCode != 0)
            {
                flashMulti.AppendLog($" {Strings.failed}\r\n");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show(Strings.failedToReadModule, Strings.dialogTitleRead, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                flashMulti.EnableControls(true);
                return(false);
            }

            // Write a success message to the log
            flashMulti.AppendLog($" {Strings.done}\r\n\r\n");

            // Reconnect the serial monitor
            if (serialMonitor != null && reconnectSerialMonitor)
            {
                Thread.Sleep(1000);
                serialMonitor.SerialConnect(comPort);
            }

            // Re-enable the form controls
            flashMulti.EnableControls(true);

            return(true);
        }
예제 #10
0
        /// <summary>
        /// Erases the flash memory of a Maple USB device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="comPort">The COM port where the Maple USB device can be found.</param>
        /// <param name="eraseEeprom">Flag indicating if the EEPROM should be erased.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task <bool> EraseFlash(FlashMulti flashMulti, string comPort, bool eraseEeprom)
        {
            string command;
            string commandArgs;
            int    returnCode = -1;

            flashMulti.AppendLog($"{Strings.modeErasing} {Strings.viaNativeUSB}\r\n");

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor = null;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");
                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog($"{Strings.failedToOpenPort} {comPort}");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show($"{Strings.failedToOpenPort} {comPort}", Strings.dialogTitleErase, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                flashMulti.EnableControls(true);
                return(false);
            }

            string mapleMode = MapleDevice.FindMaple().Mode;

            if (mapleMode == "USB")
            {
                flashMulti.AppendLog(Strings.progressSwitchingToDfuMode);
                command     = ".\\tools\\maple-reset.exe";
                commandArgs = $"{comPort} 2000";
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                if (returnCode == 0)
                {
                    flashMulti.AppendLog($" {Strings.done}\r\n");
                    flashMulti.AppendVerbose(string.Empty);
                }
                else
                {
                    if (MapleDevice.FindMaple().DfuMode == false)
                    {
                        flashMulti.AppendLog($"  {Strings.failed}\r\n");
                        using (new CenterWinDialog(flashMulti))
                        {
                            MessageBox.Show(Strings.failedtoEraseModule, Strings.dialogTitleErase, MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }

                        flashMulti.EnableControls(true);
                        return(false);
                    }
                }
            }

            // It's not actually possible to erase a device with dfu-util so we write a file full of FF bytes.
            string fileName = string.Empty;

            if (eraseEeprom)
            {
                // 120KB file overwrites the EEPROM
                fileName = ".\\tools\\erase120.bin";
            }
            else
            {
                // 118KB file preserves the EEPROM
                fileName = ".\\tools\\erase118.bin";
            }

            // Erase the the flash
            flashMulti.AppendLog(Strings.progressErasingFlash);
            command     = ".\\tools\\dfu-util-multi.exe";
            commandArgs = string.Format("-a 2 -d 1EAF:0003 -D \"{0}\" -v", fileName, comPort);
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            if (returnCode != 0)
            {
                flashMulti.AppendLog($" {Strings.failed}\r\n");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show(Strings.failedtoEraseModule, Strings.dialogTitleErase, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                flashMulti.EnableControls(true);
                return(false);
            }

            // Write a success message to the log
            flashMulti.AppendLog($" {Strings.done}\r\n");
            flashMulti.AppendLog($"\r\n{Strings.succeededErasing}");

            // Re-enable the form controls
            flashMulti.EnableControls(true);

            return(true);
        }
예제 #11
0
        /// <summary>
        /// Writes the firmware to a serial device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the file to flash.</param>
        /// <param name="comPort">The COM port where the serial device can be found.</param>
        /// <param name="writeBootloader">Indicates whether or not the bootloader should be written.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task WriteFlash(FlashMulti flashMulti, string fileName, string comPort, bool writeBootloader)
        {
            // Path to the flashing tool, stm32flash.exe
            string command = ".\\tools\\stm32flash.exe";

            // Path to the bootloader file
            string bootLoaderPath = ".\\bootloaders\\StmMulti4in1.bin";

            // Baud rate for serial flash commands
            int serialBaud = Properties.Settings.Default.SerialBaudRate;

            // Arguments for the command line - will vary at each step of the process
            string commandArgs;

            // Variable to keep the return code from executed commands
            int returnCode = -1;

            // First step in flash process
            int flashStep = 1;

            // Total number of steps in flash process
            int flashSteps = 2;

            // Page in the STM32 flash memory where we will begin writing
            int flashStart = 0;

            // Address where we will start execution after flashing
            string executionAddress = "0x8000000";

            if (writeBootloader)
            {
                // Increase the total number of steps
                flashSteps = 3;

                // The bootloader occupies the first 8 pages (0-7), so start writing after it
                flashStart = 8;

                // Start execution at the Multiprotocol code rather than the bootloader
                executionAddress = "0x8002000";
            }

            // Write to the log
            flashMulti.AppendLog("Starting Multimodule update via serial\r\n");

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor          = null;
            bool          reconnectSerialMonitor = false;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    reconnectSerialMonitor = true;
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");

                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog(string.Format("Couldn't open port {0}", comPort));
                MessageBox.Show(string.Format("Couldn't open port {0}", comPort), "Write Firmware", MessageBoxButtons.OK, MessageBoxIcon.Error);
                flashMulti.EnableControls(true);
                return;
            }

            // Erase the flash
            flashMulti.AppendLog($"[{flashStep}/{flashSteps}] Erasing flash memory...");

            // Set the stm32flash.exe command line arguments for erasing
            // We preserve the last 2KB of flash, which is where the EEPROM data lives.
            commandArgs = $"-o -S 0x8000000:129024 -b {serialBaud} {comPort}";

            // Run the erase command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the erase command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog(" failed!");
                MessageBox.Show("Failed to erase flash memory.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            flashMulti.AppendLog(" done\r\n");

            // Write the bootloader if required
            if (writeBootloader)
            {
                // Increment the step counter and write to the log
                flashStep++;
                flashMulti.AppendLog($"[{flashStep}/{flashSteps}] Writing bootloader...");

                // Prepare the command line arguments for writing the bootloader
                commandArgs = $"-v -e 0 -g 0x8000000 -b {serialBaud} -w \"{bootLoaderPath}\" {comPort}";

                // Run the write command asynchronously and wait for it to finish
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                // Show an error message if the command failed for any reason
                if (returnCode != 0)
                {
                    flashMulti.EnableControls(true);
                    flashMulti.AppendLog(" failed!");
                    MessageBox.Show("Failed to write the bootloader.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                flashMulti.AppendLog(" done\r\n");
            }

            // Increment the step counter and write to the log
            flashStep++;
            flashMulti.AppendLog($"[{flashStep}/{flashSteps}] Writing Multimodule firmware...");

            // Prepare the command line arguments for writing the firmware
            commandArgs = $"-v -s {flashStart} -e 0 -g {executionAddress} -b {serialBaud} -w \"{fileName}\" {comPort}";

            // Run the write command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog(" failed!");
                MessageBox.Show("Failed to write the firmware.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Reconnect the serial monitor if it was connected before
            if (serialMonitor != null && serialMonitor.IsDisposed != true && reconnectSerialMonitor)
            {
                serialMonitor.SerialConnect(comPort);
            }

            // Write a success message to the log
            flashMulti.AppendLog(" done\r\n");
            flashMulti.AppendLog("\r\nMultimodule updated sucessfully");

            // Show a success message box
            MessageBox.Show("Multimodule updated sucessfully.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Information);

            // Re-enable the form controls
            flashMulti.EnableControls(true);
        }
예제 #12
0
        /// <summary>
        /// Erases the flash memory of a serial device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="comPort">The COM port where the serial device can be found.</param>
        /// <param name="eraseEeprom">Flag indicating if the EEPROM should be erased.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task <bool> EraseFlash(FlashMulti flashMulti, string comPort, bool eraseEeprom)
        {
            // Path to the flashing tool, stm32flash.exe
            string command = ".\\tools\\stm32flash.exe";

            // Baud rate for serial flash commands
            int serialBaud = Properties.Settings.Default.SerialBaudRate;

            // Arguments for the command line - will vary at each step of the process
            string commandArgs;

            // Variable to keep the return code from executed commands
            int returnCode = -1;

            // By default we preserve the last 2KB of flash, which is where the EEPROM data lives.
            int eraseBytes = 129024;

            // But if we're writing the EEPROM we need to erase it first
            if (eraseEeprom)
            {
                eraseBytes = 131072;
            }

            // Write to the log
            flashMulti.AppendLog($"{Strings.modeErasing} {Strings.viaSerial}\r\n");

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor = null;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");
                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog($"{Strings.failedToOpenPort} {comPort}");
                MessageBox.Show($"{Strings.failedToOpenPort} {comPort}", Strings.dialogTitleErase, MessageBoxButtons.OK, MessageBoxIcon.Error);
                flashMulti.EnableControls(true);
                return(false);
            }

            // Write to the log
            flashMulti.AppendLog($"[1/1] {Strings.progressErasingFlash}");

            // Prepare the command line arguments for erasing the firmware
            commandArgs = $"-o -S 0x8000000:{eraseBytes} -b {serialBaud} {comPort}";

            // Run the write command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog(Strings.failed);
                MessageBox.Show(Strings.failedtoEraseModule, Strings.dialogTitleErase, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return(false);
            }

            // Write a success message to the log
            flashMulti.AppendLog($" {Strings.done}\r\n");
            flashMulti.AppendLog($"\r\n{Strings.succeededErasing}");

            // Re-enable the form controls
            flashMulti.EnableControls(true);

            return(true);
        }
예제 #13
0
        /// <summary>
        /// Writes the firmware to a serial device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the file to flash.</param>
        /// <param name="comPort">The COM port where the serial device can be found.</param>
        /// <param name="writeBootloader">Indicates whether or not the bootloader should be written.</param>
        /// <param name="writeEeprom">Indicates whether or not the EEPROM is being written, therefore should be erased before the write.</param>
        /// <param name="runAfterUpload">Indicates whether or not the firmware should run after it is uploaded.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task WriteFlash(FlashMulti flashMulti, string fileName, string comPort, bool writeBootloader, bool writeEeprom, bool runAfterUpload)
        {
            // Path to the flashing tool, stm32flash.exe
            string command = ".\\tools\\stm32flash.exe";

            // Path to the bootloader file
            string bootLoaderPath = ".\\bootloaders\\StmMulti4in1_StickyDfu.bin";

            // Baud rate for serial flash commands
            int serialBaud = Properties.Settings.Default.SerialBaudRate;

            // Arguments for the command line - will vary at each step of the process
            string commandArgs;

            // Variable to keep the return code from executed commands
            int returnCode = -1;

            // First step in flash process
            int flashStep = 0;

            // Total number of steps in flash process
            int flashSteps = 2;

            // Page in the STM32 flash memory where we will begin writing
            int flashStart = 0;

            // By default we preserve the last 2KB of flash, which is where the EEPROM data lives.
            int eraseBytes = 129024;

            // But if we're writing the EEPROM we need to erase it first
            if (writeEeprom)
            {
                eraseBytes = 131072;
            }

            // Address where we will start execution after flashing
            string executionAddress = "0x8000000";

            if (writeBootloader)
            {
                // Increase the total number of steps
                flashSteps++;

                // The bootloader occupies the first 8 pages (0-7), so start writing after it
                flashStart = 8;

                // Start execution at the MULTI-Module code rather than the bootloader
                executionAddress = "0x8002000";
            }

            // Write to the log
            flashMulti.AppendLog($"{Strings.modeWriting} {Strings.viaSerial}\r\n");

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor          = null;
            bool          reconnectSerialMonitor = false;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    reconnectSerialMonitor = true;
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");

                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog($"{Strings.failedToOpenPort} {comPort}");
                MessageBox.Show($"{Strings.failedToOpenPort} {comPort}", Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                flashMulti.EnableControls(true);
                return;
            }

            if (!Properties.Settings.Default.DisableFlashVerification)
            {
                flashStep++;

                // Increase the total number of steps
                flashSteps++;

                // Check that the STM32 MCU supports 128KB
                flashMulti.AppendLog($"[{flashStep}/{flashSteps}] {Strings.progressCheckingFlashSize}");

                // Create a temporary file name to read into
                string tempFileName = Path.GetTempFileName();

                // Set the stm32flash.exe command line arguments for reading the 32B of flash above 64KB
                commandArgs = $"-r {tempFileName} -S 0x8010000:32 -b {serialBaud} {comPort}";

                // Run the read command asynchronously and wait for it to finish
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                // Show an error message if the read command failed for any reason
                if (returnCode != 0)
                {
                    flashMulti.EnableControls(true);
                    flashMulti.AppendLog($" {Strings.failed}");
                    MessageBox.Show(Strings.failedToReadModule, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                flashMulti.AppendLog($" {Strings.done}\r\n");

                // Read the data we read from the module
                byte[] byteBuffer = File.ReadAllBytes(tempFileName);

                // 32 Bytes of bad data to compare to
                byte[] badData = { 7, 73, 8, 128, 7, 73, 8, 128, 7, 73, 8, 128, 7, 73, 8, 128, 7, 73, 8, 128, 7, 73, 8, 128, 7, 73, 8, 128, 7, 73, 8, 128 };

                // Compare the data we read to the known 'bad' data
                if (StructuralComparisons.StructuralEqualityComparer.Equals(byteBuffer, badData))
                {
                    // Throw a message and stop
                    flashMulti.EnableControls(true);
                    MessageBox.Show(Strings.failedToVerifyMcuFlash, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }
            }

            // Increment the step counter and write to the log
            flashStep++;
            flashMulti.AppendLog($"[{flashStep}/{flashSteps}] {Strings.progressErasingFlash}");

            // Set the stm32flash.exe command line arguments for erasing
            commandArgs = $"-o -S 0x8000000:{eraseBytes} -b {serialBaud} {comPort}";

            // Run the erase command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the erase command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog($" {Strings.failed}");
                MessageBox.Show(Strings.failedtoEraseModule, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            flashMulti.AppendLog($" {Strings.done}\r\n");

            // Write the bootloader if required
            if (writeBootloader)
            {
                // Increment the step counter and write to the log
                flashStep++;
                flashMulti.AppendLog($"[{flashStep}/{flashSteps}] {Strings.progressWritingBootloader}");

                // Prepare the command line arguments for writing the bootloader
                commandArgs = $"-v -e 0 -g 0x8000000 -b {serialBaud} -w \"{bootLoaderPath}\" {comPort}";

                // Run the write command asynchronously and wait for it to finish
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                // Show an error message if the command failed for any reason
                if (returnCode != 0)
                {
                    flashMulti.EnableControls(true);
                    flashMulti.AppendLog($" {Strings.failed}");
                    MessageBox.Show(Strings.failedToWriteBootloader, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                flashMulti.AppendLog($" {Strings.done}\r\n");
            }

            // Increment the step counter and write to the log
            flashStep++;
            flashMulti.AppendLog($"[{flashStep}/{flashSteps}] {Strings.progressWritingFirmware}");

            // Prepare the command line arguments for writing the firmware
            commandArgs = $"-v -s {flashStart} -e 0 -b {serialBaud} -w \"{fileName}\" {comPort}";

            if (runAfterUpload)
            {
                commandArgs += $" -g {executionAddress}";
            }

            // Run the write command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog($" {Strings.failed}");
                MessageBox.Show(Strings.failedToWriteFirmware, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Reconnect the serial monitor if it was connected before
            if (serialMonitor != null && serialMonitor.IsDisposed != true && reconnectSerialMonitor)
            {
                serialMonitor.SerialConnect(comPort);
            }

            // Write a success message to the log
            flashMulti.AppendLog($" {Strings.done}\r\n");
            flashMulti.AppendLog($"\r\n{Strings.succeededWritingFirmware}");

            // Re-enable the form controls
            flashMulti.EnableControls(true);

            // Show a success message box
            MessageBox.Show(Strings.succeededWritingFirmware, Strings.succeededWritingFirmware, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
예제 #14
0
        /// <summary>
        /// Reads the flash memory of a serial device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the file to write to.</param>
        /// <param name="comPort">The COM port where the serial device can be found.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task <bool> ReadFlash(FlashMulti flashMulti, string fileName, string comPort)
        {
            // Path to the flashing tool, stm32flash.exe
            string command = ".\\tools\\stm32flash.exe";

            // Baud rate for serial flash commands
            int serialBaud = Properties.Settings.Default.SerialBaudRate;

            // Arguments for the command line - will vary at each step of the process
            string commandArgs;

            // Variable to keep the return code from executed commands
            int returnCode = -1;

            // Write to the log
            flashMulti.AppendLog($"{Strings.modeReading} {Strings.viaSerial}\r\n");

            // Stop the serial monitor if it's active
            SerialMonitor serialMonitor          = null;
            bool          reconnectSerialMonitor = false;

            if (Application.OpenForms.OfType <SerialMonitor>().Any())
            {
                Debug.WriteLine("Serial monitor window is open");
                serialMonitor = Application.OpenForms.OfType <SerialMonitor>().First();
                if (serialMonitor != null && serialMonitor.SerialPort != null && serialMonitor.SerialPort.IsOpen)
                {
                    reconnectSerialMonitor = true;
                    Debug.WriteLine($"Serial monitor is connected to {serialMonitor.SerialPort.PortName}");

                    Debug.WriteLine($"Closing serial monitor connection to {serialMonitor.SerialPort.PortName}");
                    serialMonitor.SerialDisconnect();
                }
            }
            else
            {
                Debug.WriteLine("Serial monitor is not open");
            }

            // Check if the port can be opened
            if (!ComPort.CheckPort(comPort))
            {
                flashMulti.AppendLog($"{Strings.failedToOpenPort} {comPort}");
                MessageBox.Show($"{Strings.failedToOpenPort} {comPort}", Strings.dialogTitleRead, MessageBoxButtons.OK, MessageBoxIcon.Error);
                flashMulti.EnableControls(true);
                return(false);
            }

            // Write to the log
            flashMulti.AppendLog($"[1/1] {Strings.progressReadingFlash}");

            // Prepare the command line arguments for writing the firmware
            commandArgs = $"-b {serialBaud} -r \"{fileName}\" {comPort}";

            // Run the write command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.AppendLog($" {Strings.failed}");
                MessageBox.Show(Strings.failedToReadModule, Strings.dialogTitleRead, MessageBoxButtons.OK, MessageBoxIcon.Error);
                flashMulti.EnableControls(true);
                return(false);
            }

            // Reconnect the serial monitor if it was connected before
            if (serialMonitor != null && serialMonitor.IsDisposed != true && reconnectSerialMonitor)
            {
                serialMonitor.SerialConnect(comPort);
            }

            // Write a success message to the log
            flashMulti.AppendLog($" {Strings.done}\r\n\r\n");

            // Re-enable the form controls
            flashMulti.EnableControls(true);

            return(true);
        }
예제 #15
0
        /// <summary>
        /// Writes the firmware to a serial device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the file to flash.</param>
        /// <param name="writeBootloader">Indicates whether or not the bootloader should be written.</param>
        /// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns>
        public static async Task WriteFlash(FlashMulti flashMulti, string fileName, bool writeBootloader)
        {
            // Path to the flashing tool, stm32flash.exe
            string command = ".\\tools\\avrdude.exe";

            // Path to the bootloader file
            string bootLoaderPath = ".\\bootloaders\\AtmegaMultiBoot.hex";

            // Arguments for the command line - will vary at each step of the process
            string commandArgs;

            // Variable to keep the return code from executed commands
            int returnCode = -1;

            // First step in flash process
            flashMulti.FlashStep = 1;

            // Total number of steps in flash process
            flashMulti.FlashSteps = 4;

            // Fuses
            string unlockBits    = "0x3F";
            string lockBits      = "0x0F";
            string extendedFuses = "0xFD";
            string highFuses     = "0xD7";
            string lowFuses      = "0xFF";

            // Default avrdude command arguments (no bootloader)
            commandArgs = $"-C.\\tools\\avrdude.conf -patmega328p -cusbasp -Ulock:w:{unlockBits}:m -Uefuse:w:{extendedFuses}:m -Uhfuse:w:{highFuses}:m -Ulfuse:w:{lowFuses}:m -Uflash:w:{fileName}:a";

            if (writeBootloader)
            {
                // Increase the total number of steps
                flashMulti.FlashSteps = 5;

                // Set the high fuses
                highFuses = "0xD6";

                commandArgs = $"-C.\\tools\\avrdude.conf -patmega328p -cusbasp -Ulock:w:{unlockBits}:m -Uefuse:w:{extendedFuses}:m -Uhfuse:w:{highFuses}:m -Ulfuse:w:{lowFuses}:m -Uflash:w:{bootLoaderPath}:i -Ulock:w:{lockBits}:m -Uflash:w:{fileName}:a";
            }

            // Write to the log
            flashMulti.AppendLog("Starting MULTI-Module update via USBasp\r\n");

            // Run the command asynchronously and wait for it to finish
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            // Show an error message if the command failed for any reason
            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog("\r\nFirmware update failed!");
                MessageBox.Show("Failed to write flash memory.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            flashMulti.AppendLog("\r\nDone.");
            flashMulti.AppendLog("\r\nMULTI-Module updated successfully");

            MessageBox.Show("MULTI-Module updated successfully.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Information);

            flashMulti.EnableControls(true);
        }
예제 #16
0
        /// <summary>
        /// Writes the firmware to a serial device.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="fileName">The path of the file to flash.</param>
        /// <param name="comPort">The COM port where the serial device can be found.</param>
        public static async void WriteFlash(FlashMulti flashMulti, string fileName, string comPort)
        {
            string command        = ".\\tools\\stm32flash.exe";
            string bootLoaderPath = ".\\bootloaders\\StmMulti4in1.bin";
            string commandArgs;

            int returnCode = -1;
            int flashStep  = 1;
            int flashSteps = 2;

            int    flashStart       = 0;
            string executionAddress = "0x8000000";

            if (flashMulti.writeBootloader_Yes.Checked)
            {
                flashSteps = 3;
            }

            flashMulti.AppendLog("Starting Multimodule update\r\n");

            // Erase
            flashMulti.AppendLog($"[{flashStep}/{flashSteps}] Erasing flash memory...");
            commandArgs = string.Format("-o -S 0x8000000:129024 -b 115200 {0}", comPort);
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog(" failed!");
                MessageBox.Show("Failed to erase flash memory.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            flashMulti.AppendLog(" done\r\n");

            if (flashMulti.writeBootloader_Yes.Checked)
            {
                // Flash bootloader
                flashStep++;
                flashMulti.AppendLog($"[{flashStep}/{flashSteps}] Writing bootloader...");
                commandArgs = $"-v -e 0 -g {executionAddress} -b 115200 -w \"{bootLoaderPath}\" {comPort}";
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                if (returnCode != 0)
                {
                    flashMulti.EnableControls(true);
                    flashMulti.AppendLog(" failed!");
                    MessageBox.Show("Failed to write the bootloader.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                flashMulti.AppendLog(" done\r\n");

                // Set the flash address for a flash with bootloader
                flashStart       = 8;
                executionAddress = "0x8002000";
            }

            // Flash firmware
            flashStep++;
            flashMulti.AppendLog($"[{flashStep}/{flashSteps}] Writing Multimodule firmware...");
            commandArgs = $"-v -s {flashStart} -e 0 -g {executionAddress} -b 115200 -w \"{fileName}\" {comPort}";
            await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

            if (returnCode != 0)
            {
                flashMulti.EnableControls(true);
                flashMulti.AppendLog(" failed!");
                MessageBox.Show("Failed to write the firmware.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            flashMulti.AppendLog(" done\r\n");
            flashMulti.AppendLog("\r\nMultimodule updated sucessfully");

            MessageBox.Show("Multimodule updated sucessfully.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
            flashMulti.EnableControls(true);
        }