From eddbea4007412e09052d37447498bf54e2df2f41 Mon Sep 17 00:00:00 2001 From: rafal-gorecki <126687345+rafal-gorecki@users.noreply.github.com> Date: Mon, 20 May 2024 10:44:59 +0200 Subject: [PATCH] Revert "Ros1-fix-firmware-flashing (#46)" This reverts commit 008abd816199eca7f45a9269418a5391176c3d28. --- .../workflows/build-docker-image-gazebo.yaml | 11 +- .../build-docker-image-hardware.yaml | 20 ++-- Dockerfile.hardware | 101 ++++++++++++++--- Dockerfile.simulation | 4 +- flash-firmware.py | 105 +++++++++--------- 5 files changed, 157 insertions(+), 84 deletions(-) diff --git a/.github/workflows/build-docker-image-gazebo.yaml b/.github/workflows/build-docker-image-gazebo.yaml index f8c579f..f7efaf3 100644 --- a/.github/workflows/build-docker-image-gazebo.yaml +++ b/.github/workflows/build-docker-image-gazebo.yaml @@ -6,7 +6,7 @@ on: # - 'ros1' pull_request: types: [closed] - + jobs: build: runs-on: ubuntu-20.04 @@ -14,6 +14,7 @@ jobs: fail-fast: false matrix: include: + - ros-distro: melodic - ros-distro: noetic steps: @@ -22,19 +23,19 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v1 - + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 with: version: latest - + - name: Login to Docker Registry uses: docker/login-action@v1 with: registry: docker.io username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - + - name: Build and push (production) if: github.ref_name == 'ros1' uses: docker/build-push-action@v2 @@ -61,4 +62,4 @@ jobs: ROS_DISTRO=${{ matrix.ros-distro }} tags: husarion/rosbot:${{ matrix.ros-distro }}-simulation-${{ github.head_ref || github.ref_name }} cache-from: type=registry,ref=husarion/rosbot:${{ matrix.ros-distro }}-simulation-${{ github.head_ref || github.ref_name }} - cache-to: type=inline + cache-to: type=inline \ No newline at end of file diff --git a/.github/workflows/build-docker-image-hardware.yaml b/.github/workflows/build-docker-image-hardware.yaml index 5891688..0f70958 100644 --- a/.github/workflows/build-docker-image-hardware.yaml +++ b/.github/workflows/build-docker-image-hardware.yaml @@ -7,7 +7,7 @@ on: workflow_dispatch: pull_request: types: [closed] - + jobs: build: runs-on: ubuntu-20.04 @@ -16,10 +16,12 @@ jobs: matrix: include: - ros-distro: melodic - rosbot-fw-release: 0.16.2 + ros-noetic-msgs: 0 + rosbot-fw-release: 0.16.1 platforms: "linux/amd64, linux/arm64, linux/arm/v7" - ros-distro: noetic - rosbot-fw-release: 0.16.2 + ros-noetic-msgs: 1 + rosbot-fw-release: 0.16.1 platforms: "linux/amd64, linux/arm64" steps: @@ -28,19 +30,19 @@ jobs: - name: Set up QEMU uses: docker/setup-qemu-action@v1 - + - name: Set up Docker Buildx uses: docker/setup-buildx-action@v1 with: version: latest - + - name: Login to Docker Registry uses: docker/login-action@v1 with: registry: docker.io username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_TOKEN }} - + - name: Build and push (production) if: github.ref_name == 'ros1' uses: docker/build-push-action@v2 @@ -51,8 +53,9 @@ jobs: push: true build-args: | ROS_DISTRO=${{ matrix.ros-distro }} + ROS_NOETIC_MSGS=${{ matrix.ros-noetic-msgs }} ROSBOT_FW_RELEASE=${{ matrix.rosbot-fw-release }} - tags: husarion/rosbot:${{ matrix.ros-distro }} + tags: husarion/rosbot:${{ matrix.ros-distro }} cache-from: type=registry,ref=husarion/rosbot:${{ matrix.ros-distro }} cache-to: type=inline @@ -66,7 +69,8 @@ jobs: push: true build-args: | ROS_DISTRO=${{ matrix.ros-distro }} + ROS_NOETIC_MSGS=${{ matrix.ros-noetic-msgs }} ROSBOT_FW_RELEASE=${{ matrix.rosbot-fw-release }} tags: husarion/rosbot:${{ matrix.ros-distro }}-${{ github.head_ref || github.ref_name }} cache-from: type=registry,ref=husarion/rosbot:${{ matrix.ros-distro }}-${{ github.head_ref || github.ref_name }} - cache-to: type=inline + cache-to: type=inline \ No newline at end of file diff --git a/Dockerfile.hardware b/Dockerfile.hardware index 98b11ae..688c33c 100644 --- a/Dockerfile.hardware +++ b/Dockerfile.hardware @@ -1,7 +1,80 @@ -ARG ROS_DISTRO=noetic -ARG ROSBOT_FW_RELEASE=0.16.2 + +ARG ROS_DISTRO=melodic + +## ============================ STM32FLASH ================================= +# stm32flash needs an older version of glibc (2.28), which is why ubuntu 18.04 was used +FROM ubuntu:18.04 AS stm32flash_builder + +# official releases are only for intel archs, so we need to build stm32flash from sources +RUN apt-get update && apt-get install -y \ + git \ + build-essential && \ + git clone https://github.com/stm32duino/stm32flash.git && \ + cd stm32flash/ && \ + make all + +## =========================== STM32 firmware=============================== +# FROM --platform=linux/amd64 ubuntu:18.04 as stm32_firmware_builder +# TODO: wget from releases instead +FROM --platform=linux/amd64 ubuntu:20.04 AS stm32_firmware_builder + +ARG ROSBOT_FW_RELEASE=0.16.1 +ARG ROS_NOETIC_MSGS=0 + +SHELL ["/bin/bash", "-c"] + +# ENV PIO_VERSION="5.1.0" +RUN apt update && apt install -y \ + python3 \ + python3-pip \ + git \ + wget \ + tree + +# https://docs.platformio.org/en/latest/core/installation.html#system-requirements +# RUN pip3 install -U platformio==${PIO_VERSION} +RUN pip3 install -U platformio + +RUN git clone https://github.com/husarion/rosbot-stm32-firmware.git --branch ${ROSBOT_FW_RELEASE} && \ + mkdir -p ~/.platformio/packages/framework-mbed/features/ && \ + cp rosbot-stm32-firmware/.mbedignore ~/.platformio/packages/framework-mbed/features/.mbedignore + +WORKDIR /rosbot-stm32-firmware + +RUN git submodule update --init --recursive + +# RUN wget https://github.com/husarion/rosbot-stm32-firmware/archive/refs/tags/${ROSBOT_FW_RELEASE}.tar.gz && \ +# tar -xf *.tar.gz && \ +# mv rosbot-stm32-firmware* rosbot-stm32-firmware && \ +# mkdir -p ~/.platformio/packages/framework-mbed/features/ && \ +# cp rosbot-stm32-firmware/.mbedignore ~/.platformio/packages/framework-mbed/features/.mbedignore + +WORKDIR /rosbot-stm32-firmware + +RUN export LC_ALL=C.UTF-8 && \ + export LANG=C.UTF-8 && \ + pio project init -e core2_diff -O \ + "build_flags= \ + -I\$PROJECTSRC_DIR/TARGET_CORE2 \ + -DPIO_FRAMEWORK_MBED_RTOS_PRESENT \ + -DPIO_FRAMEWORK_EVENT_QUEUE_PRESENT \ + -DMBED_BUILD_PROFILE_RELEASE \ + -DJOINT_STATES_ENABLE=1 \ + -DROS_NOETIC_MSGS=${ROS_NOETIC_MSGS} \ + -DKINEMATIC_TYPE=0" && \ + pio project init -e core2_mec -O \ + "build_flags= \ + -I\$PROJECTSRC_DIR/TARGET_CORE2 \ + -DPIO_FRAMEWORK_MBED_RTOS_PRESENT \ + -DPIO_FRAMEWORK_EVENT_QUEUE_PRESENT \ + -DMBED_BUILD_PROFILE_RELEASE \ + -DJOINT_STATES_ENABLE=1 \ + -DROS_NOETIC_MSGS=${ROS_NOETIC_MSGS} \ + -DKINEMATIC_TYPE=1" && \ + pio run ## =========================== ROS package builder =============================== + FROM ros:$ROS_DISTRO-ros-core AS pkg-builder SHELL ["/bin/bash", "-c"] @@ -9,7 +82,7 @@ SHELL ["/bin/bash", "-c"] RUN apt update && apt install -y \ git \ python3-pip \ - ros-$ROS_DISTRO-rosserial-python \ + ros-$ROS_DISTRO-rosserial-python \ ros-$ROS_DISTRO-rosserial-server \ ros-$ROS_DISTRO-rosserial-client \ ros-$ROS_DISTRO-rosserial-msgs \ @@ -32,25 +105,21 @@ WORKDIR /ros_ws # clone robot github repositories RUN mkdir -p src && \ git clone https://github.com/husarion/rosbot_ros.git --branch=melodic src/rosbot_ros && \ - git clone https://github.com/husarion/rosbot_ekf.git --branch=master src/rosbot_ekf + git clone https://github.com/husarion/rosbot_ekf.git --branch=master src/rosbot_ekf # build ROS workspace RUN source /opt/ros/$ROS_DISTRO/setup.bash && \ catkin_make -DCATKIN_ENABLE_TESTING=0 -DCMAKE_BUILD_TYPE=Release +## =========================== ROS image =============================== -## =========================== Final Stage =============================== -FROM ros:$ROS_DISTRO-ros-core - -ARG ROSBOT_FW_RELEASE +FROM ros:$ROS_DISTRO-ros-core SHELL ["/bin/bash", "-c"] RUN apt update && apt install -y \ - curl \ python3-pip \ - stm32flash \ - ros-$ROS_DISTRO-rosserial-python \ + ros-$ROS_DISTRO-rosserial-python \ ros-$ROS_DISTRO-rosserial-server \ ros-$ROS_DISTRO-rosserial-client \ ros-$ROS_DISTRO-rosserial-msgs \ @@ -71,10 +140,10 @@ RUN apt update && apt install -y \ # copy ROS package from previous step COPY --from=pkg-builder /ros_ws /ros_ws -# copy firmware built -RUN cd /root && \ - curl -L https://github.com/husarion/rosbot-stm32-firmware/releases/download/$ROSBOT_FW_RELEASE/firmware_diff.bin -o firmware_diff.bin && \ - curl -L https://github.com/husarion/rosbot-stm32-firmware/releases/download/$ROSBOT_FW_RELEASE/firmware_mec.bin -o firmware_mecanum.bin +# copy firmware built in previous stage +COPY --from=stm32_firmware_builder /rosbot-stm32-firmware/.pio/build/core2_diff/firmware.bin /root/firmware_diff.bin +COPY --from=stm32_firmware_builder /rosbot-stm32-firmware/.pio/build/core2_mec/firmware.bin /root/firmware_mecanum.bin +COPY --from=stm32flash_builder /stm32flash/stm32flash /usr/bin/stm32flash # copy scripts COPY ./flash-firmware.py / @@ -87,4 +156,4 @@ RUN echo ". /opt/ros/$ROS_DISTRO/setup.bash" >> ~/.bashrc && \ echo ". /ros_ws/devel/setup.bash" >> ~/.profile ENTRYPOINT ["/ros_entrypoint.sh"] -CMD ["bash"] +CMD ["bash"] \ No newline at end of file diff --git a/Dockerfile.simulation b/Dockerfile.simulation index fb2da18..4521832 100644 --- a/Dockerfile.simulation +++ b/Dockerfile.simulation @@ -1,4 +1,4 @@ -ARG ROS_DISTRO=noetic +ARG ROS_DISTRO=melodic FROM osrf/ros:$ROS_DISTRO-desktop @@ -34,4 +34,4 @@ RUN apt-get update && \ # replace entrypoint ENTRYPOINT ["/ros_ws/ros_entrypoint.sh"] -CMD ["bash"] +CMD ["bash"] \ No newline at end of file diff --git a/flash-firmware.py b/flash-firmware.py index efe106e..60304d0 100755 --- a/flash-firmware.py +++ b/flash-firmware.py @@ -1,50 +1,38 @@ #!/usr/bin/python3 -# Copyright 2023 Husarion -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import sh +import sh import time import sys import argparse from periphery import GPIO -class FirmwareFlasher: +class FirmwareFlasher: def __init__(self, sys_arch, binary_file): + self.binary_file = binary_file self.sys_arch = sys_arch - self.max_approach_no = 3 + self.max_approach_no = 5 print(f"System architecture: {self.sys_arch}") - if self.sys_arch == "armv7l\n": + if self.sys_arch.stdout == b'armv7l\n': # Setups ThinkerBoard pins print("Device: ThinkerBoard\n") self.port = "/dev/ttyS1" boot0_pin_no = 164 reset_pin_no = 184 + - elif self.sys_arch == "x86_64\n": + elif self.sys_arch.stdout == b'x86_64\n': # Setups UpBoard pins print("Device: UpBoard\n") self.port = "/dev/ttyS4" boot0_pin_no = 17 reset_pin_no = 18 - - elif self.sys_arch == "aarch64\n": + + elif self.sys_arch.stdout == b'aarch64\n': # Setups RPi pins print("Device: RPi\n") self.port = "/dev/ttyAMA0" @@ -57,68 +45,79 @@ def __init__(self, sys_arch, binary_file): self.boot0_pin = GPIO(boot0_pin_no, "out") self.reset_pin = GPIO(reset_pin_no, "out") + def enter_bootloader_mode(self): + self.boot0_pin.write(True) self.reset_pin.write(True) time.sleep(0.2) self.reset_pin.write(False) time.sleep(0.2) + def exit_bootloader_mode(self): + self.boot0_pin.write(False) self.reset_pin.write(True) time.sleep(0.2) self.reset_pin.write(False) time.sleep(0.2) - def try_flash_operation(self, operation_name, flash_command, flash_args): - for i in range(self.max_approach_no): - try: - flash_command(self.port, *flash_args, _out=sys.stdout) - 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): + self.enter_bootloader_mode() - # Disable the flash write-protection - self.try_flash_operation("Write-UnProtection", sh.stm32flash, ["-u"]) + # Flashing the firmware + succes_no = 0 + for i in range(self.max_approach_no): + try: + if succes_no == 0: + # Disable the flash write-protection + sh.stm32flash(self.port, "-u", _out=sys.stdout) + time.sleep(0.2) + succes_no += 1 + + if succes_no == 1: + # Disable the flash read-protection + sh.stm32flash(self.port, "-k", _out=sys.stdout) + time.sleep(0.2) + succes_no += 1 + + if succes_no == 2: + # Flashing the firmware + sh.stm32flash(self.port, "-v", w=self.binary_file, b="115200", _out=sys.stdout) + time.sleep(0.2) + break + except: + pass - # Disable the flash read-protection - self.try_flash_operation("Read-UnProtection", sh.stm32flash, ["-k"]) + else: + print('ERROR! Something goes wrong. Try again.') - # Flashing the firmware - flash_args = ["-v", "-w", self.binary_file, "-b", "115200"] - self.try_flash_operation("Flashing", sh.stm32flash, flash_args) self.exit_bootloader_mode() + def main(): - parser = argparse.ArgumentParser( - description="Flashing the firmware on STM32 microcontroller in ROSbot" - ) + parser = argparse.ArgumentParser( + description='Flashing the firmware on STM32 microcontroller in ROSbot') + parser.add_argument( - "file", - nargs="?", - default="/root/firmware_diff.bin", - help="Path to a firmware file. Default = /root/firmware.bin", - ) - - binary_file = parser.parse_args().file - sys_arch = sh.uname("-m") + "file", + nargs='?', + default="/root/firmware_diff.bin", + help="Path to a firmware file. Default = /root/firmware_diff.bin") + + binary_file = parser.parse_args().file + sys_arch = sh.uname('-m') flasher = FirmwareFlasher(sys_arch, binary_file) flasher.flash_firmware() - print("Done!") + print("Done.") if __name__ == "__main__": - main() + main() \ No newline at end of file