# This file is part of the MicroPython project, http://micropython.org/ # # The MIT License (MIT) # # Copyright (c) 2022 Ibrahim Abdelkader # # Permission is hereby granted, free of charge, to any person obtaining a copy # of this software and associated documentation files (the "Software"), to deal # in the Software without restriction, including without limitation the rights # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the Software is # furnished to do so, subject to the following conditions: # # The above copyright notice and this permission notice shall be included in # all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. # # A minimal esptool implementation to communicate with ESP32 ROM bootloader. # Note this tool does Not support advanced features, other ESP chips or stub loading. # This is only meant to be used for updating the U-blox Nina module firmware. import os import struct from micropython import const from time import sleep import binascii _CMD_SYNC = const(0x08) _CMD_CHANGE_BAUDRATE = const(0x0F) _CMD_ESP_READ_REG = const(0x0A) _CMD_ESP_WRITE_REG = const(0x09) _CMD_SPI_ATTACH = const(0x0D) _CMD_SPI_FLASH_MD5 = const(0x13) _CMD_SPI_FLASH_PARAMS = const(0x0B) _CMD_SPI_FLASH_BEGIN = const(0x02) _CMD_SPI_FLASH_DATA = const(0x03) _CMD_SPI_FLASH_END = const(0x04) _FLASH_ID = const(0) _FLASH_REG_BASE = const(0x60002000) _FLASH_BLOCK_SIZE = const(64 * 1024) _FLASH_SECTOR_SIZE = const(4 * 1024) _FLASH_PAGE_SIZE = const(256) _ESP_ERRORS = { 0x05: "Received message is invalid", 0x06: "Failed to act on received message", 0x07: "Invalid CRC in message", 0x08: "Flash write error", 0x09: "Flash read error", 0x0A: "Flash read length error", 0x0B: "Deflate error", } class ESPFlash: def __init__(self, reset, gpio0, uart, log_enabled=False): self.uart = uart self.reset_pin = reset self.gpio0_pin = gpio0 self.log = log_enabled self.baudrate = 115200 self.md5sum = None try: import hashlib if hasattr(hashlib, "md5"): self.md5sum = hashlib.md5() except ImportError: pass def _log(self, data, out=True): if self.log: size = len(data) print( f"out({size}) => " if out else f"in({size}) <= ", "".join("%.2x" % (i) for i in data[0:10]), ) def _uart_drain(self): while self.uart.read(1) is not None: pass def _read_reg(self, addr): v, d = self._command(_CMD_ESP_READ_REG, struct.pack("= 8: (flag, _cmd, size, val) = struct.unpack(" {baudrate}") self._uart_drain() self._command(_CMD_CHANGE_BAUDRATE, struct.pack("> 16 if flash_bits < 0x12 or flash_bits > 0x19: raise Exception(f"Unexpected flash size bits: 0x{flash_bits:02X}.") flash_size = 2**flash_bits print(f"Flash size {flash_size/1024/1024} MBytes") return flash_size def flash_attach(self): self._command(_CMD_SPI_ATTACH, struct.pack(" {seq+erase_blocks}...") self._command( _CMD_SPI_FLASH_BEGIN, struct.pack( "