예제 #1
0
        /// <summary>
        /// Runs a command with arguments.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="command">The command to run.</param>
        /// <param name="args">Arguments for the command.</param>
        /// <returns>The exit code returned by the command.</returns>
        public static int Run(FlashMulti flashMulti, string command, string args)
        {
            Debug.WriteLine("\n" + command + " " + args + "\n");
            flashMulti.AppendVerbose(command + " " + args + "\r\n");

            // Check if the file exists
            if (!File.Exists(command))
            {
                flashMulti.AppendVerbose(string.Format("{0} does not exist", command));
                return(-1);
            }

            Process myProcess = new Process();

            // Process process = new Process();
            myProcess.StartInfo.FileName               = command;
            myProcess.StartInfo.Arguments              = args;
            myProcess.StartInfo.UseShellExecute        = false;
            myProcess.StartInfo.RedirectStandardOutput = true;
            myProcess.StartInfo.RedirectStandardError  = true;
            myProcess.StartInfo.CreateNoWindow         = true;

            // Set your output and error (asynchronous) handlers
            myProcess.OutputDataReceived += new DataReceivedEventHandler(flashMulti.OutputHandler);
            myProcess.ErrorDataReceived  += new DataReceivedEventHandler(flashMulti.OutputHandler);

            // Start process and handlers
            myProcess.Start();

            // Read the output
            myProcess.BeginOutputReadLine();
            myProcess.BeginErrorReadLine();

            // Loop until the process finishes
            myProcess.WaitForExit();

            // Return the exit code from the process
            return(myProcess.ExitCode);
        }
예제 #2
0
        /// <summary>
        /// Runs a command with arguments.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="command">The command to run.</param>
        /// <param name="args">Arguments for the command.</param>
        /// <returns>The exit code returned by the command.</returns>
        public static int Run(FlashMulti flashMulti, string command, string args)
        {
            Debug.WriteLine("\n" + command + " " + args + "\n");
            flashMulti.AppendVerbose(command + " " + args + "\r\n");

            // Check if the file exists
            if (!File.Exists(command))
            {
                flashMulti.AppendVerbose(string.Format("{0} does not exist", command));
                return(-1);
            }

            Process myProcess = new Process();

            // Process process = new Process();
            myProcess.StartInfo.FileName               = command;
            myProcess.StartInfo.Arguments              = args;
            myProcess.StartInfo.UseShellExecute        = false;
            myProcess.StartInfo.RedirectStandardOutput = true;
            myProcess.StartInfo.RedirectStandardError  = true;
            myProcess.StartInfo.CreateNoWindow         = true;

            // avrdude sends all output to stderr, so reverse the sync/async processing
            if (command.EndsWith("avrdude.exe"))
            {
                // Handle standard output asynchronously
                myProcess.OutputDataReceived += new DataReceivedEventHandler(flashMulti.OutputHandler);

                // Start process and handlers
                myProcess.Start();

                // Read the standard output asynchronously, handle it by line
                myProcess.BeginOutputReadLine();

                // Read the error output synchronously, handle it character-by-character
                while (!myProcess.StandardError.EndOfStream)
                {
                    var data = myProcess.StandardError.Read();
                    flashMulti.CharOutputHandler((char)data);
                }
            }
            else
            {
                // Hande error output asynchronously
                myProcess.ErrorDataReceived += new DataReceivedEventHandler(flashMulti.OutputHandler);

                // Start process and handlers
                myProcess.Start();

                // Read the error output asynchronously, handle it by line
                myProcess.BeginErrorReadLine();

                // Read the standard output synchronously, handle it character-by-character
                while (!myProcess.StandardOutput.EndOfStream)
                {
                    var data = myProcess.StandardOutput.Read();
                    flashMulti.CharOutputHandler((char)data);
                }
            }

            // Loop until the process finishes
            myProcess.WaitForExit();

            int returnCode = myProcess.ExitCode;

            myProcess.Dispose();

            // Return the exit code from the process
            return(returnCode);
        }
예제 #3
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);
        }
예제 #4
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);
        }
예제 #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>
        /// <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);
            }
        }
예제 #6
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);
        }
예제 #7
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);
        }
예제 #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>
        /// <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 MULTI-Module 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 MULTI-Module into DFU mode ...");
                command     = ".\\tools\\maple-reset.exe";
                commandArgs = $"{comPort} 2000";
                await Task.Run(() => { returnCode = RunCommand.Run(flashMulti, command, commandArgs); });

                if (returnCode == 0)
                {
                    flashMulti.AppendLog(" done\r\n");
                    flashMulti.AppendVerbose(string.Empty);
                }
                else
                {
                    if (MapleDevice.FindMaple().DfuMode == false)
                    {
                        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 make 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;
                        }
                    }
                    else
                    {
                        flashMulti.AppendLog(" done\r\n");
                        flashMulti.AppendVerbose(string.Empty);
                    }
                }
            }

            // First attempt to flash the firmware
            flashMulti.AppendLog("Writing firmware to MULTI-Module ...");
            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 MULTI-Module ...");
                    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\nMULTI-Module updated successfully");

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

            MessageBox.Show("MULTI-Module updated successfully.", "Firmware Update", MessageBoxButtons.OK, MessageBoxIcon.Information);
            flashMulti.EnableControls(true);
        }
예제 #9
0
        /// <summary>
        /// Uses the temporary file read from the module to extract and save a firmware backup.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="flashFileName">The temporary file containing the module's flash data.</param>
        /// <param name="eepromFileName">The temporary file containing an Atmega328p module's EEPROM data.</param>
        internal static void SaveFirmwareBackup(FlashMulti flashMulti, string flashFileName, string eepromFileName)
        {
            Debug.WriteLine($"Flash backup file:  {flashFileName}");

            // Stop if the backup file isn't found or the type isn't valid
            if (!File.Exists(flashFileName) || flashMulti.BackupModuleType < 1)
            {
                MessageBox.Show("Backup file not found. Please read the MULTI-Module again.", "Save Backup", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Ask the user if they want to include the EEPROM
            DialogResult includeEeprom = DialogResult.Cancel;

            if (flashMulti.BackupModuleType == FlashMulti.Stm32BackupDfuUtil || flashMulti.BackupModuleType == FlashMulti.Stm32BackupStm32Flash)
            {
                // STM32 backup - ask if EEPROM data should be included in the backup
                includeEeprom = MessageBox.Show("Include the EEPROM data in the backup?", "Include EEPROM", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
            }
            else if (flashMulti.BackupModuleType == FlashMulti.AtmegaBackup)
            {
                // Atmega328p backup - ask if the EEPROM should be save seperately
                Debug.WriteLine($"EEPROM backup file: {eepromFileName}");
                includeEeprom = MessageBox.Show("Save the EEPROM data?  It will be saved in a separate file.", "Include EEPROM", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);
            }

            // Stop if the user cancelled
            if (includeEeprom == DialogResult.Cancel)
            {
                return;
            }

            // Get the size of the back up file
            long flashFileSize = new System.IO.FileInfo(flashFileName).Length;

            Debug.WriteLine($"Flash file is {flashFileSize} bytes.");

            // Get the maximum file size for each backup type
            long firmwareSizeMax = 0;

            switch (flashMulti.BackupModuleType)
            {
            case FlashMulti.AtmegaBackup:
                firmwareSizeMax = 32 * 1024;
                break;

            case FlashMulti.Stm32BackupDfuUtil:
                firmwareSizeMax = 120 * 1024;
                break;

            case FlashMulti.Stm32BackupStm32Flash:
                firmwareSizeMax = 128 * 1024;
                break;
            }

            // Stop if the file is bigger than we expect
            if (flashFileSize > firmwareSizeMax)
            {
                MessageBox.Show($"Unexpected backup file size.  File is {flashFileSize} bytes, maximum size is {firmwareSizeMax} bytes.", "Save Backup", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            // Get the start byte
            long backupStartByte = 0;

            // Skip the first 8KB if the backup includes the bootloader
            if (flashMulti.BackupModuleType == FlashMulti.Stm32BackupStm32Flash && FirmwareContainsBootloader(flashFileName) && flashFileSize == 128 * 1024)
            {
                backupStartByte = 8192;
            }

            // Get the end byte - default to the entire file
            long backupEndByte = flashFileSize;

            // If this is an STM32 backup and the EEPROM is not being included we don't need the last 2KB of the backup
            if (flashMulti.BackupModuleType != FlashMulti.AtmegaBackup && includeEeprom == DialogResult.No)
            {
                // Discard the last 2KB of the flash backup
                backupEndByte = flashFileSize - 2048;
            }

            // Create the file save dialog for the flash backup
            using (SaveFileDialog saveFileDialog = new SaveFileDialog())
            {
                // Title for the dialog
                saveFileDialog.Title = "Location to save the flash backup";

                // Filter for .bin files
                saveFileDialog.Filter = ".bin File|*.bin";

                // Return if the dialog was cancelled
                if (saveFileDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                // Extract the firmware from the backup file
                byte[] firmwareData;

                // Read the last firmware from the binary file
                using (BinaryReader b = new BinaryReader(File.Open(flashFileName, FileMode.Open, FileAccess.Read)))
                {
                    // Length of data to read
                    long byteLength = backupEndByte - backupStartByte;
                    Debug.WriteLine($"Capturing {byteLength} bytes between {backupStartByte} and {backupEndByte}");

                    // Seek to the start position
                    b.BaseStream.Seek(backupStartByte, SeekOrigin.Begin);

                    // Read the firmware data
                    firmwareData = b.ReadBytes((int)byteLength);
                }

                // Save the file
                using (BinaryWriter b = new BinaryWriter(File.Open(saveFileDialog.FileName, FileMode.Create, FileAccess.Write)))
                {
                    // Write the data
                    b.Write(firmwareData);
                }

                flashMulti.AppendLog($"\r\n\r\nMULTI-Module firmware saved successfully");
                flashMulti.AppendVerbose($"Firmware saved to '{saveFileDialog.FileName}'");
            }

            // Save the Atmega328p EEPROM to a separate file
            if (flashMulti.BackupModuleType == FlashMulti.AtmegaBackup && includeEeprom == DialogResult.Yes)
            {
                // Create the file save dialog for the flash backup
                using (SaveFileDialog saveFileDialog = new SaveFileDialog())
                {
                    // Title for the dialog
                    saveFileDialog.Title = "Location to save the EEPROM backup";

                    // Filter for .eep files
                    saveFileDialog.Filter = ".eep File|*.eep";

                    // Return if the dialog was cancelled
                    if (saveFileDialog.ShowDialog() != DialogResult.OK)
                    {
                        return;
                    }

                    // Extract the firmware from the backup file
                    byte[] firmwareData;

                    // Read the last firmware from the binary file
                    using (BinaryReader b = new BinaryReader(File.Open(eepromFileName, FileMode.Open, FileAccess.Read)))
                    {
                        // Seek to the start position
                        b.BaseStream.Seek(0, SeekOrigin.Begin);

                        // Read the firmware data
                        firmwareData = b.ReadBytes(1024);
                    }

                    // Save the file
                    using (BinaryWriter b = new BinaryWriter(File.Open(saveFileDialog.FileName, FileMode.Create, FileAccess.Write)))
                    {
                        // Write the data
                        b.Write(firmwareData);
                    }

                    flashMulti.AppendLog($"\r\nMULTI-Module EEPROM saved successfully");
                    flashMulti.AppendVerbose($"EEPROM saved to '{saveFileDialog.FileName}'");
                }
            }
        }