Update: 更新esptool ( version: 4.7.0 )
This commit is contained in:
96
tools/python/esptool/uf2_writer.py
Normal file
96
tools/python/esptool/uf2_writer.py
Normal file
@@ -0,0 +1,96 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# SPDX-FileCopyrightText: 2020-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: GPL-2.0-or-later
|
||||
# Code was originally licensed under Apache 2.0 before the release of ESP-IDF v5.2
|
||||
|
||||
import hashlib
|
||||
import os
|
||||
import struct
|
||||
from typing import List
|
||||
|
||||
from util import div_roundup
|
||||
|
||||
|
||||
class UF2Writer(object):
|
||||
# The UF2 format is described here: https://github.com/microsoft/uf2
|
||||
UF2_BLOCK_SIZE = 512
|
||||
# max value of CHUNK_SIZE reduced by optional parts. Currently, MD5_PART only.
|
||||
UF2_DATA_SIZE = 476
|
||||
UF2_MD5_PART_SIZE = 24
|
||||
UF2_FIRST_MAGIC = 0x0A324655
|
||||
UF2_SECOND_MAGIC = 0x9E5D5157
|
||||
UF2_FINAL_MAGIC = 0x0AB16F30
|
||||
UF2_FLAG_FAMILYID_PRESENT = 0x00002000
|
||||
UF2_FLAG_MD5_PRESENT = 0x00004000
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
chip_id: int,
|
||||
output_file: os.PathLike,
|
||||
chunk_size: int,
|
||||
md5_enabled: bool = True,
|
||||
) -> None:
|
||||
if not md5_enabled:
|
||||
self.UF2_MD5_PART_SIZE = 0
|
||||
self.UF2_FLAG_MD5_PRESENT = 0x00000000
|
||||
self.md5_enabled = md5_enabled
|
||||
self.chip_id = chip_id
|
||||
self.CHUNK_SIZE = (
|
||||
self.UF2_DATA_SIZE - self.UF2_MD5_PART_SIZE
|
||||
if chunk_size is None
|
||||
else chunk_size
|
||||
)
|
||||
self.f = open(output_file, "wb")
|
||||
|
||||
def __enter__(self) -> "UF2Writer":
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type: str, exc_val: int, exc_tb: List) -> None:
|
||||
if self.f:
|
||||
self.f.close()
|
||||
|
||||
@staticmethod
|
||||
def _to_uint32(num: int) -> bytes:
|
||||
return struct.pack("<I", num)
|
||||
|
||||
def _write_block(
|
||||
self, addr: int, chunk: bytes, len_chunk: int, block_no: int, blocks: int
|
||||
) -> None:
|
||||
assert len_chunk > 0
|
||||
assert len_chunk <= self.CHUNK_SIZE
|
||||
assert block_no < blocks
|
||||
block = struct.pack(
|
||||
"<IIIIIIII",
|
||||
self.UF2_FIRST_MAGIC,
|
||||
self.UF2_SECOND_MAGIC,
|
||||
self.UF2_FLAG_FAMILYID_PRESENT | self.UF2_FLAG_MD5_PRESENT,
|
||||
addr,
|
||||
len_chunk,
|
||||
block_no,
|
||||
blocks,
|
||||
self.chip_id,
|
||||
)
|
||||
block += chunk
|
||||
|
||||
if self.md5_enabled:
|
||||
md5_part = struct.pack("<II", addr, len_chunk)
|
||||
md5_part += hashlib.md5(chunk).digest()
|
||||
assert len(md5_part) == self.UF2_MD5_PART_SIZE
|
||||
|
||||
block += md5_part
|
||||
block += b"\x00" * (self.UF2_DATA_SIZE - self.UF2_MD5_PART_SIZE - len_chunk)
|
||||
block += self._to_uint32(self.UF2_FINAL_MAGIC)
|
||||
assert len(block) == self.UF2_BLOCK_SIZE
|
||||
self.f.write(block)
|
||||
|
||||
def add_file(self, addr: int, image: bytes) -> None:
|
||||
blocks = div_roundup(len(image), self.CHUNK_SIZE)
|
||||
chunks = [
|
||||
image[i : i + self.CHUNK_SIZE]
|
||||
for i in range(0, len(image), self.CHUNK_SIZE)
|
||||
]
|
||||
for i, chunk in enumerate(chunks):
|
||||
len_chunk = len(chunk)
|
||||
self._write_block(addr, chunk, len_chunk, i, blocks)
|
||||
addr += len_chunk
|
||||
Reference in New Issue
Block a user