Beispiel #1
0
 /// <summary>
 /// Initializes a new instance of the <see cref="DfuRecoveryDialog"/> class.
 /// </summary>
 /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> form.</param>
 public DfuRecoveryDialog(FlashMulti flashMulti)
 {
     this.InitializeComponent();
     this.flashMulti = flashMulti;
     this.Load      += this.DfuRecoveryDialog_Load;
     this.Shown     += this.DfuRecoveryDialog_Shown;
 }
Beispiel #2
0
        /// <summary>
        /// Prompt the user if a newer version is available.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        public static async void DoCheck(FlashMulti flashMulti)
        {
            // Get check for the latest version on Github
            UpdateCheck check = new UpdateCheck();
            await Task.Run(() => { check = GetLatestVersion(); });

            // If the check completed successfully
            if (check.CheckSuccess)
            {
                // Get the current version
                Version currentVersion = Version.Parse(Application.ProductVersion);

                // Get the version available on Github
                Version latestVersion = check.LatestVersion;

                // Check if the current version is older than the latest Github release version
                if (currentVersion.CompareTo(latestVersion) == -1)
                {
                    // A newer version is available to show the user a prompt
                    Debug.WriteLine($"App version is older than latest version: {currentVersion} < {latestVersion}");
                    DialogResult showUpdate = MessageBox.Show(
                        $"A newer version of Flash Multi is available.\n\nYou have Flash Multi v{currentVersion.ToString()} and Flash Multi v{latestVersion.ToString()} is available.\n\nSee the latest release on Github?",
                        "Flash Multi Update Available",
                        MessageBoxButtons.YesNo,
                        MessageBoxIcon.Information);

                    // Show the Github release page for the new version if the user clicked Yes
                    if (showUpdate == DialogResult.Yes)
                    {
                        flashMulti.OpenLink(check.ReleaseUrl);
                    }
                }
            }
        }
Beispiel #3
0
        /// <summary>
        /// Prompt the user if a newer version is available.
        /// </summary>
        /// <param name="flashMulti">An instance of the <see cref="FlashMulti"/> class.</param>
        /// <param name="showNoUpdate">Indicate whether or not to show a message if there is no update.</param>
        public static async void DoCheck(FlashMulti flashMulti, bool showNoUpdate = false)
        {
            // Get check for the latest version on Github
            UpdateCheck check = new UpdateCheck();
            await Task.Run(() => { check = GetLatestVersion(); });

            // If the check completed successfully
            if (check.CheckSuccess)
            {
                // Get the current version
                Version currentVersion = Version.Parse(Application.ProductVersion);

                // Get the version available on Github
                Version latestVersion = check.LatestVersion;

                // Check if the current version is older than the latest Github release version
                if (currentVersion.CompareTo(latestVersion) == -1)
                {
                    // A newer version is available to show the user a prompt
                    Debug.WriteLine($"App version is older than latest version: {currentVersion} < {latestVersion}");

                    DialogResult showUpdate;
                    using (new CenterWinDialog(flashMulti))
                    {
                        showUpdate = MessageBox.Show(
                            $"{Strings.updatePromptPart1} v{currentVersion} {Strings.updatePromptPart2} v{latestVersion} {Strings.updatePromptPart3}",
                            Strings.dialogTitleUpdateCheck,
                            MessageBoxButtons.YesNo,
                            MessageBoxIcon.Information);
                    }

                    // Show the Github release page for the new version if the user clicked Yes
                    if (showUpdate == DialogResult.Yes)
                    {
                        flashMulti.OpenLink(check.ReleaseUrl);
                    }
                }
                else
                {
                    if (showNoUpdate)
                    {
                        using (new CenterWinDialog(flashMulti))
                        {
                            MessageBox.Show(Strings.updateNoUpdate, Strings.dialogTitleUpdateCheck, MessageBoxButtons.OK);
                        }
                    }
                }
            }
            else
            {
                if (showNoUpdate)
                {
                    using (new CenterWinDialog(flashMulti))
                    {
                        MessageBox.Show(Strings.updateCheckFailed, Strings.dialogTitleUpdateCheck, MessageBoxButtons.OK);
                    }
                }
            }
        }
Beispiel #4
0
        /// <summary>
        /// Writes the firmware via a USBasp 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;

            // Default avrdude command arguments (no bootloader)
            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:{fileName}:a";

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

                commandArgs = $"-C.\\tools\\avrdude.conf -patmega328p -cusbasp -Ulock:w:{UnlockBits}:m -Uefuse:w:{ExtendedFuses}:m -Uhfuse:w:{HighFusesBoot}:m -Ulfuse:w:{LowFuses}:m -Uflash:w:{bootLoaderPath}:i -Ulock:w:{LockBits}:m -Uflash:w:{fileName}:a";
            }

            // 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.EnableControls(true);
                flashMulti.AppendLog($"\r\n{Strings.failedToWriteFirmware}");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show(Strings.failedToWriteFirmware, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                return;
            }

            flashMulti.AppendLog($"\r\n{Strings.succeededWritingFirmware}");
            using (new CenterWinDialog(flashMulti))
            {
                MessageBox.Show(Strings.succeededWritingFirmware, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            flashMulti.EnableControls(true);
        }
Beispiel #5
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}");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show(Strings.failedtoEraseModule, Strings.dialogTitleErase, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                return(false);
            }

            flashMulti.AppendLog($"\r\n{Strings.succeededErasing}");
            flashMulti.EnableControls(true);
            return(true);
        }
Beispiel #6
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}");
                using (new CenterWinDialog(flashMulti))
                {
                    MessageBox.Show(Strings.failedToWriteEeprom, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Error);
                }

                flashMulti.EnableControls(true);
                return;
            }

            flashMulti.AppendLog($"\r\n{Strings.succeededWritingEeprom}");
            using (new CenterWinDialog(flashMulti))
            {
                MessageBox.Show(Strings.succeededWritingEeprom, Strings.dialogTitleWrite, MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            flashMulti.EnableControls(true);
        }
Beispiel #7
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);
        }
Beispiel #8
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);
        }
Beispiel #9
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);
        }
Beispiel #10
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);
        }
Beispiel #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>
        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);
        }
Beispiel #12
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);
        }
Beispiel #13
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);
        }
Beispiel #14
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);
        }
Beispiel #15
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);
        }
Beispiel #16
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);
            }
        }
Beispiel #17
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);
        }
Beispiel #18
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);
        }
Beispiel #19
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}'");
                }
            }
        }
Beispiel #20
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);
        }
Beispiel #21
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);
        }
Beispiel #22
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);
        }
Beispiel #23
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);
        }