Skip to content

Commit

Permalink
Merge pull request #27 from benlye/0.5.0
Browse files Browse the repository at this point in the history
Merge 0.5.0 work
  • Loading branch information
benlye authored Sep 10, 2020
2 parents 7207053 + be56d54 commit 60c85b0
Show file tree
Hide file tree
Showing 34 changed files with 1,739 additions and 196 deletions.
90 changes: 90 additions & 0 deletions doc/New_Bootloader.md
Original file line number Diff line number Diff line change
@@ -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.
File renamed without changes.
Binary file added linux/bootloader/StmMulti4in1_StickyDfu.bin
Binary file not shown.
72 changes: 51 additions & 21 deletions linux/flash-multi
Original file line number Diff line number Diff line change
Expand Up @@ -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"
;;
Expand All @@ -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
Expand All @@ -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: "
Expand Down Expand Up @@ -261,13 +276,21 @@ 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";
printf "Multi Telemetry Type: $FW_TELEMETRY_TYPE\n";
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";
}

Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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;
Expand Down
16 changes: 11 additions & 5 deletions linux/multi-bootreloader
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down
File renamed without changes.
Binary file added linux/tools/BootReloader_StickyDfu.bin
Binary file not shown.
Loading

0 comments on commit 60c85b0

Please sign in to comment.