/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); } }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }
/// <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); }