From ab9f7142486aeb7d6e991354da0693caa6421c69 Mon Sep 17 00:00:00 2001 From: Roland Dobai Date: Mon, 6 Apr 2020 16:41:44 +0200 Subject: [PATCH] Add build system support for programming ESP32-S2 using DFU utils --- docs/conf_common.py | 1 + docs/en/api-guides/dfu.rst | 99 +++++++++++++++++ docs/en/api-guides/index.rst | 1 + docs/en/api-guides/tools/idf-tools-notes.inc | 5 + docs/en/get-started/linux-setup-scratch.rst | 6 +- docs/en/get-started/linux-setup.rst | 6 +- docs/en/get-started/macos-setup-scratch.rst | 4 +- docs/en/get-started/macos-setup.rst | 4 +- docs/zh_CN/api-guides/dfu.rst | 1 + docs/zh_CN/api-guides/index.rst | 1 + .../api-guides/tools/idf-tools-notes.inc | 5 + .../zh_CN/get-started/linux-setup-scratch.rst | 6 +- docs/zh_CN/get-started/linux-setup.rst | 6 +- .../zh_CN/get-started/macos-setup-scratch.rst | 4 +- docs/zh_CN/get-started/macos-setup.rst | 4 +- tools/ci/config/host-test.yml | 8 ++ tools/ci/executable-list.txt | 2 + tools/ci/test_build_system_cmake.sh | 10 ++ tools/cmake/dfu.cmake | 26 +++++ tools/cmake/idf.cmake | 1 + tools/cmake/project.cmake | 3 + tools/idf.py | 2 +- tools/idf_py_actions/dfu_ext.py | 39 +++++++ tools/idf_py_actions/tools.py | 7 ++ tools/mkdfu.py | 103 ++++++++++++------ tools/test_mkdfu/1/1.bin | Bin 0 -> 1024 bytes tools/test_mkdfu/1/2.bin | Bin 0 -> 2048 bytes tools/test_mkdfu/1/3.bin | Bin 0 -> 3072 bytes tools/test_mkdfu/1/dfu.bin | Bin 0 -> 10256 bytes tools/test_mkdfu/1/flasher_args.json | 7 ++ tools/test_mkdfu/test_mkdfu.py | 99 +++++++++++++++++ tools/tools.json | 37 +++++++ 32 files changed, 444 insertions(+), 53 deletions(-) create mode 100644 docs/en/api-guides/dfu.rst create mode 100644 docs/zh_CN/api-guides/dfu.rst create mode 100644 tools/cmake/dfu.cmake create mode 100644 tools/idf_py_actions/dfu_ext.py create mode 100644 tools/test_mkdfu/1/1.bin create mode 100644 tools/test_mkdfu/1/2.bin create mode 100644 tools/test_mkdfu/1/3.bin create mode 100644 tools/test_mkdfu/1/dfu.bin create mode 100644 tools/test_mkdfu/1/flasher_args.json create mode 100755 tools/test_mkdfu/test_mkdfu.py diff --git a/docs/conf_common.py b/docs/conf_common.py index 36ecf4ff7..e7ad6e2dd 100644 --- a/docs/conf_common.py +++ b/docs/conf_common.py @@ -159,6 +159,7 @@ def update_exclude_patterns(tags): # note: in toctrees, these also need to be marked with a :esp32: filter for e in ['esp32s2.rst', 'hw-reference/esp32s2/**', + 'api-guides/dfu.rst', 'api-guides/ulps2_instruction_set.rst', 'api-reference/peripherals/hmac.rst', 'api-reference/peripherals/temp_sensor.rst']: diff --git a/docs/en/api-guides/dfu.rst b/docs/en/api-guides/dfu.rst new file mode 100644 index 000000000..251b58c5c --- /dev/null +++ b/docs/en/api-guides/dfu.rst @@ -0,0 +1,99 @@ +*********************************************** +Device Firmware Upgrade through USB +*********************************************** + +.. only:: esp32 + + .. note:: + Device Firmware Upgrade through USB is not supported with ESP32 chips. + +Device Firmware Upgrade (DFU) is a mechanism for upgrading the firmware of devices through Universal Serial Bus (USB). +DFU is supported by ESP32-S2 chips. The necessary connections for the USB peripheral are shown in the following table. + ++------+-------------+ +| GPIO | USB | ++======+=============+ +| 19 | D- (green) | ++------+-------------+ +| 20 | D+ (white) | ++------+-------------+ +| GND | GND (black) | ++------+-------------+ +| | +5V (red) | ++------+-------------+ + +The software requirements of DFU are included in :ref:`get-started-get-prerequisites` of the Getting Started Guide. + +Section :ref:`api_guide_dfu_build` describes how to build firmware for DFU with ESP-IDF and +Section :ref:`api_guide_dfu_flash` deals with flashing the firmware. + +.. _api_guide_dfu_build: + +Building the DFU Image +====================== + +The DFU image can be created by running:: + + idf.py dfu + +which creates ``dfu.bin`` in the build directory. + +.. note:: + Don't forget to set the target chip by ``idf.py set-target`` before running ``idf.py dfu``. Otherwise, you might + create an image for a different chip or receive an error message something like ``unknown target 'dfu'``. + +.. _api_guide_dfu_flash: + +Flashing the Chip with the DFU Image +==================================== + +The DFU image is downloaded into the chip by running:: + + idf.py dfu-flash + +which relies on `dfu-util `_. Please see :ref:`get-started-get-prerequisites` for +installing ``dfu-util``. ``dfu-util`` needs additional setup for :ref:`api_guide_dfu_flash_win` or setting up an +:ref:`api_guide_dfu_flash_udev`. Mac OS users should be able to use ``dfu-util`` without further setup. + +See :ref:`api_guide_dfu_flash_errors` and their solutions. + +.. _api_guide_dfu_flash_udev: + +udev rule (Linux only) +---------------------- + +udev is a device manager for the Linux kernel. It allows us to run ``dfu-util`` (and ``idf.py dfu-flash``) without +``sudo`` for gaining access to the chip. + +Create file ``/etc/udev/rules.d/40-dfuse.rules`` with the following content:: + + SUBSYSTEMS=="usb", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="00??", GROUP="plugdev", MODE="0666" + +.. note:: + Please check the output of command ``groups``. The user has to be a member of the `GROUP` specified above. You may + use some other existing group for this purpose (e.g. `uucp` on some systems instead of `plugdev`) or create a new + group for this purpose. + +Restart your computer so the previous setting could take into affect or run ``sudo udevadm trigger`` to force +manually udev to trigger your new rule. + +.. _api_guide_dfu_flash_win: + +USB drivers (Windows only) +-------------------------- + +``dfu-util`` uses `libusb` to access the device. You have to register on Windows the device with the `WinUSB` driver. +Please see the `libusb wiki `_ for more +details. + +.. _api_guide_dfu_flash_errors: + +Common errors +------------- + +- ``dfu-util: command not found`` might indicate that the tool hasn't been installed or is not available from the terminal. + An easy way of checking the tool is running ``dfu-util --version``. Please see :ref:`get-started-get-prerequisites` for + installing ``dfu-util``. +- The reason for ``No DFU capable USB device available`` could be that the USB driver wasn't properly installed on + Windows (see :ref:`api_guide_dfu_flash_win`) or udev rule was not setup on Linux + (see :ref:`api_guide_dfu_flash_udev`). diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index 4b11122ac..946b85f6c 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -11,6 +11,7 @@ API Guides Build System :esp32: Build System (Legacy GNU Make) Deep Sleep Wake Stubs + :esp32s2: Device Firmware Upgrade through USB Error Handling :esp32: ESP-BLE-MESH ESP-MESH (Wi-Fi) diff --git a/docs/en/api-guides/tools/idf-tools-notes.inc b/docs/en/api-guides/tools/idf-tools-notes.inc index ffd58cd36..426b33edb 100644 --- a/docs/en/api-guides/tools/idf-tools-notes.inc +++ b/docs/en/api-guides/tools/idf-tools-notes.inc @@ -47,4 +47,9 @@ On Linux and macOS, it is recommended to install ninja using the OS-specific pac .. tool-ccache-notes +--- + +.. tool-dfu-util-notes + + --- diff --git a/docs/en/get-started/linux-setup-scratch.rst b/docs/en/get-started/linux-setup-scratch.rst index 1ba2f560d..07b236c9a 100644 --- a/docs/en/get-started/linux-setup-scratch.rst +++ b/docs/en/get-started/linux-setup-scratch.rst @@ -15,15 +15,15 @@ To compile with ESP-IDF you need to get the following packages: - CentOS 7:: - sudo yum install git wget ncurses-devel flex bison gperf python pyserial python-pyelftools cmake ninja-build ccache + sudo yum install git wget ncurses-devel flex bison gperf python pyserial python-pyelftools cmake ninja-build ccache dfu-util - Ubuntu and Debian:: - sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache libffi-dev libssl-dev + sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache libffi-dev libssl-dev dfu-util - Arch:: - sudo pacman -S --needed gcc git make ncurses flex bison gperf python-pyserial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja ccache + sudo pacman -S --needed gcc git make ncurses flex bison gperf python-pyserial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja ccache dfu-util .. note:: CMake version 3.5 or newer is required for use with ESP-IDF. Older Linux distributions may require updating, enabling of a "backports" repository, or installing of a "cmake3" package rather than "cmake". diff --git a/docs/en/get-started/linux-setup.rst b/docs/en/get-started/linux-setup.rst index bde40fe2a..80fcc75b1 100644 --- a/docs/en/get-started/linux-setup.rst +++ b/docs/en/get-started/linux-setup.rst @@ -11,15 +11,15 @@ To compile with ESP-IDF you need to get the following packages: - CentOS 7:: - sudo yum install git wget flex bison gperf python cmake ninja-build ccache + sudo yum install git wget flex bison gperf python cmake ninja-build ccache dfu-util - Ubuntu and Debian:: - sudo apt-get install git wget flex bison gperf python python-pip python-setuptools cmake ninja-build ccache libffi-dev libssl-dev + sudo apt-get install git wget flex bison gperf python python-pip python-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util - Arch:: - sudo pacman -S --needed gcc git make flex bison gperf python-pip cmake ninja ccache + sudo pacman -S --needed gcc git make flex bison gperf python-pip cmake ninja ccache dfu-util .. note:: CMake version 3.5 or newer is required for use with ESP-IDF. Older Linux distributions may require updating, enabling of a "backports" repository, or installing of a "cmake3" package rather than "cmake". diff --git a/docs/en/get-started/macos-setup-scratch.rst b/docs/en/get-started/macos-setup-scratch.rst index e906b9fe7..122373038 100644 --- a/docs/en/get-started/macos-setup-scratch.rst +++ b/docs/en/get-started/macos-setup-scratch.rst @@ -31,11 +31,11 @@ Install Prerequisites - If you have HomeBrew, you can run:: - brew install cmake ninja + brew install cmake ninja dfu-util - If you have MacPorts, you can run:: - sudo port install cmake ninja + sudo port install cmake ninja dfu-util Compile the Toolchain from Source ================================= diff --git a/docs/en/get-started/macos-setup.rst b/docs/en/get-started/macos-setup.rst index caede42ec..5a072c3d7 100644 --- a/docs/en/get-started/macos-setup.rst +++ b/docs/en/get-started/macos-setup.rst @@ -21,11 +21,11 @@ ESP-IDF will use the version of Python installed by default on macOS. - If you have HomeBrew_, you can run:: - brew install cmake ninja + brew install cmake ninja dfu-util - If you have MacPorts_, you can run:: - sudo port install cmake ninja + sudo port install cmake ninja dfu-util - Otherwise, consult the CMake_ and Ninja_ home pages for macOS installation downloads. diff --git a/docs/zh_CN/api-guides/dfu.rst b/docs/zh_CN/api-guides/dfu.rst new file mode 100644 index 000000000..566cdee39 --- /dev/null +++ b/docs/zh_CN/api-guides/dfu.rst @@ -0,0 +1 @@ +.. include:: ../../en/api-guides/dfu.rst diff --git a/docs/zh_CN/api-guides/index.rst b/docs/zh_CN/api-guides/index.rst index 09a32d945..9a08e2ad3 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -12,6 +12,7 @@ API 指南 严重错误 Event Handling Deep Sleep Wake Stubs + :esp32s2: Device Firmware Upgrade through USB ESP32 Core Dump Flash Encryption <../security/flash-encryption> FreeRTOS SMP Changes diff --git a/docs/zh_CN/api-guides/tools/idf-tools-notes.inc b/docs/zh_CN/api-guides/tools/idf-tools-notes.inc index c7c750089..946e8222c 100644 --- a/docs/zh_CN/api-guides/tools/idf-tools-notes.inc +++ b/docs/zh_CN/api-guides/tools/idf-tools-notes.inc @@ -49,4 +49,9 @@ On Linux and macOS, it is recommended to install ninja using the OS package mana .. tool-ccache-notes +--- + +.. tool-dfu-util-notes + + --- diff --git a/docs/zh_CN/get-started/linux-setup-scratch.rst b/docs/zh_CN/get-started/linux-setup-scratch.rst index 3d8bee637..5964e4c3c 100644 --- a/docs/zh_CN/get-started/linux-setup-scratch.rst +++ b/docs/zh_CN/get-started/linux-setup-scratch.rst @@ -13,15 +13,15 @@ - CentOS 7:: - sudo yum install git wget ncurses-devel flex bison gperf python pyserial python-pyelftools cmake ninja-build ccache + sudo yum install git wget ncurses-devel flex bison gperf python pyserial python-pyelftools cmake ninja-build ccache dfu-util - Ubuntu 和 Debian:: - sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache libffi-dev libssl-dev + sudo apt-get install git wget libncurses-dev flex bison gperf python python-pip python-setuptools python-serial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja-build ccache libffi-dev libssl-dev dfu-util - Arch:: - sudo pacman -S --needed gcc git make ncurses flex bison gperf python-pyserial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja ccache + sudo pacman -S --needed gcc git make ncurses flex bison gperf python-pyserial python-click python-cryptography python-future python-pyparsing python-pyelftools cmake ninja ccache dfu-util .. note:: 使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早版本的 Linux 可能需要升级才能向后移植仓库,或安装 "cmake3" 软件包,而不是安装 "cmake"。 diff --git a/docs/zh_CN/get-started/linux-setup.rst b/docs/zh_CN/get-started/linux-setup.rst index 4f6019857..38b04a855 100644 --- a/docs/zh_CN/get-started/linux-setup.rst +++ b/docs/zh_CN/get-started/linux-setup.rst @@ -11,15 +11,15 @@ Linux 平台工具链的标准设置 - CentOS 7:: - sudo yum install git wget flex bison gperf python cmake ninja-build ccache + sudo yum install git wget flex bison gperf python cmake ninja-build ccache dfu-util - Ubuntu 和 Debian:: - sudo apt-get install git wget flex bison gperf python python-pip python-setuptools cmake ninja-build ccache libffi-dev libssl-dev + sudo apt-get install git wget flex bison gperf python python-pip python-setuptools cmake ninja-build ccache libffi-dev libssl-dev dfu-util - Arch:: - sudo pacman -S --needed gcc git make flex bison gperf python-pip python-pyserial cmake ninja ccache + sudo pacman -S --needed gcc git make flex bison gperf python-pip python-pyserial cmake ninja ccache dfu-util .. note:: 使用 ESP-IDF 需要 CMake 3.5 或以上版本。较早版本的 Linux 可能需要升级才能向后移植仓库,或安装 "cmake3" 软件包,而不是安装 "cmake"。 diff --git a/docs/zh_CN/get-started/macos-setup-scratch.rst b/docs/zh_CN/get-started/macos-setup-scratch.rst index f880317cd..68c0d5aba 100644 --- a/docs/zh_CN/get-started/macos-setup-scratch.rst +++ b/docs/zh_CN/get-started/macos-setup-scratch.rst @@ -31,11 +31,11 @@ MacPorts 需要完整的 XCode 软件,而 homebrew 只需要安装 XCode 命 - 若有 HomeBrew,您可以运行:: - brew install cmake ninja + brew install cmake ninja dfu-util - 若有 MacPorts,您可以运行:: - sudo port install cmake ninja + sudo port install cmake ninja dfu-util 从源代码编译工具链 ================================= diff --git a/docs/zh_CN/get-started/macos-setup.rst b/docs/zh_CN/get-started/macos-setup.rst index 4e9322550..c5d3e52bd 100644 --- a/docs/zh_CN/get-started/macos-setup.rst +++ b/docs/zh_CN/get-started/macos-setup.rst @@ -21,11 +21,11 @@ ESP-IDF 将使用 Mac OS 上默认安装的 Python 版本。 - 若有 HomeBrew_,您可以运行:: - brew install cmake ninja + brew install cmake ninja dfu-util - 若有 MacPorts_,您可以运行:: - sudo port install cmake ninja + sudo port install cmake ninja dfu-util - 若以上均不适用,请访问 CMake_ 和 Ninja_ 主页,查询有关 Mac OS 平台的下载安装问题。 diff --git a/tools/ci/config/host-test.yml b/tools/ci/config/host-test.yml index 84ec1cee8..e7018ddc1 100644 --- a/tools/ci/config/host-test.yml +++ b/tools/ci/config/host-test.yml @@ -304,3 +304,11 @@ test_sysviewtrace_proc: script: - cd ${IDF_PATH}/tools/esp_app_trace/test/sysview - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test.sh + +test_mkdfu: + extends: .host_test_template + variables: + LC_ALL: C.UTF-8 + script: + - cd ${IDF_PATH}/tools/test_mkdfu + - ${IDF_PATH}/tools/ci/multirun_with_pyenv.sh ./test_mkdfu.py diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt index 690ba367f..426e30851 100644 --- a/tools/ci/executable-list.txt +++ b/tools/ci/executable-list.txt @@ -85,12 +85,14 @@ tools/ldgen/ldgen.py tools/ldgen/test/test_fragments.py tools/ldgen/test/test_generation.py tools/mass_mfg/mfg_gen.py +tools/mkdfu.py tools/set-submodules-to-github.sh tools/test_check_kconfigs.py tools/test_idf_monitor/run_test_idf_monitor.py tools/test_idf_py/test_idf_py.py tools/test_idf_size/test.sh tools/test_idf_tools/test_idf_tools.py +tools/test_mkdfu/test_mkdfu.py tools/unit-test-app/tools/get_available_configs.sh tools/unit-test-app/unit_test.py tools/windows/eclipse_make.sh diff --git a/tools/ci/test_build_system_cmake.sh b/tools/ci/test_build_system_cmake.sh index ad7e8e49b..555234468 100755 --- a/tools/ci/test_build_system_cmake.sh +++ b/tools/ci/test_build_system_cmake.sh @@ -700,6 +700,16 @@ endmenu\n" >> ${IDF_PATH}/Kconfig bin_header_match build/bootloader/bootloader.bin "021f" rm sdkconfig + print_status "DFU build works" + rm -f -r build sdkconfig + idf.py dfu &> tmp.log + grep "command \"dfu\" is not known to idf.py and is not a Ninja target" tmp.log || (tail -n 100 tmp.log ; failure "DFU build should fail for default chip target") + idf.py set-target esp32s2 + idf.py dfu &> tmp.log + grep "build/dfu.bin\" has been written. You may proceed with DFU flashing." tmp.log || (tail -n 100 tmp.log ; failure "DFU build should succeed for esp32s2") + rm tmp.log + assert_built ${APP_BINS} ${BOOTLOADER_BINS} ${PARTITION_BIN} "dfu.bin" + print_status "All tests completed" if [ -n "${FAILURES}" ]; then echo "Some failures were detected:" diff --git a/tools/cmake/dfu.cmake b/tools/cmake/dfu.cmake new file mode 100644 index 000000000..f29de4b58 --- /dev/null +++ b/tools/cmake/dfu.cmake @@ -0,0 +1,26 @@ +# Add DFU build and flashing related targets +# + +function(__add_dfu_targets) + idf_build_get_property(target IDF_TARGET) + if(NOT "${target}" STREQUAL "esp32s2") + return() + endif() + + idf_build_get_property(python PYTHON) + idf_build_get_property(idf_path IDF_PATH) + + add_custom_target(dfu + COMMAND ${python} ${idf_path}/tools/mkdfu.py write + -o "${CMAKE_CURRENT_BINARY_DIR}/dfu.bin" + --json "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json" + DEPENDS gen_project_binary bootloader + VERBATIM + USES_TERMINAL) + + add_custom_target(dfu-flash + COMMAND dfu-util + -D "${CMAKE_CURRENT_BINARY_DIR}/dfu.bin" + VERBATIM + USES_TERMINAL) +endfunction() diff --git a/tools/cmake/idf.cmake b/tools/cmake/idf.cmake index 2d396c886..82468355e 100644 --- a/tools/cmake/idf.cmake +++ b/tools/cmake/idf.cmake @@ -43,6 +43,7 @@ if(NOT __idf_env_set) include(utilities) include(targets) include(ldgen) + include(dfu) include(version) __build_init("${idf_path}") diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index 11b6c7916..2ec9ea4a6 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -486,6 +486,9 @@ macro(project project_name) unset(idf_size) + # Add DFU build and flash targets + __add_dfu_targets() + idf_build_executable(${project_elf}) __project_info("${test_components}") diff --git a/tools/idf.py b/tools/idf.py index 39716210d..118ff5c30 100755 --- a/tools/idf.py +++ b/tools/idf.py @@ -447,7 +447,7 @@ def init_cli(verbose_output=None): def _print_closing_message(self, args, actions): # print a closing message of some kind # - if "flash" in str(actions): + if "flash" in str(actions) or "dfu" in str(actions): print("Done") return diff --git a/tools/idf_py_actions/dfu_ext.py b/tools/idf_py_actions/dfu_ext.py new file mode 100644 index 000000000..af8d2d7fa --- /dev/null +++ b/tools/idf_py_actions/dfu_ext.py @@ -0,0 +1,39 @@ +from idf_py_actions.tools import is_target_supported, ensure_build_directory, run_target +from idf_py_actions.errors import FatalError + + +def action_extensions(base_actions, project_path): + + SUPPORTED_TARGETS = ['esp32s2'] + + def dfu_target(target_name, ctx, args): + ensure_build_directory(args, ctx.info_name) + run_target(target_name, args) + + def dfu_flash_target(target_name, ctx, args): + ensure_build_directory(args, ctx.info_name) + + try: + run_target(target_name, args) + except FatalError: + # Cannot capture the error from dfu-util here so the best advise is: + print('Please have a look at the "Device Firmware Upgrade through USB" chapter in API Guides of the ' + 'ESP-IDF documentation for solving common dfu-util issues.') + raise + + dfu_actions = { + "actions": { + "dfu": { + "callback": dfu_target, + "short_help": "Build the DFU binary", + "dependencies": ["all"], + }, + "dfu-flash": { + "callback": dfu_flash_target, + "short_help": "Flash the DFU binary", + "order_dependencies": ["dfu"], + }, + } + } + + return dfu_actions if is_target_supported(project_path, SUPPORTED_TARGETS) else {} diff --git a/tools/idf_py_actions/tools.py b/tools/idf_py_actions/tools.py index 663522b82..d96ee9f35 100644 --- a/tools/idf_py_actions/tools.py +++ b/tools/idf_py_actions/tools.py @@ -269,6 +269,13 @@ def get_sdkconfig_value(sdkconfig_file, key): return value +def is_target_supported(project_path, supported_targets): + """ + Returns True if the active target is supported, or False otherwise. + """ + return get_sdkconfig_value(os.path.join(project_path, "sdkconfig"), 'CONFIG_IDF_TARGET') in supported_targets + + def _guess_or_check_idf_target(args, prog_name, cache): """ If CMakeCache.txt doesn't exist, and IDF_TARGET is not set in the environment, guess the value from diff --git a/tools/mkdfu.py b/tools/mkdfu.py index eecd00b55..d2e562c71 100755 --- a/tools/mkdfu.py +++ b/tools/mkdfu.py @@ -1,16 +1,31 @@ #!/usr/bin/env python # +# Copyright 2020 Espressif Systems (Shanghai) PTE LTD +# +# 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. +# # This program creates archives compatible with ESP32-S* ROM DFU implementation. # # The archives are in CPIO format. Each file which needs to be flashed is added to the archive # as a separate file. In addition to that, a special index file, 'dfuinfo0.dat', is created. # This file must be the first one in the archive. It contains binary structures describing each # subsequent file (for example, where the file needs to be flashed/loaded). -# -import argparse from collections import namedtuple +from future.utils import iteritems +import argparse import hashlib +import json import os import struct import zlib @@ -21,6 +36,12 @@ except ImportError: # Only used for type annotations pass +try: + from itertools import izip as zip +except ImportError: + # Python 3 + pass + # CPIO ("new ASCII") format related things CPIO_MAGIC = b"070701" CPIO_STRUCT = b"=6s" + b"8s" * 13 @@ -166,46 +187,64 @@ class EspDfuWriter(object): def action_write(args): - writer = EspDfuWriter(args.output_file) - for addr, file in args.files: - writer.add_file(addr, file) + writer = EspDfuWriter(args['output_file']) + for addr, f in args['files']: + print('Adding {} at {:#x}'.format(f, addr)) + writer.add_file(addr, f) writer.finish() - - -class WriteArgsAction(argparse.Action): - """ Helper for argparse to parse argument pairs """ - - def __init__(self, *args, **kwargs): - super(WriteArgsAction, self).__init__(*args, **kwargs) - - def __call__(self, parser, namespace, values, option_string=None): - # TODO: add validation - addr = 0 - result = [] - for i, value in enumerate(values): - if i % 2 == 0: - addr = int(value, 0) - else: - result.append((addr, value)) - - setattr(namespace, self.dest, result) + print('"{}" has been written. You may proceed with DFU flashing.'.format(args['output_file'].name)) def main(): - parser = argparse.ArgumentParser("mkdfu") + parser = argparse.ArgumentParser() # Provision to add "info" command subparsers = parser.add_subparsers(dest="command") write_parser = subparsers.add_parser("write") - write_parser.add_argument("-o", "--output-file", type=argparse.FileType("wb")) - write_parser.add_argument( - "files", metavar="
", action=WriteArgsAction, nargs="+" - ) + write_parser.add_argument("-o", "--output-file", + help='Filename for storing the output DFU image', + required=True, + type=argparse.FileType("wb")) + write_parser.add_argument("--json", + help='Optional file for loading "flash_files" dictionary with
items') + write_parser.add_argument("files", + metavar="
", help='Add at
', + nargs="*") args = parser.parse_args() - print(repr(args)) - if args.command == "write": - action_write(args) + + def check_file(file_name): + if not os.path.isfile(file_name): + raise RuntimeError('{} is not a regular file!'.format(file_name)) + return file_name + + files = [] + if args.files: + files += [(int(addr, 0), check_file(f_name)) for addr, f_name in zip(args.files[::2], args.files[1::2])] + + if args.json: + json_dir = os.path.dirname(os.path.abspath(args.json)) + + def process_json_file(path): + ''' + The input path is relative to json_dir. This function makes it relative to the current working + directory. + ''' + return check_file(os.path.relpath(os.path.join(json_dir, path), start=os.curdir)) + + with open(args.json) as f: + files += [(int(addr, 0), + process_json_file(f_name)) for addr, f_name in iteritems(json.load(f)['flash_files'])] + + files = sorted([(addr, f_name) for addr, f_name in iteritems(dict(files))], + key=lambda x: x[0]) # remove possible duplicates and sort based on the address + + cmd_args = {'output_file': args.output_file, + 'files': files, + } + + {'write': action_write + }[args.command](cmd_args) if __name__ == "__main__": diff --git a/tools/test_mkdfu/1/1.bin b/tools/test_mkdfu/1/1.bin new file mode 100644 index 0000000000000000000000000000000000000000..60320aa0dfc237aa20e77095a77bc7ba1d92c23e GIT binary patch literal 1024 zcmV+b1poW?rO<&1Jk2e#T6U3AHj9`>iTrAJGFqQzUBo~;Eyvw~SyAkXsF5QyW+`d7 zh!b}HXY{h>#&X(}oyD6EsOUn*cHmy$JfV>O9Lp?q`K${11n~_)!zIFZ0%{rnK|h+? z0}ZFMpmhKnRr5+Eu_MT&FXV~U3CvfL2d&+7H%jOn=L!@ z1naJSE#b&XK{Uwr4?2nL_XjRgGPobYp6LjUk!r05ktSaR66!rE2KR>sZ3ugOW}_y# zcFQ-_Mx5IrHaVLSXpyH}p2&%#z4t;VHXVyrwG(Gt2iuUeXaa__a(S~G%4l995e3N( zwb3k4&X}eQ)b(q}Vpf~ds7!%6$k9QZX}e;PpN=&6%zvcKt(N?6X`=AcM$F76fr=t; zJ}lFldntGW9# zs&i}FsEXw}3oFEN>yoGFeAAA$%J~SY%CU!LJWpb=RnISDLMubkJ~7(sMMpf%&yr#+ zl!`a20@zqLb6ci>(mBJ%uk*K1H?e%0aP@&Xz61dr)Pc|nibKpX+Bg$5=7-7kNgbSA zGiqoa!}3JGc78iIl?0&prLpIy@h|+}>m__@o*txA7(WI&*PXa2&NQ;Y$>>j9DyE1c zc`^{kMUz+fKorrIC($Vui-8_6tK3mbORDINI4uy`X#R*KP`F*iO zI=*+1fPEUa-^AeqCN;S6UX?GP%-Dc3a8a)(fiAhjXtYcaguIoX>^sPhQmr5h^pl=F z_Z$gva4W~m< zI8?Q8@8O8n&1)}O{(Mp@m?KnoPZ-O@@wb3<8rT!-Bg&yrdj-Pp7b u?A)#U+?v$C@qJO^*1&*^J@g226}>9wJpDj3pAieN>!OtQj+!LDNO(=k+5bKO literal 0 HcmV?d00001 diff --git a/tools/test_mkdfu/1/2.bin b/tools/test_mkdfu/1/2.bin new file mode 100644 index 0000000000000000000000000000000000000000..1b9950f09d21d0a83b8d0079da0fd3f56a8b483f GIT binary patch literal 2048 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 Oindgtr?zsZWQVGQ!Sa*< literal 0 HcmV?d00001 diff --git a/tools/test_mkdfu/1/dfu.bin b/tools/test_mkdfu/1/dfu.bin new file mode 100644 index 0000000000000000000000000000000000000000..74f9fef52c94be0d0c2513169d43ce1f7d7337f0 GIT binary patch literal 10256 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 WKLq~mui#^afK-=~Kr8Etu>K#0?Q`1z literal 0 HcmV?d00001 diff --git a/tools/test_mkdfu/1/flasher_args.json b/tools/test_mkdfu/1/flasher_args.json new file mode 100644 index 000000000..06a54d0cc --- /dev/null +++ b/tools/test_mkdfu/1/flasher_args.json @@ -0,0 +1,7 @@ +{ + "flash_files" : { + "0x8000" : "2.bin", + "0x1000" : "1.bin", + "0x10000" : "3.bin" + } +} diff --git a/tools/test_mkdfu/test_mkdfu.py b/tools/test_mkdfu/test_mkdfu.py new file mode 100755 index 000000000..1ce60c227 --- /dev/null +++ b/tools/test_mkdfu/test_mkdfu.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +# +# Copyright 2020 Espressif Systems (Shanghai) CO LTD +# +# 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. + +from __future__ import unicode_literals +import filecmp +import os +import pexpect +import shutil +import sys +import tempfile +import time +import unittest + +current_dir = os.path.dirname(os.path.realpath(__file__)) +mkdfu_path = os.path.join(current_dir, '..', 'mkdfu.py') + + +class TestHelloWorldExample(unittest.TestCase): + def common_test(self, add_args): + with tempfile.NamedTemporaryFile(delete=False) as f: + self.addCleanup(os.unlink, f.name) + cmd = ' '.join([sys.executable, mkdfu_path, 'write', + '-o', f.name, + add_args]) + p = pexpect.spawn(cmd, timeout=10) + self.addCleanup(p.terminate, force=True) + + p.expect_exact(['Adding 1/bootloader.bin at 0x1000', + 'Adding 1/partition-table.bin at 0x8000', + 'Adding 1/hello-world.bin at 0x10000', + '"{}" has been written. You may proceed with DFU flashing.'.format(f.name)]) + + # Need to wait for the process to end because the output file is closed when mkdfu exits. + # Do non-blocking wait instead of the blocking p.wait(): + for _ in range(10): + if not p.isalive(): + break + time.sleep(0.5) + else: + p.terminate() + + self.assertTrue(filecmp.cmp(f.name, os.path.join(current_dir, '1','dfu.bin')), 'Output files are different') + + def test_with_json(self): + self.common_test(' '.join(['--json', os.path.join(current_dir, '1', 'flasher_args.json')])) + + def test_without_json(self): + + self.common_test(' '.join(['0x1000', os.path.join(current_dir, '1', '1.bin'), + '0x8000', os.path.join(current_dir, '1', '2.bin'), + '0x10000', os.path.join(current_dir, '1', '3.bin') + ])) + + def test_filenames(self): + temp_dir = tempfile.mkdtemp(prefix='very_long_directory_name' * 8) + self.addCleanup(shutil.rmtree, temp_dir, ignore_errors=True) + + with tempfile.NamedTemporaryFile(dir=temp_dir, delete=False) as f: + output = f.name + + with tempfile.NamedTemporaryFile(prefix='ľščťžýáíéěř\u0420\u043e\u0441\u0441\u0438\u044f', + dir=temp_dir, + delete=False) as f: + bootloader = f.name + + shutil.copyfile(os.path.join(current_dir, '1', '1.bin'), bootloader) + + cmd = ' '.join([sys.executable, mkdfu_path, 'write', + '-o', output, + ' '.join(['0x1000', bootloader, + '0x8000', os.path.join(current_dir, '1', '2.bin'), + '0x10000', os.path.join(current_dir, '1', '3.bin') + ]) + ]) + p = pexpect.spawn(cmd, timeout=10, encoding='utf-8') + self.addCleanup(p.terminate, force=True) + + p.expect_exact(['Adding {} at 0x1000'.format(bootloader), + 'Adding 1/2.bin at 0x8000', + 'Adding 1/3.bin at 0x10000', + '"{}" has been written. You may proceed with DFU flashing.'.format(output)]) + + +if __name__ == '__main__': + unittest.main() diff --git a/tools/tools.json b/tools/tools.json index f1c93c2f6..840a734e6 100644 --- a/tools/tools.json +++ b/tools/tools.json @@ -483,6 +483,43 @@ } } ] + }, + { + "description": "dfu-util (Device Firmware Upgrade Utilities)", + "export_paths": [ + [ + "dfu-util-0.9-win64" + ] + ], + "export_vars": {}, + "info_url": "http://dfu-util.sourceforge.net/", + "install": "never", + "license": "GPL-2.0-only", + "name": "dfu-util", + "platform_overrides": [ + { + "install": "always", + "platforms": [ + "win64" + ] + } + ], + "version_cmd": [ + "dfu-util", + "--version" + ], + "version_regex": "dfu-util ([0-9.]+)", + "versions": [ + { + "name": "0.9", + "status": "recommended", + "win64": { + "sha256": "5816d7ec68ef3ac07b5ac9fb9837c57d2efe45b6a80a2f2bbe6b40b1c15c470e", + "size": 735635, + "url": "https://dl.espressif.com/dl/dfu-util-0.9-win64.zip" + } + } + ] } ], "version": 1