esputil is a command line tool for managing Espressif devices. It is a replacement for esptool.py. esputil is part of https://github.com/cpq/mdk. It is written in C and is available as a no-dependency static binary for Mac, Linux, Windows
- Windows binary: esputil.exe
- Linux binary: esputil_linux
- MacOS binary: esputil_macos
Some notable features are:
esputil mkhexcommand can create a single .hex file from multiple .bin files, which is useful for distributing ESP32 firmwares as a single flashable fileesputil unhexcommand unpacks .hex file back into a set of .bin filesesputil flashcommand can flash either .hex files or .bin files
esputil works similarly to esptool.py --no-stub, in other words, it does not use in-memory stub.
$ esputil -h Defaults: BAUD=115200, PORT=/dev/ttyUSB0 Usage: esputil [-v] [-b BAUD] [-p PORT] monitor esputil [-v] [-b BAUD] [-p PORT] info esputil [-v] [-b BAUD] [-p PORT] readmem ADDR SIZE esputil [-v] [-b BAUD] [-p PORT] readflash ADDR SIZE esputil [-v] [-b BAUD] [-p PORT] [-fp FLASH_PARAMS] [-fspi FLASH_SPI] flash ADDRESS1 BINFILE1 ... esputil [-v] [-b BAUD] [-p PORT] [-fp FLASH_PARAMS] [-fspi FLASH_SPI] flash FILE.HEX esputil [-v] mkbin FIRMWARE.ELF FIRMWARE.BIN esputil mkhex ADDRESS1 BINFILE1 ADDRESS2 BINFILE2 ... esputil [-tmp TMP_DIR] unhex HEXFILEExample: flash MDK-built ESP32C3 firmware:
$ esputil flash 0 firmware.binExample: flash ESP-IDF built firmware on ESP32-PICO-Kit board:
$ esputil -fspi 6,17,8,11,16 flash 0x1000 build/bootloader/bootloader.bin \ 0x8000 build/partitions.bin \ 0xe000 build/ota_data_initial.bin \ 0x10000 build/firmware.binFlashing ESP32 chips is done via UART. In order to do so, ESP32 should be rebooted in the flashing mode, by pulling IO0 low during boot. Then, a ROM bootloader uses SLIP framing for a simple serial protocol, which is described at https://docs.espressif.com/projects/esptool/en/latest/advanced-topics/serial-protocol.html.
Using that SLIP protocol, it is possible to write images to flash at any offset. That is what esputil.c implements. The ESP32 image file has the following format:
- COMMON HEADER - 4 bytes, contains number of segments in the image and flash params
- ENTRY POINT ADDRESS - 4 bytes, the beginning of the image code
- EXTENDED HEADER - 16 bytes, contains chip ID and extra flash params
- One or more SEGMENTS, which are padded to 16 bytes
| COMMON HEADER | ENTRY | EXTENDED HEADER | SEGM1 | ... | | 0xe9 N F1 F2 | X X X X | 0xee 0 0 0 C 0 V 0 0 0 0 0 0 0 0 1 | | ... | 0xe9 - Espressif image magic number. All images must start with 0xe9 N - a number of segments in the image F1 - flash mode. 0: QIO, 1: QOUT, 2: DIO, 3: DOUT F2 - flash size (high 4 bits) and flash frequency (low 4 bits): size: 0: 1MB, 0x10: 2MB, 0x20: 4MB, 0x30: 8MB, 0x40: 16MB freq: 0: 40m, 1: 26m, 2: 20m, 0xf: 80m ENTRY - 4-byte entry point address in little endian C - Chip ID. 0: ESP32, 5: ESP32C3 V - Chip revision Segment format: | ADDR | SIZE | DATA | ADDR - segment load address SIZE - segment size, aligned to 4 bytes DATA - segment data, padded with 0 to 16-byte boundary Image header format includes two bytes, F1 and F2, which desribe SPI flash parameters that ROM bootloader uses to load the rest of the firmware.
- Flash mode. F1 byte,
0: qio,1: qout,2: dio,3: dout - FLash size. High 4 bits of F2 byte,
- for ESP32:
0: 1m,1: 2m,2: 4m,3: 8m,4: 16m - for ESP8266:
0: 512k,1: 256k,2: 1m,3: 2m,4: 4m,8: 8m,9: 16m
- for ESP32:
- Flash frequency. Low 4 bits of F2 byte,
0: 40m,1: 26m,2: 20m,f: 80m
By default, esputil fetches flash params F1 and F2 from the existing bootloader by reading first 4 bytes of the bootloader from flash. It is possible to manually set flash params via the -fp 0xABC command line flag, where A is flash mode, B is flash size, C is flash frequency. For example fp 0x220 sets flash to DIO, 4MB, 40MHz:
$ esputil -fp 0x220 flash 0 firmware.binSome boards fail to talk to flash: when you attempt to esputil flash them, they'll time out with the flash_begin/erase failed, for example trying to flash a bootloader on a ESP32-PICO-D4-Kit:
$ esputil flash 4096 build/bootloader/bootloader.bin Error: can't read bootloader @ addr 0x1000 Erasing 24736 bytes @ 0x1000 flash_begin/erase failedThis is because ROM bootloader on such boards have wrong SPI pins settings. Espressif's esptool.py alleviates that by uploading its own piece of software into ESP32 RAM, which does the right thing. esputil uses ROM bootloader, and in order to fix an issue, a -fspi FLASH_PARAMS parameter can be set which manually sets flash SPI pins. The format of the FLASH_PARAMS is five comma-separated integers for CLK,Q,D,HD,CS pins.
A previously failed ESP32-PICO-D4-Kit example can be fixed by passing a correct SPI pin settings:
$ esputil -fspi 6,17,8,11,16 flash 4096 build/bootloader/bootloader.bin Written build/bootloader/bootloader.bin, 24736 bytes @ 0x1000