mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Add ability to select a device for DFU flashing
This commit is contained in:
parent
e1ec6c86e6
commit
0ff8ec66e4
@ -64,6 +64,22 @@ which relies on `dfu-util <http://dfu-util.sourceforge.net/>`_. Please see :ref:
|
||||
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.
|
||||
|
||||
If there are more boards with the same chip connected then ``idf.py dfu-list`` can be used to list the available
|
||||
devices, for example::
|
||||
|
||||
Found Runtime: [303a:0002] ver=0723, devnum=4, cfg=1, intf=2, path="1-10", alt=0, name="UNKNOWN", serial="0"
|
||||
Found Runtime: [303a:0002] ver=0723, devnum=6, cfg=1, intf=2, path="1-2", alt=0, name="UNKNOWN", serial="0"
|
||||
|
||||
Consequently, the desired device can be selected for flashing by the ``--path`` argument. For example, the devices
|
||||
listed above can be flashed individually by the following commands::
|
||||
|
||||
idf.py dfu-flash --path 1-10
|
||||
idf.py dfu-flash --path 1-2
|
||||
|
||||
.. note::
|
||||
The vendor and product identificators are set based on the selected chip target by the ``idf.py set-target``
|
||||
command and it is not selectable during the ``idf.py dfu-flash`` call.
|
||||
|
||||
See :ref:`api_guide_dfu_flash_errors` and their solutions.
|
||||
|
||||
.. _api_guide_dfu_flash_udev:
|
||||
|
@ -3,8 +3,12 @@
|
||||
|
||||
function(__add_dfu_targets)
|
||||
idf_build_get_property(target IDF_TARGET)
|
||||
if(NOT "${target}" STREQUAL "esp32s2")
|
||||
if("${target}" STREQUAL "esp32")
|
||||
return()
|
||||
elseif("${target}" STREQUAL "esp32s2")
|
||||
set(dfu_pid "2")
|
||||
else()
|
||||
message(FATAL_ERROR "DFU PID unknown for ${target}")
|
||||
endif()
|
||||
|
||||
idf_build_get_property(python PYTHON)
|
||||
@ -14,13 +18,21 @@ function(__add_dfu_targets)
|
||||
COMMAND ${python} ${idf_path}/tools/mkdfu.py write
|
||||
-o "${CMAKE_CURRENT_BINARY_DIR}/dfu.bin"
|
||||
--json "${CMAKE_CURRENT_BINARY_DIR}/flasher_args.json"
|
||||
--pid "${dfu_pid}"
|
||||
DEPENDS gen_project_binary bootloader
|
||||
VERBATIM
|
||||
USES_TERMINAL)
|
||||
|
||||
add_custom_target(dfu-list
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-D ESP_DFU_LIST="1"
|
||||
-P ${idf_path}/tools/cmake/run_dfu_util.cmake
|
||||
USES_TERMINAL)
|
||||
|
||||
add_custom_target(dfu-flash
|
||||
COMMAND dfu-util
|
||||
-D "${CMAKE_CURRENT_BINARY_DIR}/dfu.bin"
|
||||
VERBATIM
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
-D ESP_DFU_BIN="${CMAKE_CURRENT_BINARY_DIR}/dfu.bin"
|
||||
-D ESP_DFU_PID="${dfu_pid}"
|
||||
-P ${idf_path}/tools/cmake/run_dfu_util.cmake
|
||||
USES_TERMINAL)
|
||||
endfunction()
|
||||
|
28
tools/cmake/run_dfu_util.cmake
Normal file
28
tools/cmake/run_dfu_util.cmake
Normal file
@ -0,0 +1,28 @@
|
||||
# A CMake script to run dfu-util from within ninja or make
|
||||
# or another cmake-based build runner
|
||||
#
|
||||
# It is recommended to NOT USE this CMake script directly
|
||||
|
||||
cmake_minimum_required(VERSION 3.5)
|
||||
|
||||
set(TOOL "dfu-util")
|
||||
set(CMD "${TOOL}")
|
||||
|
||||
if(${ESP_DFU_LIST})
|
||||
list(APPEND CMD "--list")
|
||||
else()
|
||||
# The following works even when ESP_DFU_PID is not defined.
|
||||
list(APPEND CMD "-d" "303a:${ESP_DFU_PID}")
|
||||
|
||||
if(NOT $ENV{ESP_DFU_PATH} STREQUAL "")
|
||||
list(APPEND CMD "--path" $ENV{ESP_DFU_PATH})
|
||||
endif()
|
||||
list(APPEND CMD "-D" ${ESP_DFU_BIN})
|
||||
endif()
|
||||
|
||||
message("Command list: ${CMD}")
|
||||
execute_process(COMMAND ${CMD} RESULT_VARIABLE result)
|
||||
|
||||
if(${result})
|
||||
message(FATAL_ERROR "${TOOL} failed")
|
||||
endif()
|
@ -10,11 +10,11 @@ def action_extensions(base_actions, project_path):
|
||||
ensure_build_directory(args, ctx.info_name)
|
||||
run_target(target_name, args)
|
||||
|
||||
def dfu_flash_target(target_name, ctx, args):
|
||||
def dfu_flash_target(target_name, ctx, args, path):
|
||||
ensure_build_directory(args, ctx.info_name)
|
||||
|
||||
try:
|
||||
run_target(target_name, args)
|
||||
run_target(target_name, args, {"ESP_DFU_PATH": path})
|
||||
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 '
|
||||
@ -28,10 +28,24 @@ def action_extensions(base_actions, project_path):
|
||||
"short_help": "Build the DFU binary",
|
||||
"dependencies": ["all"],
|
||||
},
|
||||
"dfu-list": {
|
||||
"callback": dfu_target,
|
||||
"short_help": "List DFU capable devices",
|
||||
"dependencies": [],
|
||||
},
|
||||
"dfu-flash": {
|
||||
"callback": dfu_flash_target,
|
||||
"short_help": "Flash the DFU binary",
|
||||
"order_dependencies": ["dfu"],
|
||||
"options": [
|
||||
{
|
||||
"names": ["--path"],
|
||||
"default": "",
|
||||
"help": "Specify path to DFU device. The default empty path works if there is just one "
|
||||
"ESP device with the same product identificator. See the device list for paths "
|
||||
"of available devices."
|
||||
}
|
||||
],
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -107,8 +107,6 @@ DFUSuffix = namedtuple(
|
||||
"DFUSuffix", ["bcd_device", "pid", "vid", "bcd_dfu", "sig", "len"]
|
||||
)
|
||||
ESPRESSIF_VID = 12346
|
||||
# TODO: set PID based on the chip type (add a command line argument)
|
||||
DFUSUFFIX_DEFAULT = DFUSuffix(0xFFFF, 0xFFFF, ESPRESSIF_VID, 0x0100, b"UFD", 16)
|
||||
# This CRC32 gets added after DFUSUFFIX_STRUCT
|
||||
DFUCRC_STRUCT = b"<I"
|
||||
|
||||
@ -126,8 +124,9 @@ def pad_bytes(b, multiple, padding=b"\x00"): # type: (bytes, int, bytes) -> byt
|
||||
|
||||
|
||||
class EspDfuWriter(object):
|
||||
def __init__(self, dest_file): # type: (typing.BinaryIO) -> None
|
||||
def __init__(self, dest_file, pid): # type: (typing.BinaryIO) -> None
|
||||
self.dest = dest_file
|
||||
self.pid = pid
|
||||
self.entries = [] # type: typing.List[bytes]
|
||||
self.index = [] # type: typing.List[DFUInfo]
|
||||
|
||||
@ -151,7 +150,8 @@ class EspDfuWriter(object):
|
||||
out_data = pad_bytes(out_data, cpio_block_size)
|
||||
|
||||
# Add DFU suffix and CRC
|
||||
out_data += struct.pack(DFUSUFFIX_STRUCT, *DFUSUFFIX_DEFAULT)
|
||||
dfu_suffix = DFUSuffix(0xFFFF, self.pid, ESPRESSIF_VID, 0x0100, b"UFD", 16)
|
||||
out_data += struct.pack(DFUSUFFIX_STRUCT, *dfu_suffix)
|
||||
out_data += struct.pack(DFUCRC_STRUCT, dfu_crc(out_data))
|
||||
|
||||
# Finally write the entire binary
|
||||
@ -187,7 +187,7 @@ class EspDfuWriter(object):
|
||||
|
||||
|
||||
def action_write(args):
|
||||
writer = EspDfuWriter(args['output_file'])
|
||||
writer = EspDfuWriter(args['output_file'], args['pid'])
|
||||
for addr, f in args['files']:
|
||||
print('Adding {} at {:#x}'.format(f, addr))
|
||||
writer.add_file(addr, f)
|
||||
@ -205,6 +205,10 @@ def main():
|
||||
help='Filename for storing the output DFU image',
|
||||
required=True,
|
||||
type=argparse.FileType("wb"))
|
||||
write_parser.add_argument("--pid",
|
||||
required=True,
|
||||
type=lambda h: int(h, 16),
|
||||
help='Hexa-decimal product indentificator')
|
||||
write_parser.add_argument("--json",
|
||||
help='Optional file for loading "flash_files" dictionary with <address> <file> items')
|
||||
write_parser.add_argument("files",
|
||||
@ -241,6 +245,7 @@ def main():
|
||||
|
||||
cmd_args = {'output_file': args.output_file,
|
||||
'files': files,
|
||||
'pid': args.pid,
|
||||
}
|
||||
|
||||
{'write': action_write
|
||||
|
Binary file not shown.
@ -35,6 +35,7 @@ class TestHelloWorldExample(unittest.TestCase):
|
||||
self.addCleanup(os.unlink, f.name)
|
||||
cmd = ' '.join([sys.executable, mkdfu_path, 'write',
|
||||
'-o', f.name,
|
||||
'--pid', '2',
|
||||
add_args])
|
||||
p = pexpect.spawn(cmd, timeout=10)
|
||||
self.addCleanup(p.terminate, force=True)
|
||||
@ -81,6 +82,7 @@ class TestHelloWorldExample(unittest.TestCase):
|
||||
|
||||
cmd = ' '.join([sys.executable, mkdfu_path, 'write',
|
||||
'-o', output,
|
||||
'--pid', '2',
|
||||
' '.join(['0x1000', bootloader,
|
||||
'0x8000', os.path.join(current_dir, '1', '2.bin'),
|
||||
'0x10000', os.path.join(current_dir, '1', '3.bin')
|
||||
|
Loading…
Reference in New Issue
Block a user