Skip to content

Commit

Permalink
Merge pull request #41 from husarion/ros2-usb-flash
Browse files Browse the repository at this point in the history
flashing over usb
  • Loading branch information
DominikN authored Dec 7, 2023
2 parents 19a1b77 + a662413 commit b7b7528
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 44 deletions.
19 changes: 11 additions & 8 deletions Dockerfile.hardware
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@ FROM ubuntu:18.04 AS stm32flash_builder

ARG ROS_DISTRO
ARG ROSBOT_FW_RELEASE
ARG TARGETARCH

SHELL ["/bin/bash", "-c"]

# official releases are only for intel archs, so we need to build stm32flash from sources
RUN apt-get update && apt-get install -y \
curl \
git \
build-essential \
cmake && \
git clone https://github.com/stm32duino/stm32flash.git && \
cd stm32flash/ && \
make all
curl

RUN echo ros_distro=$ROS_DISTRO firmware_release=$ROSBOT_FW_RELEASE

# Copy firmware binaries
RUN curl -L https://github.com/husarion/stm32flash/releases/download/2023-12-05/stm32flash-$TARGETARCH -o /stm32flash && \
chmod +x /stm32flash

# Copy firmware binaries
RUN curl -L https://github.com/husarion/rosbot_ros2_firmware/releases/download/$ROSBOT_FW_RELEASE/firmware.bin -o /firmware.bin && \
curl -L https://github.com/husarion/rosbot_ros2_firmware/releases/download/$ROSBOT_FW_RELEASE/firmware.hex -o /firmware.hex
Expand Down Expand Up @@ -129,8 +128,11 @@ COPY --from=ros_builder /ros2_ws /ros2_ws
COPY --from=healthcheck_builder /ros2_ws /ros2_ws_healthcheck

RUN apt-get update && apt-get install -y \
python3-pip \
python3-rosdep \
usbutils \
ros-$ROS_DISTRO-teleop-twist-keyboard && \
pip3 install pyftdi sh && \
rm -rf /etc/ros/rosdep/sources.list.d/20-default.list && \
rosdep init && \
rosdep update --rosdistro $ROS_DISTRO && \
Expand All @@ -145,7 +147,7 @@ RUN apt-get update && apt-get install -y \
# copy firmware built in previous stage and downloaded repository
COPY --from=stm32flash_builder /firmware.bin /root/firmware.bin
COPY --from=stm32flash_builder /firmware.hex /root/firmware.hex
COPY --from=stm32flash_builder /stm32flash/stm32flash /usr/bin/stm32flash
COPY --from=stm32flash_builder /stm32flash /usr/bin/stm32flash

COPY --from=cpu_id_builder /read_cpu_id/.pio/build/olimex_e407/firmware.bin /firmware_read_cpu_id.bin

Expand All @@ -161,4 +163,5 @@ COPY microros_localhost_only.xml /
# copy scripts
COPY flash-firmware.py /
COPY flash-firmware.py /usr/bin/
COPY flash-firmware-usb.py /usr/bin/
COPY print-serial-number.py /usr/bin/
16 changes: 10 additions & 6 deletions demo/namespace/compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,18 @@ services:
ipc: host
devices:
- ${SERIAL_PORT:?err}
- /dev/bus/usb/
volumes:
- ../../flash-firmware-usb.py:/usr/bin/flash-firmware-usb.py
environment:
- FASTRTPS_DEFAULT_PROFILES_FILE=/shm-only.xml
command: >
ros2 launch rosbot_bringup combined.launch.py
mecanum:=${MECANUM:-False}
serial_port:=$SERIAL_PORT
serial_baudrate:=576000
namespace:=robot1
command: tail -f /dev/null
# command: >
# ros2 launch rosbot_bringup combined.launch.py
# mecanum:=${MECANUM:-False}
# serial_port:=$SERIAL_PORT
# serial_baudrate:=576000
# namespace:=robot1

ros2router:
image: husarnet/ros2router:1.4.0
Expand Down
109 changes: 109 additions & 0 deletions flash-firmware-usb.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#!/usr/bin/python3

import sh
import time
import sys
import argparse
from pyftdi.ftdi import Ftdi

# CBUS0 - BOOT0
# CBUS1 - RST

class FirmwareFlasher:
def __init__(self, binary_file, port):

# ftdi.show_devices()
# self.ftdi = Ftdi.create_from_url('ftdi://ftdi:ft-x:DK0AM0V0/1')
self.device = 'ftdi://ftdi:ft-x:/1'
self.ftdi = Ftdi()

self.binary_file = binary_file
self.max_approach_no = 3
self.port = port

def enter_bootloader_mode(self):

self.ftdi.open_from_url(url=self.device)
self.ftdi.set_cbus_direction(0b11,0b11) # set CBUS0 and CBUS1 to output
time.sleep(0.1)
self.ftdi.set_cbus_gpio(0b11) #set CBUS0 to 1 and RST to 1
time.sleep(0.1)
self.ftdi.set_cbus_gpio(0b01) #set CBUS0 to 1 and RST to 0
time.sleep(0.1)
# self.ftdi.set_cbus_direction(0b11,0b00) # set CBUS0 and CBUS1 to input
time.sleep(0.1)
self.ftdi.close()

def exit_bootloader_mode(self):

self.ftdi.open_from_url(url=self.device)
self.ftdi.set_cbus_direction(0b11,0b11) # set CBUS0 and CBUS1 to output
time.sleep(0.1)
self.ftdi.set_cbus_gpio(0b10) #set CBUS0 to 1 and RST to 1
time.sleep(0.1)
self.ftdi.set_cbus_gpio(0b00) #set CBUS0 to 1 and RST to 0
time.sleep(0.1)
# self.ftdi.set_cbus_direction(0b11,0b00) # set CBUS0 and CBUS1 to input
time.sleep(0.1)
self.ftdi.close()

def try_flash_operation(self, operation_name, flash_command, flash_args):
for i in range(self.max_approach_no):
try:
self.enter_bootloader_mode()
sh.usbreset("0403:6015")
flash_command(self.port, *flash_args, _out=sys.stdout)
self.exit_bootloader_mode()
time.sleep(0.2)
break
except Exception as e:
print(f"{operation_name} error! Trying again.")
print(f"Error: {e}")
print("---------------------------------------")
else:
print(f"WARNING! {operation_name} went wrong.")

def flash_firmware(self):
# Disable the flash write-protection
self.try_flash_operation("Write-UnProtection", sh.stm32flash, ["-u"])

# Disable the flash read-protection
self.try_flash_operation("Read-UnProtection", sh.stm32flash, ["-k"])

# Flashing the firmware
# /usr/bin/stm32flash /dev/ttyUSB0 -v -w /root/firmware.bin -b 115200
flash_args = ["-v", "-w", self.binary_file, "-b", "115200"]
self.try_flash_operation("Flashing", sh.stm32flash, flash_args)


sh.usbreset("0403:6015")


def main():

parser = argparse.ArgumentParser(
description='Flashing the firmware on STM32 microcontroller in ROSbot XL')

parser.add_argument(
"-f",
"--file",
nargs='?',
default="/root/firmware.bin",
help="Path to a firmware file. Default: /root/firmware.bin")
parser.add_argument(
"-p",
"--port",
nargs='?',
default="/dev/ttyUSB0",
help="Path to serial connection. Default: /dev/ttyUSB0")

binary_file = parser.parse_args().file
port = parser.parse_args().port

flasher = FirmwareFlasher(binary_file, port)
flasher.flash_firmware()
print("Done.")


if __name__ == "__main__":
main()
47 changes: 17 additions & 30 deletions flash-firmware.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ def __init__(self, sys_arch, binary_file):
self.binary_file = binary_file
self.sys_arch = sys_arch

self.max_approach_no = 5
self.max_approach_no = 3

print(f"System architecture: {self.sys_arch}")

Expand Down Expand Up @@ -57,44 +57,31 @@ def exit_bootloader_mode(self):
self.reset_pin.write(False)
time.sleep(0.2)

def flash_firmware(self):
self.enter_bootloader_mode()

# Disable the flash write-protection
def try_flash_operation(self, operation_name, flash_command, flash_args):
for i in range(self.max_approach_no):
try:
sh.stm32flash(self.port, "-u", _out=sys.stdout)
flash_command(self.port, *flash_args, _out=sys.stdout)
time.sleep(0.2)
break
except Exception:
print("Write-UnProtection error! Trying again.")
pass
except Exception as e:
print(f"{operation_name} error! Trying again.")
print(f"Error: {e}")
print("---------------------------------------")
else:
print("WARNING! Disabling the flash Write-Protection went wrong.")
print(f"WARNING! {operation_name} went wrong.")

def flash_firmware(self):
self.enter_bootloader_mode()

# Disable the flash write-protection
self.try_flash_operation("Write-UnProtection", sh.stm32flash, ["-u"])

# Disable the flash read-protection
for i in range(self.max_approach_no):
try:
sh.stm32flash(self.port, "-k", _out=sys.stdout)
time.sleep(0.2)
break
except Exception:
print("Read-UnProtection error! Trying again.")
pass
else:
print("WARNING! Disabling the flash Read-Protection went wrong.")
self.try_flash_operation("Read-UnProtection", sh.stm32flash, ["-k"])

# Flashing the firmware
for i in range(self.max_approach_no):
try:
sh.stm32flash(self.port, "-v", w=self.binary_file, b="115200", _out=sys.stdout)
time.sleep(0.2)
break
except Exception:
print("Flashing error! Trying again.")
pass
else:
print("ERROR! Flashing the firmware went wrong. Try again.")
flash_args = ["-v", "-w", self.binary_file, "-b", "115200"]
self.try_flash_operation("Flashing", sh.stm32flash, flash_args)

self.exit_bootloader_mode()

Expand Down

0 comments on commit b7b7528

Please sign in to comment.