diff --git a/doc/New_Bootloader.md b/doc/New_Bootloader.md new file mode 100644 index 0000000..5423a38 --- /dev/null +++ b/doc/New_Bootloader.md @@ -0,0 +1,90 @@ +# New MULTI-Module Bootloader + +If you have: +* A radio with an internal MULTI-Module (e.g. T16, T18, TX16S), or +* A Jumper JP4IN1-SE or RadioBoss JP4IN1 MULTI-Module, or +* Any other MULTI-Module which is identified as a CP2102 device when you plug it, or +* Any Atmega32p-based MULTI-Module + +You can stop reading now - this does not matter to you. + +**If you have a Jumper JP4IN1, iRangeX IRX4, Banggood, or any other STM32 MULTI-Module, please read this information - if you use the USB port on your module, you will need to take action!** + +If you want to cut to the chase, skip to the [what you need to do](#what-you-need-to-do) section. + +## Introduction +The latest version of Flash Multi, v0.5.0, gives you the ability to flash a new bootloader to your MULTI-Module. + +The new bootloader changes the behaviour of the USB port on your MULTI-module when you plug the module into a computer. + +| Action | Old Bootloader (COM Port Mode) | New Bootloader (Sticky DFU Mode) | +| --- | --- | --- | +| Connect the module to the computer, radio is off | Module starts in DFU mode then switches to COM port mode | Module starts in DFU mode and stays in DFU mode | +| Connect the module to the computer, radio is on | Computer will detect a USB COM port | Computer will detect an unidentified device | + +## Reason for Change +Historically, the MULTI-Module firmware has always included code to make the USB COM port work when the module is running. However, the USB COM port is only used in two ways: +* Switching the module to firmware update (DFU) mode when it is being flashed by using Flash Multi or the Arduino IDE +* Debug output when running a debug-enabled build (typically only used by developers) + +And, there is never need for an internal MULTI-Module to have the USB COM port code, but it was always included. When this decision was made the firmware was around 80KB, and we had plenty of free space in the 128KB available flash on the STM32 MCU. + +Fast-forward three years and we have all but run out of space in the STM32. In an effort to free some space up, we are removing USB support from the firmware. **This change saves 5KB of flash.** This may not seem like much, but it's room for several more protocols. + +**Firmware without USB support will start to be released later in 2020.** + +Because we're removing the mechanism that would allow flashing tools to put the module into DFU mode, we have to provide a different way to do that. + +This is where the new bootloader comes in - it keeps the module in DFU mode when it is plugged in via USB, removing the need to use the COM port to switch it into DFU mode. + +## What you need to do +**You will need to use Flash Multi to upgrade the bootloader on your MULTI-Module _before_ you flash firmware which does not have USB support.** + +### Upgrading to the new bootloader +There is a one-time process to update the bootloader on the module. After the bootloader upgrade you will need to flash new firmware to your module. + +1. Launch Flash Multi +1. Tell Flash Multi to use the new bootloader: + 1. Click **Advanced** -> **Settings** -> **USB Port Mode** -> **Sticky DFU Mode (New)** +1. Plug your module in +1. Ensure that the correct COM port is selected +1. Flash the new bootloader to your module: + 1. Click **Advanced** -> **Actions** -> **Flash Module Bootloader** + 1. Wait for the red LED to go out + 1. Unplug the module + +**You must pay attention to the instructions. DO NOT unplug the module until the red LED has gone out for at least two seconds.** + +You will now need to write new MULTI-Module firmware to the module in the normal way: +1. Check that the COM port is set to **DFU Device** +1. Select the firmware file +1. Click **Write Module** + +You will get a warning reminding you that you needed to update the bootloader, you may check the box to stop the message showing again. + +Once you have written new firmware to your module, if you unplug it and plug it back in, the module should stay in DFU mode with the red LED blinking continuously. + +## Frequently Asked Questions +## When should I update the bootloader? +You can do it any time after the release of Flash Multi v0.5.0. The new bootloader works with all previous MULTI-Module firmware releases. + +### If I only ever flash my MULTI-Module from the radio do I have to do the bootloader update? +No, you don't have to do it. You can also wait and do it later if you want to. + +### How do I know which bootloader my MULTI-Module has? +Plug it in via USB +* If the red LED blinks rapidly then starts to blink slowly and the green LED comes on you have the old bootloader +* If the red LED blinks rapidly continuously you have the new bootloader +* If the green LED comes on and the red LED stays off you have a module which does not use the bootloader for the USB port + +### I flashed new firmware without USB support from the radio and now my USB port doesn't work, how do I fix it? +You have the old bootloader. Use Flash Multi to flash the module bootloader, as explained above. You will have to unplug and replug the module when instructed. + +### I have to unplug and re-plug my module every time I flash it, how do I fix it? +You have the old bootloader. Use Flash Multi to flash the module bootloader, as explained above. You will have to unplug and replug the module when instructed. + +### Why doesn't this apply to JP4IN1-SE or Radioboss modules? +They use a different USB interface which does not use DFU mode to flash firmware. They will work happily with the old or new bootloaders and do not require updating this way. + +### Why doesn't this apply to radios with internal modules? +Because internal modules don't have USB ports they do not require any update to work properly with the new firmware which does not have USB support. diff --git a/linux/bootloader/StmMulti4in1.bin b/linux/bootloader/StmMulti4in1_Legacy.bin similarity index 100% rename from linux/bootloader/StmMulti4in1.bin rename to linux/bootloader/StmMulti4in1_Legacy.bin diff --git a/linux/bootloader/StmMulti4in1_StickyDfu.bin b/linux/bootloader/StmMulti4in1_StickyDfu.bin new file mode 100644 index 0000000..6ac312c Binary files /dev/null and b/linux/bootloader/StmMulti4in1_StickyDfu.bin differ diff --git a/linux/flash-multi b/linux/flash-multi index 726b505..30f5bd7 100755 --- a/linux/flash-multi +++ b/linux/flash-multi @@ -19,16 +19,16 @@ shopt -s extglob # ********************************************************************* # Define the script version -VERSION=0.4.3 +VERSION=0.5.0 # Write the script header printf "flash-multi $VERSION\n\nThis program is Free Software and has NO WARRANTY.\nhttps://github.com/benlye/flash-multi/\n\n"; # Prepare simple help text to display when needed -USAGE="Usage: flash-multi [options] -f [firmware file] -p [serial device]\n\nOptions:\n -h Print this message and exit\n -r Read and display the firmware file information and exit\n -s Don't prompt for confirmation\n\n" +USAGE="Usage: flash-multi [options] -f [firmware file] -p [serial device]\n\nOptions:\n -h Print this message and exit\n -l Install legacy bootloader\n -r Read and display the firmware file information and exit\n -s Don't prompt for confirmation\n -b Baud rate (57600, 115200, 500000)\n\n" # Get the command line options -while getopts ":f:p:hrs" opt; do +while getopts ":f:p:b:hrsl" opt; do case $opt in f) FWFILE="$OPTARG" ;; @@ -38,8 +38,12 @@ while getopts ":f:p:hrs" opt; do ;; r) SHOWINFO="True" ;; + l) LEGACY="True" + ;; s) SILENT="True" ;; + b) BAUDRATE="$OPTARG" + ;; \?) printf "Invalid argument -$OPTARG\n\n"; >&2 ;; :) printf "Missing value for argument -$OPTARG\n\n"; >&2 @@ -65,6 +69,17 @@ if [ ! -r "$FWFILE" ]; then exit 2; fi +# Die if the baud rate isn't valid +if [ "x" != "x$BAUDRATE" ] && [ $BAUDRATE != "57600" ] && [ $BAUDRATE != "115200" ] && [ $BAUDRATE != "500000" ] ; then + printf "ERROR: $BAUDRATE is not a valid baud rate!\n\n"; + exit 2; +fi + +# Set the baud rate for stm32flash +if [ "x" == "x$BAUDRATE" ]; then + BAUDRATE=115200 +fi + function confirm() { while true; do read -p "$1 [Y]es or [N]o: " @@ -261,6 +276,13 @@ function get_signature() return; fi + # Determine if the specified firmware file contains support for the STM32 USB port + if grep -q $GREP_ARGS 'M\x00a\x00p\x00l\x00e\x00\x12\x03L\x00e\x00a\x00f\x00L\x00a\x00b\x00s' "$FWFILE"; then + FW_USBSERIAL_SUPPORT="True" + else + FW_USBSERIAL_SUPPORT="False" + fi + # Show the firmware information printf "Multi Firmware Version: $SIG_VERSION_STRING ($SIG_BOARD_TYPE_NAME)\n"; printf "Expected Channel Order: $FW_CHANNEL_ORDER\n"; @@ -268,6 +290,7 @@ function get_signature() printf "Invert Telemetry Enabled: $FW_INVERT_TELEMETRY_ENABLED\n"; printf "Flash From Radio Enabled: $FW_CHECK_FOR_BOOTLOADER_ENABLED\n"; printf "Bootloader Enabled: $FW_BOOTLOADER_SUPPORT\n"; + printf "USB Serial Support: $FW_USBSERIAL_SUPPORT\n"; printf "Serial Debug Enabled: $FW_DEBUG_SERIAL_ENABLED\n\n"; } @@ -385,19 +408,20 @@ if [[ $SIG_BOARD_TYPE_NAME == "AVR" ]]; then exit 0 fi - # STM32 Module Flashing # Set the path to the bootloader file -BOOTLOADERFILE="$DIR/bootloader/StmMulti4in1.bin" +if [[ $LEGACY == "True" ]]; then + BOOTLOADERFILE="$DIR/bootloader/StmMulti4in1_Legacy.bin" +else + BOOTLOADERFILE="$DIR/bootloader/StmMulti4in1_StickyDfu.bin" +fi -# Determine if the specified firmware file contains support for the STM32 USB port -if grep -q $GREP_ARGS 'M\x00a\x00p\x00l\x00e\x00\x12\x03L\x00e\x00a\x00f\x00L\x00a\x00b\x00s' "$FWFILE"; then - HAS_USB_SUPPORT=true; +# Set the parameters according to bootloader support +if [ $FW_BOOTLOADER_SUPPORT == "True" ]; then MAX_FILE_SIZE=120832 FLASH_START=8 EXEC_ADDR=0x8002000 else - HAS_USB_SUPPORT=false; MAX_FILE_SIZE=129024 FLASH_START=0 EXEC_ADDR=0x8000000 @@ -421,25 +445,25 @@ then fi STEP=1 - [ "$HAS_USB_SUPPORT" == true ] && NUM_STEPS=3 || NUM_STEPS=2; + [ $FW_BOOTLOADER_SUPPORT == "True" ] && NUM_STEPS=3 || NUM_STEPS=2; printf "[$STEP/$NUM_STEPS] Erasing flash...\n" - printf "$STM32_FLASH -o -S 0x8000000:129024 -b 115200 \"$PORT\"\n" - "${STM32_FLASH}" -o -S 0x8000000:129024 -b 115200 "$PORT" + printf "$STM32_FLASH -o -S 0x8000000:129024 -b $BAUDRATE \"$PORT\"\n" + "${STM32_FLASH}" -o -S 0x8000000:129024 -b $BAUDRATE "$PORT" [ $? -ne 0 ] && printf "ERROR: Failed to erase flash!\n\n" && exit 3; STEP=$((STEP+1)) - if [ "$HAS_USB_SUPPORT" == true ] ; then + if [ $FW_BOOTLOADER_SUPPORT == "True" ] ; then printf "[$STEP/$NUM_STEPS] Writing bootloader...\n" - printf "$STM32_FLASH -v -e 0 -g 0x8000000 -b 115200 -w \"$BOOTLOADERFILE\" \"$PORT\"\n" - "${STM32_FLASH}" -v -e 0 -g 0x8000000 -b 115200 -w "$BOOTLOADERFILE" "$PORT" + printf "$STM32_FLASH -v -e 0 -g 0x8000000 -b $BAUDRATE -w \"$BOOTLOADERFILE\" \"$PORT\"\n" + "${STM32_FLASH}" -v -e 0 -g 0x8000000 -b $BAUDRATE -w "$BOOTLOADERFILE" "$PORT" [ $? -ne 0 ] && printf "ERROR: Failed to write bootloader!\n\n" && exit 3; STEP=$((STEP+1)) fi printf "[$STEP/$NUM_STEPS] Writing firmware...\n" - printf "$STM32_FLASH -v -s $FLASH_START -e 0 -g $EXEC_ADDR -b 115200 -w \"$FWFILE\" \"$PORT\"\n" - "${STM32_FLASH}" -v -s $FLASH_START -e 0 -g $EXEC_ADDR -b 115200 -w "$FWFILE" "$PORT" + printf "$STM32_FLASH -v -s $FLASH_START -e 0 -g $EXEC_ADDR -b $BAUDRATE -w \"$FWFILE\" \"$PORT\"\n" + "${STM32_FLASH}" -v -s $FLASH_START -e 0 -g $EXEC_ADDR -b $BAUDRATE -w "$FWFILE" "$PORT" [ $? -ne 0 ] && printf "ERROR: Failed to write firmware!\n\n" && exit 3; else @@ -454,10 +478,16 @@ else printf "ERROR: Required tool $DFU_UTIL does not exist or is not executable!\n\n"; exit 3; fi - # Die if the firmware file doesn't contain USB code - if [ "$HAS_USB_SUPPORT" == false ]; then - printf "ERROR: Specified firmware file was not compiled with USB support.\nFlashing this file would make the MULTI-Module unusable.\n\n"; - exit 9; + # Warn if the firmware file doesn't contain USB code + if [ $FW_USBSERIAL_SUPPORT == "False" ]; then + printf "WARNING: Specified firmware file was not compiled with USB support.\n"; + printf " You MUST update the MULTI-module bootloader to the latest version BEFORE writing this firmware.\n\n"; + printf " See https://github.com/benlye/flash-multi/blob/master/doc/New_Bootloader.md for more information.\n\n"; + + if [[ "no" == $(confirm "Proceed with firmware update?") ]]; then + printf "\nFirmware update aborted.\n\n" + exit 9; + fi fi STEP=1; diff --git a/linux/multi-bootreloader b/linux/multi-bootreloader index 8a41b18..66170ad 100755 --- a/linux/multi-bootreloader +++ b/linux/multi-bootreloader @@ -19,21 +19,23 @@ shopt -s extglob # ********************************************************************* # Define the script version -VERSION=0.1.0 +VERSION=0.2.0 # Write the script header printf "multi-bootreloader $VERSION\n\nThis program is Free Software and has NO WARRANTY.\nhttps://github.com/benlye/flash-multi/\n\n"; # Prepare simple help text to display when needed -USAGE="Usage: multi-bootreloader [options] -p [serial device]\n\nOptions:\n -h Print this message and exit\n -s Don't prompt for confirmation\n\n" +USAGE="Usage: multi-bootreloader [options] -p [serial device]\n\nOptions:\n -h Print this message and exit\n -l Install legacy bootloader\n\n" # Get the command line options -while getopts ":f:p:h" opt; do +while getopts ":f:p:hl" opt; do case $opt in f) FWFILE="$OPTARG" ;; p) PORT="$OPTARG" ;; + l) LEGACY="True" + ;; h) printf "$USAGE"; exit 1 ;; \?) printf "Invalid argument -$OPTARG\n\n"; >&2 @@ -43,8 +45,12 @@ while getopts ":f:p:h" opt; do esac done -# FWFILE is BootReloader.bin -FWFILE=./tools/BootReloader.bin +# Pick the bootreloader file +if [[ $LEGACY == "True" ]]; then + FWFILE=./tools/BootReloader_Legacy.bin +else + FWFILE=./tools/BootReloader_StickyDfu.bin +fi # Die if the firmware file doesn't exist if [ ! -f "$FWFILE" ]; then diff --git a/linux/tools/BootReloader.bin b/linux/tools/BootReloader_Legacy.bin similarity index 100% rename from linux/tools/BootReloader.bin rename to linux/tools/BootReloader_Legacy.bin diff --git a/linux/tools/BootReloader_StickyDfu.bin b/linux/tools/BootReloader_StickyDfu.bin new file mode 100644 index 0000000..c27b286 Binary files /dev/null and b/linux/tools/BootReloader_StickyDfu.bin differ diff --git a/src/flash-multi/Devices/MapleDevice.cs b/src/flash-multi/Devices/MapleDevice.cs index 472d03c..25a218a 100644 --- a/src/flash-multi/Devices/MapleDevice.cs +++ b/src/flash-multi/Devices/MapleDevice.cs @@ -23,6 +23,7 @@ namespace Flash_Multi using System; using System.Collections.Generic; using System.Diagnostics; + using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -473,6 +474,74 @@ public static async Task WriteFlash(FlashMulti flashMulti, string fileName, stri } } + 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"); + 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); + 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"; @@ -607,19 +676,60 @@ public static async Task UpgradeBootloader(FlashMulti flashMulti, string c } // The bootreloader.bin file - string fileName = ".\\tools\\bootreloader.bin"; + 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"); - MessageBox.Show(Strings.failedToWriteBootReloader, Strings.dialogTitleErase, MessageBoxButtons.OK, MessageBoxIcon.Error); - flashMulti.EnableControls(true); - return false; + + 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"); + 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 diff --git a/src/flash-multi/Devices/SerialDevice.cs b/src/flash-multi/Devices/SerialDevice.cs index af11f03..9e0fa9c 100644 --- a/src/flash-multi/Devices/SerialDevice.cs +++ b/src/flash-multi/Devices/SerialDevice.cs @@ -20,7 +20,9 @@ namespace Flash_Multi { + using System.Collections; using System.Diagnostics; + using System.IO; using System.Linq; using System.Threading; using System.Threading.Tasks; @@ -222,7 +224,7 @@ public static async Task WriteFlash(FlashMulti flashMulti, string fileName, stri string command = ".\\tools\\stm32flash.exe"; // Path to the bootloader file - string bootLoaderPath = ".\\bootloaders\\StmMulti4in1.bin"; + string bootLoaderPath = ".\\bootloaders\\StmMulti4in1_StickyDfu.bin"; // Baud rate for serial flash commands int serialBaud = Properties.Settings.Default.SerialBaudRate; @@ -234,7 +236,7 @@ public static async Task WriteFlash(FlashMulti flashMulti, string fileName, stri int returnCode = -1; // First step in flash process - int flashStep = 1; + int flashStep = 0; // Total number of steps in flash process int flashSteps = 2; @@ -257,7 +259,7 @@ public static async Task WriteFlash(FlashMulti flashMulti, string fileName, stri if (writeBootloader) { // Increase the total number of steps - flashSteps = 3; + flashSteps++; // The bootloader occupies the first 8 pages (0-7), so start writing after it flashStart = 8; @@ -299,7 +301,54 @@ public static async Task WriteFlash(FlashMulti flashMulti, string fileName, stri return; } - // Erase the flash + 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 diff --git a/src/flash-multi/Dialogs/DfuRecoveryDialog.cs b/src/flash-multi/Dialogs/DfuRecoveryDialog.cs index 6a1383f..9feae68 100644 --- a/src/flash-multi/Dialogs/DfuRecoveryDialog.cs +++ b/src/flash-multi/Dialogs/DfuRecoveryDialog.cs @@ -21,7 +21,6 @@ namespace Flash_Multi { using System; - using System.Diagnostics; using System.Threading.Tasks; using System.Windows.Forms; diff --git a/src/flash-multi/Dialogs/DfuRecoveryDialog.resx b/src/flash-multi/Dialogs/DfuRecoveryDialog.resx index c20f6a0..f00d892 100644 --- a/src/flash-multi/Dialogs/DfuRecoveryDialog.resx +++ b/src/flash-multi/Dialogs/DfuRecoveryDialog.resx @@ -207,10 +207,10 @@ Flashing will continue automatically when the module is plugged back in. - 19, 13 + 13, 13 - 30, 34 + 34, 34 2 @@ -280,7 +280,7 @@ Flashing will continue automatically when the module is plugged back in. - CenterScreen + CenterParent DFU Recovery Mode diff --git a/src/flash-multi/Dialogs/UsbSupportErrorDialog.Designer.cs b/src/flash-multi/Dialogs/UsbSupportErrorDialog.Designer.cs new file mode 100644 index 0000000..22ff9c7 --- /dev/null +++ b/src/flash-multi/Dialogs/UsbSupportErrorDialog.Designer.cs @@ -0,0 +1,124 @@ +namespace Flash_Multi +{ + partial class UsbSupportErrorDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UsbSupportErrorDialog)); + this.panel2 = new System.Windows.Forms.Panel(); + this.moreInfoLinkLabel = new System.Windows.Forms.LinkLabel(); + this.dialogText = new System.Windows.Forms.Label(); + this.errorIcon = new System.Windows.Forms.PictureBox(); + this.buttonOK = new System.Windows.Forms.Button(); + this.panel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.errorIcon)).BeginInit(); + this.SuspendLayout(); + // + // panel2 + // + this.panel2.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.panel2.Controls.Add(this.moreInfoLinkLabel); + this.panel2.Controls.Add(this.dialogText); + this.panel2.Controls.Add(this.errorIcon); + this.panel2.Location = new System.Drawing.Point(0, 0); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(405, 147); + this.panel2.TabIndex = 6; + // + // moreInfoLinkLabel + // + this.moreInfoLinkLabel.AutoSize = true; + this.moreInfoLinkLabel.LinkArea = new System.Windows.Forms.LinkArea(6, 4); + this.moreInfoLinkLabel.Location = new System.Drawing.Point(57, 114); + this.moreInfoLinkLabel.Name = "moreInfoLinkLabel"; + this.moreInfoLinkLabel.Size = new System.Drawing.Size(162, 17); + this.moreInfoLinkLabel.TabIndex = 3; + this.moreInfoLinkLabel.TabStop = true; + this.moreInfoLinkLabel.Text = "Click here for more information."; + this.moreInfoLinkLabel.UseCompatibleTextRendering = true; + this.moreInfoLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.MoreInfoLinkLabel_LinkClicked); + // + // dialogText + // + this.dialogText.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.dialogText.Location = new System.Drawing.Point(54, 13); + this.dialogText.Name = "dialogText"; + this.dialogText.Size = new System.Drawing.Size(306, 101); + this.dialogText.TabIndex = 0; + this.dialogText.Text = resources.GetString("dialogText.Text"); + // + // errorIcon + // + this.errorIcon.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.errorIcon.Location = new System.Drawing.Point(13, 13); + this.errorIcon.Name = "errorIcon"; + this.errorIcon.Size = new System.Drawing.Size(34, 34); + this.errorIcon.TabIndex = 2; + this.errorIcon.TabStop = false; + // + // buttonOK + // + this.buttonOK.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.buttonOK.Location = new System.Drawing.Point(325, 153); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.Size = new System.Drawing.Size(67, 24); + this.buttonOK.TabIndex = 7; + this.buttonOK.TabStop = false; + this.buttonOK.Text = "OK"; + this.buttonOK.UseVisualStyleBackColor = true; + this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click); + // + // UsbSupportErrorDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(404, 187); + this.ControlBox = false; + this.Controls.Add(this.buttonOK); + this.Controls.Add(this.panel2); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "UsbSupportErrorDialog"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "USB Support Error"; + this.panel2.ResumeLayout(false); + this.panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.errorIcon)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.Label dialogText; + private System.Windows.Forms.PictureBox errorIcon; + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.LinkLabel moreInfoLinkLabel; + } +} \ No newline at end of file diff --git a/src/flash-multi/Dialogs/UsbSupportErrorDialog.cs b/src/flash-multi/Dialogs/UsbSupportErrorDialog.cs new file mode 100644 index 0000000..bfe4cf2 --- /dev/null +++ b/src/flash-multi/Dialogs/UsbSupportErrorDialog.cs @@ -0,0 +1,91 @@ +// ------------------------------------------------------------------------------- +// +// Copyright 2020 Ben Lye +// +// This file is part of Flash Multi. +// +// Flash Multi is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or(at your option) any later +// version. +// +// Flash Multi is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with +// Flash Multi. If not, see http://www.gnu.org/licenses/. +// +// ------------------------------------------------------------------------------- + +namespace Flash_Multi +{ + using System; + using System.Diagnostics; + using System.Windows.Forms; + + /// + /// Class for the USB Support warning dialog. + /// + public partial class UsbSupportErrorDialog : Form + { + /// + /// Initializes a new instance of the class. + /// + public UsbSupportErrorDialog() + { + this.InitializeComponent(); + } + + /// + /// Set the icon when the dialog is loaded. + /// + protected override void OnShown(EventArgs e) + { + this.errorIcon.Image = System.Drawing.SystemIcons.Error.ToBitmap(); + } + + /// + /// Handles the Cancel button being clicked. + /// + private void ButtonCancel_Click(object sender, EventArgs e) + { + // Return Cancel + this.DialogResult = DialogResult.Cancel; + this.Close(); + return; + } + + /// + /// Handles the OK button being clicked. + /// + private void ButtonOK_Click(object sender, EventArgs e) + { + // Return OK + this.DialogResult = DialogResult.OK; + this.Close(); + return; + } + + /// + /// Opens a URL in the default browser. + /// + /// The URL to open. + private void OpenLink(string url) + { + try + { + System.Diagnostics.Process.Start(url); + } + catch (Exception ex) + { + Debug.WriteLine(ex.Message); + } + } + + private void MoreInfoLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + this.OpenLink("https://github.com/benlye/flash-multi/blob/master/doc/New_Bootloader.md"); + } + } +} diff --git a/src/flash-multi/Dialogs/UsbSupportErrorDialog.resx b/src/flash-multi/Dialogs/UsbSupportErrorDialog.resx new file mode 100644 index 0000000..2d5e409 --- /dev/null +++ b/src/flash-multi/Dialogs/UsbSupportErrorDialog.resx @@ -0,0 +1,125 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + The selected firmware file was compiled without USB serial support and the 'USB Port Mode' setting is set to 'COM Port (Legacy)'. + +The MULTI-Module bootloader must be updated and the 'USB Port Mode' setting set to 'Sticky DFU Mode (New)' in order to write this firmware. + + \ No newline at end of file diff --git a/src/flash-multi/Dialogs/UsbSupportWarningDialog.Designer.cs b/src/flash-multi/Dialogs/UsbSupportWarningDialog.Designer.cs new file mode 100644 index 0000000..adf29b1 --- /dev/null +++ b/src/flash-multi/Dialogs/UsbSupportWarningDialog.Designer.cs @@ -0,0 +1,157 @@ +namespace Flash_Multi +{ + partial class UsbSupportWarningDialog + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(UsbSupportWarningDialog)); + this.buttonCancel = new System.Windows.Forms.Button(); + this.panel2 = new System.Windows.Forms.Panel(); + this.moreInfoLinkLabel = new System.Windows.Forms.LinkLabel(); + this.dialogText = new System.Windows.Forms.Label(); + this.warningIcon = new System.Windows.Forms.PictureBox(); + this.buttonOK = new System.Windows.Forms.Button(); + this.disableUsbWarning = new System.Windows.Forms.CheckBox(); + this.panel2.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.warningIcon)).BeginInit(); + this.SuspendLayout(); + // + // buttonCancel + // + this.buttonCancel.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.buttonCancel.Location = new System.Drawing.Point(322, 157); + this.buttonCancel.Name = "buttonCancel"; + this.buttonCancel.Size = new System.Drawing.Size(67, 24); + this.buttonCancel.TabIndex = 5; + this.buttonCancel.TabStop = false; + this.buttonCancel.Text = "Cancel"; + this.buttonCancel.UseVisualStyleBackColor = true; + this.buttonCancel.Click += new System.EventHandler(this.ButtonCancel_Click); + // + // panel2 + // + this.panel2.BackColor = System.Drawing.SystemColors.ControlLightLight; + this.panel2.Controls.Add(this.moreInfoLinkLabel); + this.panel2.Controls.Add(this.dialogText); + this.panel2.Controls.Add(this.warningIcon); + this.panel2.Location = new System.Drawing.Point(0, 0); + this.panel2.Name = "panel2"; + this.panel2.Size = new System.Drawing.Size(405, 147); + this.panel2.TabIndex = 6; + // + // moreInfoLinkLabel + // + this.moreInfoLinkLabel.AutoSize = true; + this.moreInfoLinkLabel.LinkArea = new System.Windows.Forms.LinkArea(6, 4); + this.moreInfoLinkLabel.Location = new System.Drawing.Point(54, 65); + this.moreInfoLinkLabel.Name = "moreInfoLinkLabel"; + this.moreInfoLinkLabel.Size = new System.Drawing.Size(162, 17); + this.moreInfoLinkLabel.TabIndex = 3; + this.moreInfoLinkLabel.TabStop = true; + this.moreInfoLinkLabel.Text = "Click here for more information."; + this.moreInfoLinkLabel.UseCompatibleTextRendering = true; + this.moreInfoLinkLabel.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.MoreInfoLinkLabel_LinkClicked); + // + // dialogText + // + this.dialogText.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.dialogText.Location = new System.Drawing.Point(54, 13); + this.dialogText.Name = "dialogText"; + this.dialogText.Size = new System.Drawing.Size(306, 101); + this.dialogText.TabIndex = 0; + this.dialogText.Text = "The selected firmware file was compiled without USB serial support. The MULTI-Mo" + + "dule bootloader should be updated before writing this firmware.\r\n\r\n\r\n\r\nClick OK " + + "to write the firmware."; + // + // warningIcon + // + this.warningIcon.Image = ((System.Drawing.Image)(resources.GetObject("warningIcon.Image"))); + this.warningIcon.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.warningIcon.Location = new System.Drawing.Point(13, 13); + this.warningIcon.Name = "warningIcon"; + this.warningIcon.Size = new System.Drawing.Size(34, 34); + this.warningIcon.TabIndex = 2; + this.warningIcon.TabStop = false; + // + // buttonOK + // + this.buttonOK.ImeMode = System.Windows.Forms.ImeMode.NoControl; + this.buttonOK.Location = new System.Drawing.Point(249, 157); + this.buttonOK.Name = "buttonOK"; + this.buttonOK.Size = new System.Drawing.Size(67, 24); + this.buttonOK.TabIndex = 7; + this.buttonOK.TabStop = false; + this.buttonOK.Text = "OK"; + this.buttonOK.UseVisualStyleBackColor = true; + this.buttonOK.Click += new System.EventHandler(this.ButtonOK_Click); + // + // disableUsbWarning + // + this.disableUsbWarning.AutoSize = true; + this.disableUsbWarning.Location = new System.Drawing.Point(57, 160); + this.disableUsbWarning.Name = "disableUsbWarning"; + this.disableUsbWarning.Size = new System.Drawing.Size(179, 17); + this.disableUsbWarning.TabIndex = 3; + this.disableUsbWarning.Text = "Do not show this message again"; + this.disableUsbWarning.UseVisualStyleBackColor = true; + // + // UsbSupportWarningDialog + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(404, 187); + this.ControlBox = false; + this.Controls.Add(this.disableUsbWarning); + this.Controls.Add(this.buttonOK); + this.Controls.Add(this.buttonCancel); + this.Controls.Add(this.panel2); + this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle; + this.MaximizeBox = false; + this.MinimizeBox = false; + this.Name = "UsbSupportWarningDialog"; + this.ShowInTaskbar = false; + this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; + this.Text = "USB Support Warning"; + this.panel2.ResumeLayout(false); + this.panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.warningIcon)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Button buttonCancel; + private System.Windows.Forms.Panel panel2; + private System.Windows.Forms.Label dialogText; + private System.Windows.Forms.PictureBox warningIcon; + private System.Windows.Forms.Button buttonOK; + private System.Windows.Forms.CheckBox disableUsbWarning; + private System.Windows.Forms.LinkLabel moreInfoLinkLabel; + } +} \ No newline at end of file diff --git a/src/flash-multi/Dialogs/UsbSupportWarningDialog.cs b/src/flash-multi/Dialogs/UsbSupportWarningDialog.cs new file mode 100644 index 0000000..084d0ec --- /dev/null +++ b/src/flash-multi/Dialogs/UsbSupportWarningDialog.cs @@ -0,0 +1,97 @@ +// ------------------------------------------------------------------------------- +// +// Copyright 2020 Ben Lye +// +// This file is part of Flash Multi. +// +// Flash Multi is free software: you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free Software +// Foundation, either version 3 of the License, or(at your option) any later +// version. +// +// Flash Multi is distributed in the hope that it will be useful, but WITHOUT +// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +// FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License along with +// Flash Multi. If not, see http://www.gnu.org/licenses/. +// +// ------------------------------------------------------------------------------- + +namespace Flash_Multi +{ + using System; + using System.Diagnostics; + using System.Windows.Forms; + + /// + /// Class for the USB Support warning dialog. + /// + public partial class UsbSupportWarningDialog : Form + { + /// + /// Initializes a new instance of the class. + /// + public UsbSupportWarningDialog() + { + this.InitializeComponent(); + } + + /// + /// Set the icon when the dialog is loaded. + /// + protected override void OnShown(EventArgs e) + { + this.warningIcon.Image = System.Drawing.SystemIcons.Warning.ToBitmap(); + } + + /// + /// Handles the Cancel button being clicked. + /// + private void ButtonCancel_Click(object sender, EventArgs e) + { + // Return Cancel + this.DialogResult = DialogResult.Cancel; + this.Close(); + return; + } + + /// + /// Handles the OK button being clicked. + /// + private void ButtonOK_Click(object sender, EventArgs e) + { + // Disable the warning if the box was checked + if (this.disableUsbWarning.Checked == true) + { + Properties.Settings.Default.WarnIfNoUSB = false; + } + + // Return OK + this.DialogResult = DialogResult.OK; + this.Close(); + return; + } + + /// + /// Opens a URL in the default browser. + /// + /// The URL to open. + private void OpenLink(string url) + { + try + { + System.Diagnostics.Process.Start(url); + } + catch (Exception ex) + { + Debug.WriteLine(ex.Message); + } + } + + private void MoreInfoLinkLabel_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) + { + this.OpenLink("https://github.com/benlye/flash-multi/blob/master/doc/New_Bootloader.md"); + } + } +} diff --git a/src/flash-multi/Dialogs/UsbSupportWarningDialog.resx b/src/flash-multi/Dialogs/UsbSupportWarningDialog.resx new file mode 100644 index 0000000..531ff04 --- /dev/null +++ b/src/flash-multi/Dialogs/UsbSupportWarningDialog.resx @@ -0,0 +1,156 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAABGdBTUEAALGPC/xhBQAAAAlwSFlzAAAO + wwAADsMBx2+oZAAABt1JREFUWEftVntMW9cdvkBtEiqWpVvSZGwJA5SGPqZVTVuSjqxLQqXSpdmUpZ2S + JZXa0EjTUrVaknV/bOv+mbqQFwb72hjbsXkFDMYmBhtsZuJXsA0mvAkpyrJAIDYYO5hg1rTffte+Wztt + Uro2qTZpn/TpXN9zzu/7ve45Zv6P/0nIlQpBk8HwXmND47tyueK7/OsvDyqVcpvB0DJnaXeAHCiWSNhk + fur+g2Ul36yuqbtms5lgtzfAYDAtyWTlP+On7z8UCvnxRp0N5ubDuGheB4vFDLVG202ZeIhfcv8glbLP + aLXNUZ2uAcPulZi4IoS1YSdazD5QFn7PL7s/YFk2pbKySmc02tFavxsAE2df51fQYT4LbYP5xqlTJx/j + l997UPQ/bW7uuNPaWoPx7tR/OICPGFhqtsLhHKYsKAjKJH7LvYNEIl5ZU1M35nAMUsoLE8KLPMmBfuuD + 8DoqYDK7YzKpbDu/7d5BJpMda2u7iAs2Flc8qZCKn8KRd3bg6JFt+N1vCvCBPx3Ohifh7hpATW19e3m5 + PJXf+sUhFos36vUtgR6/H+7WfPw1yuDw4SIUFf0WB4vexYEDR+A0rceENx2u1l/D1TX0cUmJ6HV++xcD + NV6yWq0uHxr+Cy46T+DPA0Iszafg2NF9OHToHXLi59h/4HW4TZlAaBk6Kx/D1I1pNOlNwywrzeDNfH6I + xaXft1hdt7s8LozYv0X1TsKdqIDS/2Ps3fcmXnl1H3a+vAseE80FVuGGOw127UFMBxZAZXifN/P5QKlP + ra6u9U7fvAWH6U3MTwiBhYcQm0nD228VoPClV1Dwwkt4/vkfwGNcA1z/GpZGlsGhycBY/5/Q6fDepAx+ + hzf3n4OO3CK7w3/H4zFg3P0wEF5BXItYMA2/OLQFz+btIH4PW/O3wGdcBYynY3HgQUy0pcBW9SJmQ7eh + Vldp6J5I4U1+dlDqMxp1zdemb87B1rSLhNMpxd8AZjIQm05H0YEnkPtoHjY9/RxeKMhHv2klcFmIhW4B + Fn0M/JVCdLWegMc3EhWJRC/yZj87FAqVZnBoAhcdClx1fh0IrsFHExnAxBosjKzE7sJVWLZ8Ndatz0H+ + c0+it1GAD0k47CBeILYxaC3Jpl4Ioa6+yUHH9Are9N1BtX/c0GyeGR0dgaNxOzApRGwsDdGBZEoxgzkP + g4LNDGgphKkrsCUvFz01SViwMZg1E43kANHPCqkhfwXfpXFIWekbCet3ATWNQKXSWEcvT6JdW4QZTzKi + PWTQyyDkZjDfxeAWjTvzEw48vDYLu3flY6AuCdF2Em8mGhjM6GnUMTAXr4bPZYFO3zJKpbj7Z0mNt8vY + YrtjNjegT5eO2yTORTxHoiEnibsY3Kbf+ws5Bx5AZs7T2LtnBwbPkQNc9CQ808Qg2EAj8bIsBS2Sl+H2 + jYHOhT/yMv8eEonkq1XV50acrj60Vf8IgQvJmKOIQyTKiYfsRK6+nXQDqhmcf58uoRIGXjmDSW0i8iBF + HSDhQB2D6Vp6d46BvViINu1JnDd1hqVS6SZe7l9RLq842Wb1oUV/BkM6IcKcODXV34VnO4gWygKxR8ng + zNsM3isSovU4gyjVPEhOcMIBEp2qIVYRKxl8IE2B4cQzsLsGoFKp63m5fwZFn1l7TjdpMplhqd6OoC05 + ETUJh6i5Qpw41XiOGKXnY3u5EgiwOuMpHNybhysaWsNFTuJc5HFxnkFyxkVZMCiPoqXduURNvpOX/QRK + pUpnNDlxnrp2VC+kZhMg7KIsOGjkStGZhLA1Ib5AJdizjXMgDZs278Br+19FXwXtOc+V4AGqvwABrTDO + oFZAvSDENU0KlSwbVosNZzW1zjOnz3zyWVLj5dVr9fOGprNwaAvw8eVsxAZyEbu0ETH/I4j1bMBidw5i + PnrvzQL8mfBo1uGH23Ow5yeFUPxhK2bM38aifSPmO3Jxq+NRzNs45sYZJS7ZH0Gfai30soNoNtoglrBv + 8fIMo9FUWkzmTvqb9Ut0V2XCV7kBPjVRRVTmfIrZ8Cqz4vQTndIsWE6vh0tKDsmz0SXfgK5ynvTs+RS9 + xG7aY5U8i3ajHrV1umunTp3OSjhQWdXn8Xajv9eDgV4v0YfB3h4M9fkx3N+L8bFhXL86jsDUDYSCAczN + cgwizDEUjD9znA1MYWryOqYmruPq2ChGB/vi+zk7nL0Bf8LuJX8vrNbOD/PyNhfEHSg+XlwmlcpmRaKy + iEgkSbBUEiktYyNlEjYiYWURlq2IsNKKiLRCEamoUCaoUEXoyI6P9DvMkebDtC7MsvKwhJWGy8RsmOyE + yV64RCQOi4ilpZyOqGf58rTMuAM8uGvzy+Z/Axjmb16JL+4sqeK+AAAAAElFTkSuQmCC + + + \ No newline at end of file diff --git a/src/flash-multi/FileUtils.cs b/src/flash-multi/FileUtils.cs index 4e447ce..1e4f0d6 100644 --- a/src/flash-multi/FileUtils.cs +++ b/src/flash-multi/FileUtils.cs @@ -48,10 +48,10 @@ internal class FileUtils /// /// Parses the binary file looking for a string which indicates that the compiled firmware images contains USB support. - /// The binary firmware file will contain the strings 'Maple' and 'LeafLabs' if it was compiled with support for the USB / Flash from TX bootloader. + /// The binary firmware file will contain the strings 'Maple' and 'LeafLabs' if it was compiled with USB serial support. /// /// The path to the firmware file. - /// A boolean value indicatating whether or not the firmware supports USB. + /// A boolean value indicatating whether or not the firmware supports USB serial. internal static bool CheckForUsbSupport(string filename) { bool usbSupportEnabled = false; @@ -59,17 +59,24 @@ internal static bool CheckForUsbSupport(string filename) // Get the file size long length = new System.IO.FileInfo(filename).Length; - // File is too small to contain a USB support + // File is too small to contain USB support if (length < 8192) { return usbSupportEnabled; } + // Parse the file and find the first instance of the signature byte[] byteBuffer = File.ReadAllBytes(filename); string byteBufferAsString = System.Text.Encoding.ASCII.GetString(byteBuffer); - int offset = byteBufferAsString.IndexOf("M\0a\0p\0l\0e\0\u0012\u0003L\0e\0a\0f\0L\0a\0b\0s\0\u0012\u0001"); - if (offset > 0) + // Find the signature + int signatureOffset = byteBufferAsString.IndexOf("multi-"); + + // Look for the USB string + int usbOffset = byteBufferAsString.IndexOf("M\0a\0p\0l\0e\0\u0012\u0003L\0e\0a\0f\0L\0a\0b\0s\0\u0012\u0001"); + + // If we found the usb offset before the signature, or we found the USB offset without a signature, USB is enabled + if ((usbOffset > 0 && signatureOffset > 0 && usbOffset < signatureOffset) || (usbOffset > 0 && signatureOffset == 0)) { usbSupportEnabled = true; } @@ -174,23 +181,53 @@ internal static bool CheckFirmwareFileSize(string filename) // Get the file size long length = new System.IO.FileInfo(filename).Length; - // If the file is very large we don't want to check for USB support so throw a generic error - if (length > 256000) + // Absolute max size is 128KB + int maxFileSize = 128 * 1024; + + // If the file is larger than the max flash space we don't need any more checks + if (length > maxFileSize) { MessageBox.Show("Selected firmware file is too large.", "Firmware File Error", MessageBoxButtons.OK, MessageBoxIcon.Error); return false; } - // If the file is smaller we can check if it has USB support and throw a more specific error - int maxFileSize = CheckForUsbSupport(filename) ? 120832 : 129024; + // If the file is smaller we can check if it has bootloader support and do a more exact check + FirmwareFile fileDetails = GetFirmwareSignature(filename); + if (fileDetails == null) + { + // Warn that we can't accurately check the file size + string sizeMessage = $"Firmware file does not have a signature - unable to validate the size accurately."; + DialogResult sizeWarning = MessageBox.Show(sizeMessage, "Firmware File Size", MessageBoxButtons.OKCancel, MessageBoxIcon.Warning); + if (sizeWarning != DialogResult.OK) + { + return false; + } + } + else + { + switch (fileDetails.ModuleType) + { + case "AVR": + maxFileSize = fileDetails.BootloaderSupport ? 32232 : 32744; + break; + case "STM32": + maxFileSize = fileDetails.BootloaderSupport ? 120832 : 129024; + break; + } + } - // Check if the file contains EEPROM data - byte[] eePromData = Stm32EepromUtils.GetEepromDataFromBackup(filename); - if (eePromData != null && Stm32EepromUtils.FindValidPage(eePromData) >= 0) + // Check if the file contains EEPROM data if it is for an STM32 + if (fileDetails.ModuleType == "STM32") { - maxFileSize += 2048; + byte[] eePromData = Stm32EepromUtils.GetEepromDataFromBackup(filename); + if (eePromData != null && Stm32EepromUtils.FindValidPage(eePromData) >= 0) + { + maxFileSize += 2048; + } } + Debug.WriteLine($"Selected file is {length / 1024:n0} KB, maximum size is {maxFileSize / 1024:n0} KB."); + if (length > maxFileSize) { string sizeMessage = $"Firmware file is too large.\r\n\r\nSelected file is {length / 1024:n0} KB, maximum size is {maxFileSize / 1024:n0} KB."; @@ -219,32 +256,14 @@ internal static FirmwareFile GetFirmwareSignature(string filename) return null; } - // Read the last 24 bytes of the binary file so we can see if it contains a signature string - using (var reader = new StreamReader(filename)) - { - if (reader.BaseStream.Length > 24) - { - reader.BaseStream.Seek(-24, SeekOrigin.End); - } - - string line; - while ((line = reader.ReadLine()) != null) - { - signature = line; - } - } + // Parse the file and find the first instance of the signature + byte[] byteBuffer = File.ReadAllBytes(filename); + string byteBufferAsString = System.Text.Encoding.ASCII.GetString(byteBuffer); + int offset = byteBufferAsString.IndexOf("multi-"); - // Parse the entire file if we didn't find the signature in the last 24 bytes - if (signature != string.Empty && signature.Substring(0, 6) != "multi-") + if (offset > 0) { - byte[] byteBuffer = File.ReadAllBytes(filename); - string byteBufferAsString = System.Text.Encoding.ASCII.GetString(byteBuffer); - int offset = byteBufferAsString.IndexOf("multi-"); - - if (offset > 0) - { - signature = byteBufferAsString.Substring(offset, 24); - } + signature = byteBufferAsString.Substring(offset, 24); } Debug.WriteLine(signature); @@ -299,7 +318,7 @@ internal static FirmwareFile GetFirmwareSignature(string filename) int.TryParse(versionString.Substring(6, 2), out int versionPatch); string parsedVersion = versionMajor + "." + versionMinor + "." + versionRevision + "." + versionPatch; - // Create the firmware file signatre and return it + // Create the firmware file signature and return it FirmwareFile file = new FirmwareFile { Signature = signature, @@ -446,8 +465,8 @@ internal static void SaveFirmwareBackup(FlashMulti flashMulti, string flashFileN b.Write(firmwareData); } - flashMulti.AppendLog($"\r\n\r\nMULTI-Module firmware saved succesfully"); - flashMulti.AppendVerbose($"Firmware saved to '{flashFileName}'"); + 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 @@ -488,8 +507,8 @@ internal static void SaveFirmwareBackup(FlashMulti flashMulti, string flashFileN b.Write(firmwareData); } - flashMulti.AppendLog($"\r\nMULTI-Module EEPROM saved succesfully"); - flashMulti.AppendVerbose($"EEPROM saved to '{eepromFileName}'"); + flashMulti.AppendLog($"\r\nMULTI-Module EEPROM saved successfully"); + flashMulti.AppendVerbose($"EEPROM saved to '{saveFileDialog.FileName}'"); } } } @@ -560,6 +579,11 @@ internal class FirmwareFile /// public bool InvertTelemetry { get; set; } + /// + /// Gets or sets a value indicating whether the firmware was compiled with USB Serial support. + /// + public bool UsbSerial { get; set; } + /// /// Gets or sets a value indicating whether the firmware was compiled with DEBUG_SERIAL defined. /// diff --git a/src/flash-multi/FlashMulti.Designer.cs b/src/flash-multi/FlashMulti.Designer.cs index 9413a04..75d475e 100644 --- a/src/flash-multi/FlashMulti.Designer.cs +++ b/src/flash-multi/FlashMulti.Designer.cs @@ -75,16 +75,21 @@ private void InitializeComponent() this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.exitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.advancedToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.actionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.installUSBDriversToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.resetToDFUModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.upgradeBootloaderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.settingsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.baudRateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItemBaudRate57600 = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItemBaudRate115200 = new System.Windows.Forms.ToolStripMenuItem(); - this.runAfterUploadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItemBaudRate500000 = new System.Windows.Forms.ToolStripMenuItem(); + this.bootloaderTypeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.stickyDfuUsbModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.comPortUsbModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.disableCompatibilityCheckToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.enableDeviceDetectionToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.runAfterUploadToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.actionsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.installUSBDriversToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.resetToDFUModeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.upgradeBootloaderToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.helpToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.checkForUpdateToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.documentationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); @@ -284,44 +289,19 @@ private void InitializeComponent() // advancedToolStripMenuItem // this.advancedToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.actionsToolStripMenuItem, - this.settingsToolStripMenuItem}); + this.settingsToolStripMenuItem, + this.actionsToolStripMenuItem}); this.advancedToolStripMenuItem.Name = "advancedToolStripMenuItem"; resources.ApplyResources(this.advancedToolStripMenuItem, "advancedToolStripMenuItem"); // - // actionsToolStripMenuItem - // - this.actionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.installUSBDriversToolStripMenuItem, - this.resetToDFUModeToolStripMenuItem, - this.upgradeBootloaderToolStripMenuItem}); - this.actionsToolStripMenuItem.Name = "actionsToolStripMenuItem"; - resources.ApplyResources(this.actionsToolStripMenuItem, "actionsToolStripMenuItem"); - // - // installUSBDriversToolStripMenuItem - // - this.installUSBDriversToolStripMenuItem.Name = "installUSBDriversToolStripMenuItem"; - resources.ApplyResources(this.installUSBDriversToolStripMenuItem, "installUSBDriversToolStripMenuItem"); - this.installUSBDriversToolStripMenuItem.Click += new System.EventHandler(this.InstallUSBDriversToolStripMenuItem_Click); - // - // resetToDFUModeToolStripMenuItem - // - this.resetToDFUModeToolStripMenuItem.Name = "resetToDFUModeToolStripMenuItem"; - resources.ApplyResources(this.resetToDFUModeToolStripMenuItem, "resetToDFUModeToolStripMenuItem"); - this.resetToDFUModeToolStripMenuItem.Click += new System.EventHandler(this.ResetToDFUModeToolStripMenuItem_Click); - // - // upgradeBootloaderToolStripMenuItem - // - this.upgradeBootloaderToolStripMenuItem.Name = "upgradeBootloaderToolStripMenuItem"; - resources.ApplyResources(this.upgradeBootloaderToolStripMenuItem, "upgradeBootloaderToolStripMenuItem"); - this.upgradeBootloaderToolStripMenuItem.Click += new System.EventHandler(this.UpgradeBootloaderToolStripMenuItem_Click); - // // settingsToolStripMenuItem // this.settingsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.baudRateToolStripMenuItem, - this.runAfterUploadToolStripMenuItem, - this.enableDeviceDetectionToolStripMenuItem}); + this.bootloaderTypeToolStripMenuItem, + this.disableCompatibilityCheckToolStripMenuItem, + this.enableDeviceDetectionToolStripMenuItem, + this.runAfterUploadToolStripMenuItem}); this.settingsToolStripMenuItem.Name = "settingsToolStripMenuItem"; resources.ApplyResources(this.settingsToolStripMenuItem, "settingsToolStripMenuItem"); // @@ -329,7 +309,8 @@ private void InitializeComponent() // this.baudRateToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripMenuItemBaudRate57600, - this.toolStripMenuItemBaudRate115200}); + this.toolStripMenuItemBaudRate115200, + this.toolStripMenuItemBaudRate500000}); this.baudRateToolStripMenuItem.Name = "baudRateToolStripMenuItem"; resources.ApplyResources(this.baudRateToolStripMenuItem, "baudRateToolStripMenuItem"); // @@ -345,11 +326,38 @@ private void InitializeComponent() resources.ApplyResources(this.toolStripMenuItemBaudRate115200, "toolStripMenuItemBaudRate115200"); this.toolStripMenuItemBaudRate115200.Click += new System.EventHandler(this.ToolStripMenuItemBaudRate115200_Click); // - // runAfterUploadToolStripMenuItem + // toolStripMenuItemBaudRate500000 // - this.runAfterUploadToolStripMenuItem.CheckOnClick = true; - this.runAfterUploadToolStripMenuItem.Name = "runAfterUploadToolStripMenuItem"; - resources.ApplyResources(this.runAfterUploadToolStripMenuItem, "runAfterUploadToolStripMenuItem"); + this.toolStripMenuItemBaudRate500000.Name = "toolStripMenuItemBaudRate500000"; + resources.ApplyResources(this.toolStripMenuItemBaudRate500000, "toolStripMenuItemBaudRate500000"); + this.toolStripMenuItemBaudRate500000.Click += new System.EventHandler(this.ToolStripMenuItemBaudRate500000_Click); + // + // bootloaderTypeToolStripMenuItem + // + this.bootloaderTypeToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.stickyDfuUsbModeToolStripMenuItem, + this.comPortUsbModeToolStripMenuItem}); + this.bootloaderTypeToolStripMenuItem.Name = "bootloaderTypeToolStripMenuItem"; + resources.ApplyResources(this.bootloaderTypeToolStripMenuItem, "bootloaderTypeToolStripMenuItem"); + // + // stickyDfuUsbModeToolStripMenuItem + // + this.stickyDfuUsbModeToolStripMenuItem.Name = "stickyDfuUsbModeToolStripMenuItem"; + resources.ApplyResources(this.stickyDfuUsbModeToolStripMenuItem, "stickyDfuUsbModeToolStripMenuItem"); + this.stickyDfuUsbModeToolStripMenuItem.Click += new System.EventHandler(this.StickyDfuUsbModeToolStripMenuItem_Click); + // + // comPortUsbModeToolStripMenuItem + // + this.comPortUsbModeToolStripMenuItem.Name = "comPortUsbModeToolStripMenuItem"; + resources.ApplyResources(this.comPortUsbModeToolStripMenuItem, "comPortUsbModeToolStripMenuItem"); + this.comPortUsbModeToolStripMenuItem.Click += new System.EventHandler(this.ComPortUsbModeToolStripMenuItem_Click); + // + // disableCompatibilityCheckToolStripMenuItem + // + this.disableCompatibilityCheckToolStripMenuItem.CheckOnClick = true; + this.disableCompatibilityCheckToolStripMenuItem.Name = "disableCompatibilityCheckToolStripMenuItem"; + resources.ApplyResources(this.disableCompatibilityCheckToolStripMenuItem, "disableCompatibilityCheckToolStripMenuItem"); + this.disableCompatibilityCheckToolStripMenuItem.Click += new System.EventHandler(this.DisableCompatibilityCheckToolStripMenuItem_Click); // // enableDeviceDetectionToolStripMenuItem // @@ -358,6 +366,39 @@ private void InitializeComponent() resources.ApplyResources(this.enableDeviceDetectionToolStripMenuItem, "enableDeviceDetectionToolStripMenuItem"); this.enableDeviceDetectionToolStripMenuItem.Click += new System.EventHandler(this.EnableDeviceDetectionToolStripMenuItem_Click); // + // runAfterUploadToolStripMenuItem + // + this.runAfterUploadToolStripMenuItem.CheckOnClick = true; + this.runAfterUploadToolStripMenuItem.Name = "runAfterUploadToolStripMenuItem"; + resources.ApplyResources(this.runAfterUploadToolStripMenuItem, "runAfterUploadToolStripMenuItem"); + // + // actionsToolStripMenuItem + // + this.actionsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.installUSBDriversToolStripMenuItem, + this.resetToDFUModeToolStripMenuItem, + this.upgradeBootloaderToolStripMenuItem}); + this.actionsToolStripMenuItem.Name = "actionsToolStripMenuItem"; + resources.ApplyResources(this.actionsToolStripMenuItem, "actionsToolStripMenuItem"); + // + // installUSBDriversToolStripMenuItem + // + this.installUSBDriversToolStripMenuItem.Name = "installUSBDriversToolStripMenuItem"; + resources.ApplyResources(this.installUSBDriversToolStripMenuItem, "installUSBDriversToolStripMenuItem"); + this.installUSBDriversToolStripMenuItem.Click += new System.EventHandler(this.InstallUSBDriversToolStripMenuItem_Click); + // + // resetToDFUModeToolStripMenuItem + // + this.resetToDFUModeToolStripMenuItem.Name = "resetToDFUModeToolStripMenuItem"; + resources.ApplyResources(this.resetToDFUModeToolStripMenuItem, "resetToDFUModeToolStripMenuItem"); + this.resetToDFUModeToolStripMenuItem.Click += new System.EventHandler(this.ResetToDFUModeToolStripMenuItem_Click); + // + // upgradeBootloaderToolStripMenuItem + // + this.upgradeBootloaderToolStripMenuItem.Name = "upgradeBootloaderToolStripMenuItem"; + resources.ApplyResources(this.upgradeBootloaderToolStripMenuItem, "upgradeBootloaderToolStripMenuItem"); + this.upgradeBootloaderToolStripMenuItem.Click += new System.EventHandler(this.UpgradeBootloaderToolStripMenuItem_Click); + // // helpToolStripMenuItem // this.helpToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { @@ -458,6 +499,11 @@ private void InitializeComponent() private System.Windows.Forms.ToolStripMenuItem runAfterUploadToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem installUSBDriversToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem enableDeviceDetectionToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem bootloaderTypeToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem stickyDfuUsbModeToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem comPortUsbModeToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem disableCompatibilityCheckToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItemBaudRate500000; } } diff --git a/src/flash-multi/FlashMulti.cs b/src/flash-multi/FlashMulti.cs index e416289..1c2785a 100644 --- a/src/flash-multi/FlashMulti.cs +++ b/src/flash-multi/FlashMulti.cs @@ -149,6 +149,13 @@ public FlashMulti() this.enableDeviceDetection = Properties.Settings.Default.EnableDeviceDetection; this.enableDeviceDetectionToolStripMenuItem.Checked = this.enableDeviceDetection; + // Set 'Enable Flash Verification' from the settings + this.disableCompatibilityCheckToolStripMenuItem.Checked = Settings.Default.DisableFlashVerification; + + // Set the 'Bootloader / USB Port' mode from the settings + this.comPortUsbModeToolStripMenuItem.Checked = Settings.Default.ErrorIfNoUSB; + this.stickyDfuUsbModeToolStripMenuItem.Checked = !Settings.Default.ErrorIfNoUSB; + // Hide the verbose output panel and set the height of the other panel int initialHeight = 215; this.splitContainer1.Panel2Collapsed = true; @@ -953,10 +960,11 @@ private async void UpgradeBootloaderToolStripMenuItem_Click(object sender, Event /// private void ToolStripMenuItemBaudRate57600_Click(object sender, EventArgs e) { - Properties.Settings.Default.SerialBaudRate = 57600; - Properties.Settings.Default.Save(); + Settings.Default.SerialBaudRate = 57600; + Settings.Default.Save(); this.toolStripMenuItemBaudRate57600.Checked = true; this.toolStripMenuItemBaudRate115200.Checked = false; + this.toolStripMenuItemBaudRate500000.Checked = false; } /// @@ -964,10 +972,23 @@ private void ToolStripMenuItemBaudRate57600_Click(object sender, EventArgs e) /// private void ToolStripMenuItemBaudRate115200_Click(object sender, EventArgs e) { - Properties.Settings.Default.SerialBaudRate = 115200; - Properties.Settings.Default.Save(); + Settings.Default.SerialBaudRate = 115200; + Settings.Default.Save(); this.toolStripMenuItemBaudRate57600.Checked = false; this.toolStripMenuItemBaudRate115200.Checked = true; + this.toolStripMenuItemBaudRate500000.Checked = false; + } + + /// + /// Handles the user setting the serial baud rate to 500000. + /// + private void ToolStripMenuItemBaudRate500000_Click(object sender, EventArgs e) + { + Settings.Default.SerialBaudRate = 500000; + Settings.Default.Save(); + this.toolStripMenuItemBaudRate57600.Checked = false; + this.toolStripMenuItemBaudRate115200.Checked = false; + this.toolStripMenuItemBaudRate500000.Checked = true; } /// @@ -989,6 +1010,37 @@ private void EnableDeviceDetectionToolStripMenuItem_Click(object sender, EventAr Properties.Settings.Default.Save(); } + private void DisableCompatibilityCheckToolStripMenuItem_Click(object sender, EventArgs e) + { + Settings.Default.DisableFlashVerification = this.disableCompatibilityCheckToolStripMenuItem.Checked; + Settings.Default.Save(); + } + + /// + /// Handles setting the Bootloader / USB Port mode to 'legacy'. + /// + private void ComPortUsbModeToolStripMenuItem_Click(object sender, EventArgs e) + { + this.stickyDfuUsbModeToolStripMenuItem.Checked = false; + this.comPortUsbModeToolStripMenuItem.Checked = true; + Settings.Default.ErrorIfNoUSB = true; + Settings.Default.WarnIfNoUSB = true; + Settings.Default.RunAfterUpload = true; + Settings.Default.Save(); + } + + /// + /// Handles setting the Bootloader / USB Port mode to 'new'. + /// + private void StickyDfuUsbModeToolStripMenuItem_Click(object sender, EventArgs e) + { + this.stickyDfuUsbModeToolStripMenuItem.Checked = true; + this.comPortUsbModeToolStripMenuItem.Checked = false; + Settings.Default.ErrorIfNoUSB = false; + Settings.Default.RunAfterUpload = false; + Settings.Default.Save(); + } + /// /// Handles the user clicking the Check for Update menu item. /// @@ -1102,6 +1154,9 @@ private async Task ReadModule() // Get the signature from the firmware file FileUtils.FirmwareFile fileDetails = FileUtils.GetFirmwareSignature(tempFirmwareFileName); + // Check for USB Serial support + bool usbSerialSupport = FileUtils.CheckForUsbSupport(tempFirmwareFileName); + // If we got details from the signature write them to the log window if (fileDetails != null) { @@ -1111,6 +1166,7 @@ private async Task ReadModule() this.AppendLog($"Invert Telemetry Enabled: {fileDetails.InvertTelemetry}\r\n"); this.AppendLog($"Flash from Radio Enabled: {fileDetails.CheckForBootloader}\r\n"); this.AppendLog($"Bootloader Enabled: {fileDetails.BootloaderSupport}\r\n"); + this.AppendLog($"USB Serial Support: {usbSerialSupport}\r\n"); this.AppendLog($"Serial Debug Enabled: {fileDetails.DebugSerial}\r\n"); } else @@ -1347,15 +1403,52 @@ private async Task WriteModule() // Get the signature from the firmware file FileUtils.FirmwareFile fileSignature = FileUtils.GetFirmwareSignature(this.textFileName.Text); - // Error if flashing non-USB firmware via native USB port - if (mapleResult.DeviceFound && !firmwareSupportsUsb) + // Stop if this is a firmware file without a signature - we can't be sure that it will match the module + if (this.textFileName.Text.EndsWith(".bin") && fileSignature == null) + { + string msgBoxMessage = "Unable to validate the selected firmware file. The firmware signature is missing."; + MessageBox.Show(msgBoxMessage, "Incompatible Firmware", MessageBoxButtons.OK, MessageBoxIcon.Error); + this.EnableControls(true); + return; + } + + // Error if flashing firmware without bootloader support firmware via native USB port + if (mapleResult.DeviceFound && !fileSignature.BootloaderSupport) { - string msgBoxMessage = "The selected firmware file was compiled without USB support.\r\n\r\nFlashing this firmware would prevent the MULTI-Module from functioning correctly.\r\n\r\nPlease select a different firmware file."; + string msgBoxMessage = "The selected firmware file was compiled without bootloader support\r\n\r\nThis firmware cannot be written to the connected MULTI-Module."; MessageBox.Show(msgBoxMessage, "Incompatible Firmware", MessageBoxButtons.OK, MessageBoxIcon.Error); this.EnableControls(true); return; } + // Error or warn if flashing non-USB firmware via native USB port and we're not configured for hte new bootloader + if (mapleResult.DeviceFound && !firmwareSupportsUsb) + { + if (Settings.Default.ErrorIfNoUSB) + { + // Error if the new bootloader hasn't been enabled + UsbSupportErrorDialog usbSupportErrorDialog = new UsbSupportErrorDialog(); + usbSupportErrorDialog.ShowDialog(); + this.EnableControls(true); + return; + } + else + { + if (Settings.Default.WarnIfNoUSB) + { + // Warn that bootloader update is required if the firmware file does not have USB support + UsbSupportWarningDialog usbSupportWarning = new UsbSupportWarningDialog(); + var warnResult = usbSupportWarning.ShowDialog(); + + if (warnResult != DialogResult.OK) + { + this.EnableControls(true); + return; + } + } + } + } + // Get the selected COM port string comPort = this.GetSelectedPort().ToString(); @@ -1401,7 +1494,7 @@ private async Task WriteModule() } else { - await SerialDevice.WriteFlash(this, this.textFileName.Text, comPort, firmwareSupportsUsb, firmwareContainsEeprom, this.runAfterUploadToolStripMenuItem.Checked); + await SerialDevice.WriteFlash(this, this.textFileName.Text, comPort, fileSignature.BootloaderSupport, firmwareContainsEeprom, this.runAfterUploadToolStripMenuItem.Checked); } // Populate the COM ports in case they changed @@ -1440,6 +1533,9 @@ private void OpenFile() uint globalId = 0; if (openFileDialog.FileName.EndsWith(".bin")) { + // Check for USB Serial support + bool usbSerialSupport = FileUtils.CheckForUsbSupport(this.textFileName.Text); + // Get the signature from the firmware file FileUtils.FirmwareFile fileDetails = FileUtils.GetFirmwareSignature(this.textFileName.Text); @@ -1453,6 +1549,7 @@ private void OpenFile() this.AppendLog($"Invert Telemetry Enabled: {fileDetails.InvertTelemetry}\r\n"); this.AppendLog($"Flash from Radio Enabled: {fileDetails.CheckForBootloader}\r\n"); this.AppendLog($"Bootloader Enabled: {fileDetails.BootloaderSupport}\r\n"); + this.AppendLog($"USB Serial Support: {usbSerialSupport}\r\n"); this.AppendLog($"Serial Debug Enabled: {fileDetails.DebugSerial}"); } else diff --git a/src/flash-multi/FlashMulti.resx b/src/flash-multi/FlashMulti.resx index ae3c033..4658e0c 100644 --- a/src/flash-multi/FlashMulti.resx +++ b/src/flash-multi/FlashMulti.resx @@ -750,30 +750,6 @@ &File - - 224, 22 - - - &Install USB Device Drivers - - - 224, 22 - - - &Reset Module to DFU Mode - - - 224, 22 - - - &Upgrade Module Bootloader - - - 180, 22 - - - A&ctions - 110, 22 @@ -786,17 +762,41 @@ 115200 + + 110, 22 + + + 500000 + 207, 22 Serial &Baud Rate - + + 199, 22 + + + Sticky &DFU Mode (New) + + + 199, 22 + + + &COM Port (Legacy) + + 207, 22 - - &Run Firmware After Write + + USB Port Mode + + + 207, 22 + + + Disable Flash Size Check 207, 22 @@ -804,12 +804,42 @@ &Enable Device Detection + + 207, 22 + + + &Run Firmware After Write + 180, 22 &Settings + + 219, 22 + + + &Install USB Device Drivers + + + 219, 22 + + + &Reset Module to DFU Mode + + + 219, 22 + + + &Flash Module Bootloader + + + 180, 22 + + + A&ctions + 72, 20 @@ -1478,30 +1508,6 @@ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - actionsToolStripMenuItem - - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - installUSBDriversToolStripMenuItem - - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - resetToDFUModeToolStripMenuItem - - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - upgradeBootloaderToolStripMenuItem - - - System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - settingsToolStripMenuItem @@ -1526,10 +1532,34 @@ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - runAfterUploadToolStripMenuItem + + toolStripMenuItemBaudRate500000 - + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + bootloaderTypeToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + stickyDfuUsbModeToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + comPortUsbModeToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + disableCompatibilityCheckToolStripMenuItem + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 @@ -1538,6 +1568,36 @@ System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + runAfterUploadToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + actionsToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + installUSBDriversToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + resetToDFUModeToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + upgradeBootloaderToolStripMenuItem + + + System.Windows.Forms.ToolStripMenuItem, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + helpToolStripMenuItem diff --git a/src/flash-multi/Localization/Strings.Designer.cs b/src/flash-multi/Localization/Strings.Designer.cs index ac3f9e3..03016b1 100644 --- a/src/flash-multi/Localization/Strings.Designer.cs +++ b/src/flash-multi/Localization/Strings.Designer.cs @@ -61,7 +61,7 @@ internal Strings() { } /// - /// Looks up a localized string similar to Bootloader upgrade app written successfully. + /// Looks up a localized string similar to Bootloader upgrade app written successfully. /// ///The app will now update the bootloader on the MULTI-Module. /// @@ -85,9 +85,7 @@ internal static string bootloaderUpgradeFailed { /// /// Looks up a localized string similar to Upgrading the bootloader will erase the MULTI-Module firmware. New firmware will need to be written to the module before it is usable. /// - ///The red LED on the MULTI-Module will indicate the progress of the bootloader upgrade. - /// - ///Once the bootloader upgrade is started the module must not be unplugged until the red LED remains off for 5s. + ///The red LED on the MULTI-Module will indicate the progress of the bootloader upgrade. Once the bootloader upgrade is started the module must not be unplugged until the red LED remains off for 5s. /// ///Once the LED has been off for 5s, unplug the module, plug it back in, then write new firmware to it. /// @@ -263,6 +261,15 @@ internal static string failedToReadModule { } } + /// + /// Looks up a localized string similar to Module flash verification failed. This MCU on this module does not support 128KB of flash.. + /// + internal static string failedToVerifyMcuFlash { + get { + return ResourceManager.GetString("failedToVerifyMcuFlash", resourceCulture); + } + } + /// /// Looks up a localized string similar to Failed to write the bootloader.. /// @@ -344,6 +351,15 @@ internal static string modeWriting { } } + /// + /// Looks up a localized string similar to Checking flash size .... + /// + internal static string progressCheckingFlashSize { + get { + return ResourceManager.GetString("progressCheckingFlashSize", resourceCulture); + } + } + /// /// Looks up a localized string similar to Erasing flash memory .... /// diff --git a/src/flash-multi/Localization/Strings.resx b/src/flash-multi/Localization/Strings.resx index e001a7f..0bce838 100644 --- a/src/flash-multi/Localization/Strings.resx +++ b/src/flash-multi/Localization/Strings.resx @@ -220,7 +220,7 @@ You are running the latest version of Flash Multi. - Bootloader upgrade app written successfully. + Bootloader upgrade app written successfully. The app will now update the bootloader on the MULTI-Module. @@ -229,9 +229,7 @@ DO NOT UNPLUG THE MULTI-MODULE UNTIL THE RED LED GOES OUT AND REMAINS OFF FOR 5 Upgrading the bootloader will erase the MULTI-Module firmware. New firmware will need to be written to the module before it is usable. -The red LED on the MULTI-Module will indicate the progress of the bootloader upgrade. - -Once the bootloader upgrade is started the module must not be unplugged until the red LED remains off for 5s. +The red LED on the MULTI-Module will indicate the progress of the bootloader upgrade. Once the bootloader upgrade is started the module must not be unplugged until the red LED remains off for 5s. Once the LED has been off for 5s, unplug the module, plug it back in, then write new firmware to it. @@ -285,4 +283,10 @@ If you are upgrading ore replacing existing drivers, ensure that the MULTI-Modul + + Checking flash size ... + + + Module flash verification failed. This MCU on this module does not support 128KB of flash. + \ No newline at end of file diff --git a/src/flash-multi/Properties/AssemblyInfo.cs b/src/flash-multi/Properties/AssemblyInfo.cs index cf8d9a6..0db95fb 100644 --- a/src/flash-multi/Properties/AssemblyInfo.cs +++ b/src/flash-multi/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.4.3")] -[assembly: AssemblyFileVersion("0.4.3")] +[assembly: AssemblyVersion("0.5.0")] +[assembly: AssemblyFileVersion("0.5.0")] diff --git a/src/flash-multi/Properties/Resources.Designer.cs b/src/flash-multi/Properties/Resources.Designer.cs new file mode 100644 index 0000000..7b228a5 --- /dev/null +++ b/src/flash-multi/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Flash_Multi.Properties { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Flash_Multi.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/src/flash-multi/Properties/Resources.resx b/src/flash-multi/Properties/Resources.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/src/flash-multi/Properties/Resources.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/flash-multi/Properties/Settings.Designer.cs b/src/flash-multi/Properties/Settings.Designer.cs index a4c9da8..1aebb2c 100644 --- a/src/flash-multi/Properties/Settings.Designer.cs +++ b/src/flash-multi/Properties/Settings.Designer.cs @@ -106,5 +106,41 @@ public bool EnableDeviceDetection { this["EnableDeviceDetection"] = value; } } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool ErrorIfNoUSB { + get { + return ((bool)(this["ErrorIfNoUSB"])); + } + set { + this["ErrorIfNoUSB"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("True")] + public bool WarnIfNoUSB { + get { + return ((bool)(this["WarnIfNoUSB"])); + } + set { + this["WarnIfNoUSB"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("False")] + public bool DisableFlashVerification { + get { + return ((bool)(this["DisableFlashVerification"])); + } + set { + this["DisableFlashVerification"] = value; + } + } } } diff --git a/src/flash-multi/Properties/Settings.settings b/src/flash-multi/Properties/Settings.settings index 41347a9..cc6973e 100644 --- a/src/flash-multi/Properties/Settings.settings +++ b/src/flash-multi/Properties/Settings.settings @@ -23,5 +23,14 @@ True + + True + + + True + + + False + \ No newline at end of file diff --git a/src/flash-multi/app.config b/src/flash-multi/app.config index 8dbe58e..ff49b95 100644 --- a/src/flash-multi/app.config +++ b/src/flash-multi/app.config @@ -28,6 +28,15 @@ True + + True + + + True + + + False + diff --git a/src/flash-multi/flash-multi.csproj b/src/flash-multi/flash-multi.csproj index 594f930..05bf6ef 100644 --- a/src/flash-multi/flash-multi.csproj +++ b/src/flash-multi/flash-multi.csproj @@ -51,6 +51,18 @@ + + Form + + + UsbSupportErrorDialog.cs + + + Form + + + UsbSupportWarningDialog.cs + @@ -70,6 +82,11 @@ + + True + True + Resources.resx + @@ -93,6 +110,12 @@ SerialMonitor.cs + + UsbSupportErrorDialog.cs + + + UsbSupportWarningDialog.cs + FlashMulti.cs @@ -107,6 +130,10 @@ Strings.Designer.cs Flash_Multi + + ResXFileCodeGenerator + Resources.Designer.cs + @@ -136,9 +163,7 @@ - - - + XCOPY "$(SolutionDir)tools\*.*" "$(TargetDir)" /S /Y diff --git a/src/tools/bootloaders/StmMulti4in1.bin b/src/tools/bootloaders/StmMulti4in1_Legacy.bin similarity index 100% rename from src/tools/bootloaders/StmMulti4in1.bin rename to src/tools/bootloaders/StmMulti4in1_Legacy.bin diff --git a/src/tools/bootloaders/StmMulti4in1_StickyDfu.bin b/src/tools/bootloaders/StmMulti4in1_StickyDfu.bin new file mode 100644 index 0000000..6ac312c Binary files /dev/null and b/src/tools/bootloaders/StmMulti4in1_StickyDfu.bin differ diff --git a/src/tools/tools/BootReloader.bin b/src/tools/tools/BootReloader_Legacy.bin similarity index 100% rename from src/tools/tools/BootReloader.bin rename to src/tools/tools/BootReloader_Legacy.bin diff --git a/src/tools/tools/BootReloader_StickyDfu.bin b/src/tools/tools/BootReloader_StickyDfu.bin new file mode 100644 index 0000000..c27b286 Binary files /dev/null and b/src/tools/tools/BootReloader_StickyDfu.bin differ