Add build system support for programming ESP32-S2 using DFU utils

This commit is contained in:
Roland Dobai 2020-04-06 16:41:44 +02:00
parent 2aaab7eeef
commit ab9f714248
32 changed files with 444 additions and 53 deletions

View File

@ -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']:

View File

@ -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 <http://dfu-util.sourceforge.net/>`_. 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 <https://github.com/libusb/libusb/wiki/Windows#How_to_use_libusb_on_Windows>`_ 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`).

View File

@ -11,6 +11,7 @@ API Guides
Build System <build-system>
:esp32: Build System (Legacy GNU Make) <build-system-legacy>
Deep Sleep Wake Stubs <deep-sleep-stub>
:esp32s2: Device Firmware Upgrade through USB <dfu>
Error Handling <error-handling>
:esp32: ESP-BLE-MESH <esp-ble-mesh/ble-mesh-index>
ESP-MESH (Wi-Fi) <mesh>

View File

@ -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
---

View File

@ -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".

View File

@ -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".

View File

@ -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
=================================

View File

@ -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.

View File

@ -0,0 +1 @@
.. include:: ../../en/api-guides/dfu.rst

View File

@ -12,6 +12,7 @@ API 指南
严重错误 <fatal-errors>
Event Handling <event-handling>
Deep Sleep Wake Stubs <deep-sleep-stub>
:esp32s2: Device Firmware Upgrade through USB <dfu>
ESP32 Core Dump <core_dump>
Flash Encryption <../security/flash-encryption>
FreeRTOS SMP Changes <freertos-smp>

View File

@ -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
---

View File

@ -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"。

View File

@ -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"。

View File

@ -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
从源代码编译工具链
=================================

View File

@ -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 平台的下载安装问题。

View File

@ -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

View File

@ -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

View File

@ -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:"

26
tools/cmake/dfu.cmake Normal file
View File

@ -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()

View File

@ -43,6 +43,7 @@ if(NOT __idf_env_set)
include(utilities)
include(targets)
include(ldgen)
include(dfu)
include(version)
__build_init("${idf_path}")

View File

@ -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}")

View File

@ -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

View File

@ -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 {}

View File

@ -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

View File

@ -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 <address, filename> 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="<address> <file>", 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 <address> <file> items')
write_parser.add_argument("files",
metavar="<address> <file>", help='Add <file> at <address>',
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__":

BIN
tools/test_mkdfu/1/1.bin Normal file

Binary file not shown.

BIN
tools/test_mkdfu/1/2.bin Normal file

Binary file not shown.

BIN
tools/test_mkdfu/1/3.bin Normal file

Binary file not shown.

BIN
tools/test_mkdfu/1/dfu.bin Normal file

Binary file not shown.

View File

@ -0,0 +1,7 @@
{
"flash_files" : {
"0x8000" : "2.bin",
"0x1000" : "1.bin",
"0x10000" : "3.bin"
}
}

99
tools/test_mkdfu/test_mkdfu.py Executable file
View File

@ -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()

View File

@ -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