Skip to content

esp32s3_hmi43v3_factory_app_tools

Host-side Python developer tools for the ESP32-S3 HMI 4.3” V3 factory application. This module provides four scripts that cover the complete factory workflow: initial board provisioning, firmware updates, display font generation, and screenshot debugging. All scripts run on the developer’s PC — none are compiled into firmware.


  1. Module Context
  2. Tools Overview
  3. Architecture & Component Relationships
  4. Tool Reference
  5. Data & Process Flows
  6. Prerequisites & Installation
  7. Usage Examples
  8. Cross-Board Pattern

This module sits at the leaf level of the esp32s3_hmi43v3 board hierarchy, inside the factory application sub-tree:

Board_Support_Packages
└── esp32s3_hmi43v3
├── esp32s3_hmi43v3_bsp ← LVGL BSP, RM68120 i80 display, GT911 touch
├── esp32s3_hmi43v3_build_scripts ← build_one.py, variants, common
└── esp32s3_hmi43v3_factory_app
├── esp32s3_hmi43v3_factory_app_main ← app_main, menu, OTA restore
├── esp32s3_hmi43v3_factory_app_display ← gfx.c, rm68120.c (raw renderer)
├── esp32s3_hmi43v3_factory_app_input ← buttons, encoder, touch, buzzer
├── esp32s3_hmi43v3_factory_app_storage ← sdcard mount/unmount
└── esp32s3_hmi43v3_factory_app_tools ← THIS MODULE (host-side tools)

Key relationships with sibling modules:

SiblingRelationship to This Module
esp32s3_hmi43v3_factory_app_displaysnap2png.py converts the raw files that gfx_snapshot_begin, gfx_snapshot_end, and snap_write produce on the board
esp32s3_hmi43v3_factory_app_mainflash_all.py provisions the complete firmware stack that app_main requires; snap_find_next_number names the raw files that snap2png.py consumes
esp32s3_hmi43v3_factory_app_storageSnapshots are written to the SD card managed by sdcard_mount/unmount; flash scripts reference the partition CSV that lives alongside the firmware
esp32s3_hmi43v3_bspgenerate_font.py produces C font tables consumed by gfx_draw_char/string in the factory firmware built against this BSP

ScriptLocationPurposeKey Dependency
flash_all.pyFactory/tools/Complete board provisioning — recovery, full, or firmware-only flashesptool, pyserial
flash_factory.pyFactory/tools/Single-purpose factory partition flash with auto-detected offsetesptool, pyserial
generate_font.pyFactory/tools/generate_font/Renders a TTF or system font into C bitmap arrays for the factory appPillow
snap2png.pyFactory/tools/raw2png/Converts RGB565 raw snapshot files captured on the board to PNGPillow

All scripts are standalone executables (#!/usr/bin/env python3) and accept --help.


Factory Firmware Source

ESP32-S3 HMI 4.3 V3

Developer Host PC

invokes

port scan

invokes

port scan

image rendering

image output

parses

parses

write_flash

write_flash

write_flash

write_flash

write_flash

generates

compiled into

consumed by

writes raw pixels to SD

host reads

produces

flash_all.py

flash_factory.py

generate_font.py

snap2png.py

esptool

pyserial

Pillow / PIL

partitions*.csv

bootloader.bin

partitions.bin

factory.bin

firmware.bin

SD Card: snapXXX.raw

gfx.c - gfx_draw_char / gfx_draw_string

gfx.c - gfx_snapshot_begin / snap_write

fontWxH.c / fontWxH.h

screenshot.png

The factory partition offset is not hard-coded in the scripts — it is discovered by parsing partitions*.csv. The constant 0x7A0000 is used only as a last-resort fallback.

ESP32-S3 Flash (8 MB layout)
────────────────────────────────────────────────────
0x0000_0000 Reserved
0x0000_1000 Bootloader ← bootloader.bin
0x0000_C000 Partition Table ← partitions.bin
0x0001_0000 OTA Data (otadata)
0x0002_0000 OTA app0 slot ← firmware.bin
0x0066_0000 Flash FS (LittleFS / FAT)
0x007A_0000+ Factory Recovery ← factory.bin (auto-detected)
────────────────────────────────────────────────────

esp32s3_hmi43v3_factory_app_tools (host-side only)

Serial UART

Serial UART

C source files

embeds font table

flashes factory.bin

gfx_snapshot writes .raw

developer copies to PC

PNG

flash_all.py

flash_factory.py

generate_font.py

snap2png.py

Developer

ESP32-S3 Chip

idf.py build

factory.bin

SD Card


4.1 flash_all.py — Full Flash Orchestration

Section titled “4.1 flash_all.py — Full Flash Orchestration”

Path: boards/esp32s3_hmi43v3/Factory/tools/flash_all.py

The primary provisioning script. It handles three mutually exclusive flash modes selected via a required argument group. All binary files are validated before any flash operation begins to prevent partial writes.

FlagBinaries WrittenUse Case
--recoverybootloader + partitions + factoryFirst-time board setup or recovery from corrupted OTA state
--full --fw FILEbootloader + partitions + factory + firmwareFull clean install with factory image and production firmware
--fw FILEfirmware only → app0 at 0x20000Rapid firmware-only re-flash during development iteration
FunctionDescription
main()Argument parsing, mode dispatch, pre-flight file checks, port resolution, exit-code propagation
flash(port, baud, files)Builds the esptool write_flash command from a list of (offset, path) tuples; runs via subprocess.run(check=True)
find_factory_offset()Parses partitions*.csv globs to locate the factory entry; returns "0x7A0000" if no CSV is found
find_esp32_port()Scans serial.tools.list_ports for CP210x / CH340 / FTDI adapters; falls back to the first available port
check_file(path, name)Validates file existence and prints size; called for all binaries before any flash starts
BOOTLOADER_OFFSET = "0x1000" # Custom bootloader (44 KB reserved)
PARTITIONS_OFFSET = "0xC000" # Compiled partition table
APP0_OFFSET = "0x20000" # OTA app0 slot (firmware)
# Factory offset is read dynamically from partitions*.csv
Factory/tools/installer/
├── bootloader.bin # Pre-built custom bootloader binary
├── partitions.bin # Compiled partition table binary
└── factory.bin # Factory recovery application binary
flash_all.py [--port PORT] [--baud BAUD]
{ --recovery | --full | --fw FILE }
[--fw-file FILE]
--port, -p Serial port (auto-detected if omitted)
--baud Baud rate (default: 460800)
--recovery Flash bootloader + partitions + factory
--full Flash all four binaries (requires --fw-file or --fw)
--fw FILE Flash firmware binary only (to app0)
--fw-file FILE Firmware path for use alongside --full

4.2 flash_factory.py — Factory Partition Flash

Section titled “4.2 flash_factory.py — Factory Partition Flash”

Path: boards/esp32s3_hmi43v3/Factory/tools/flash_factory.py

A focused script for re-flashing only the factory recovery partition. Useful when the bootloader and main firmware are already installed and only the recovery image needs to be updated.

FunctionDescription
main()Argument parsing, binary existence check, offset resolution, esptool invocation
find_factory_offset()Same CSV-parsing logic as flash_all.py; probes the PARTITION_CSV_PATTERNS glob list
find_esp32_port()Identical auto-detection to flash_all.py
Aspectflash_all.pyflash_factory.py
ScopeMulti-binary, multi-modeSingle binary (factory only)
Mode selectionMandatory mode flagAlways flashes factory
Offset overrideNot supported--offset flag available
Binary path overrideNot supported--bin flag available
flash_factory.py [--port PORT] [--baud BAUD] [--bin FILE] [--offset OFFSET]
--port, -p Serial port (auto-detected if omitted)
--baud Baud rate (default: 460800)
--bin, -b Factory binary path (default: installer/factory.bin)
--offset, -o Flash offset (auto-detected from CSV if omitted)

4.3 generate_font.py — Bitmap Font Generator

Section titled “4.3 generate_font.py — Bitmap Font Generator”

Path: boards/esp32s3_hmi43v3/Factory/tools/generate_font/generate_font.py

Renders a monospace TrueType font at a target pixel cell size into two C source files. The output is compiled directly into the factory firmware, providing character bitmaps consumed by gfx_draw_char() and gfx_draw_string() in esp32s3_hmi43v3_factory_app_display.

  • ASCII printable range: 0x20 (space) through 0x7E (tilde) — 95 characters
  • 1 bit per pixel, MSB = leftmost pixel
  • Row-major order: bytes_per_row = (width + 7) / 8
  • Total flash usage: 95 × bytes_per_row × height bytes
FunctionDescription
main()Parses WxH [output_dir] [--font path] CLI; validates size bounds (width 4–32, height 6–64); orchestrates pipeline
find_monospace_font()Probes known system font paths on Linux, macOS, and Windows
find_best_font_size(font_path, w, h)Iterates point sizes upward and returns the largest that fits the target cell without clipping
render_font(font_path, w, h)Renders all 95 glyphs to Pillow images; aligns baselines globally across the full character set; thresholds pixels at 127; packs bits MSB-first into byte arrays
generate_c_files(glyphs, w, h, output_dir)Writes fontWxH.h (constants + get_glyph declaration) and fontWxH.c (static 2D array + accessor implementation)
/* fontWxH.h --------------------------------------------------------- */
#pragma once
#include <stdint.h>
#define FONT_WIDTH W /* cell width in pixels */
#define FONT_HEIGHT H /* cell height in pixels */
#define FONT_BYTES_PER_ROW ((W+7)/8) /* bytes per pixel row */
/**
* Get glyph data for an ASCII character.
* @param c ASCII character in [0x20, 0x7E]
* @return Pointer to FONT_BYTES_PER_ROW * FONT_HEIGHT bytes (read-only).
* For c outside the range, returns the space glyph (index 0).
*/
const uint8_t *fontWxH_get_glyph(char c);

For a CP437/DOS aesthetic matching the factory app visual style, use Perfect DOS VGA 437 (free, zero-width license):

generate_font.py <WxH> [output_dir] [--font path/to/font.ttf]
WxH Cell size (e.g. 8x16); width 4–32, height 6–64
output_dir Destination for .c/.h output (default: current directory)
--font Path to TrueType font file (system font auto-detected if omitted)

Path: boards/esp32s3_hmi43v3/Factory/tools/raw2png/snap2png.py

Converts raw RGB565 binary snapshot files produced by the board’s factory app into standard PNG files for visual debugging.

Offset Size Type Description
─────────────────────────────────────────────────────────────
0 4 bytes uint32_t Image width (little-endian)
4 4 bytes uint32_t Image height (little-endian)
8 W×H×2 uint16_t[] Pixel data, RGB565, row-major, little-endian

Snapshot files are written to the SD card by gfx_snapshot_begin(), gfx_snapshot_is_capturing(), and snap_write() in esp32s3_hmi43v3_factory_app_display. File naming (snap000.raw, snap001.raw, …) is managed by snap_find_next_number() in esp32s3_hmi43v3_factory_app_main.

r = (pixel >> 11) & 0x1F # extract 5-bit red
g = (pixel >> 5) & 0x3F # extract 6-bit green
b = pixel & 0x1F # extract 5-bit blue
r = (r << 3) | (r >> 2) # scale 5-bit → 8-bit
g = (g << 2) | (g >> 4) # scale 6-bit → 8-bit
b = (b << 3) | (b >> 2) # scale 5-bit → 8-bit
FunctionDescription
main()Argument parsing; enforces single-file constraint when -o is used; iterates over the file list
convert_raw_to_png(raw_path, output_path)Reads 8-byte header, allocates a PIL.Image, calls rgb565_to_rgb888 per pixel, saves PNG
rgb565_to_rgb888(pixel)Bit-shift channel extraction and 5/6→8-bit scaling
snap2png.py FILE [FILE ...] [-o OUTPUT]
FILE One or more .raw snapshot files (glob-friendly)
-o OUTPUT Output PNG filename (only valid with a single input file)

--recovery

--full

--fw FILE

yes

no

exit 0

exit non-zero

Developer runs flash_all.py

Mode?

Check installer/

bootloader + partitions + factory

Check all 4 binaries

Check firmware FILE only

Resolve serial port

auto-detect or --port

partitions*.csv

found?

Parse CSV for

factory partition offset

Use fallback offset

0x7A0000

Build esptool

write_flash command

subprocess: esptool write_flash

Hard reset board

Exit non-zero

Board running new firmware

python generate_font.py 8x16 ./main

yes

no

Developer

Parse WxH + args

--font

provided?

Load specified TTF

find_monospace_font

System path scan

find_best_font_size

Iterate pt sizes until cell overflows

render_font

Pillow: render 95 glyphs

Global baseline alignment

Threshold at 127

Bit-pack MSB-first

generate_c_files

font8x16.h

constants + get_glyph decl

font8x16.c

static 2D uint8_t array

get_glyph accessor

idf.py build factory firmware

factory.bin

flash_all.py --recovery

Board: gfx_draw_char

calls fontWxH_get_glyph

snap2png.pyHost PCSD CardFactory App (on board)Developersnap2png.pyHost PCSD CardFactory App (on board)Developergfx_snapshot_is_capturing() == trueEach gfx_flush() call invokes snap_write()Navigate to snapshot menu itemsnap_find_next_number() → "snap003"gfx_snapshot_begin()Write snap003.raw[4B width][4B height][RGB565 pixels]gfx_snapshot_end()Remove SD card / mount via card readerCopy snap003.raw to hostpython snap2png.py snap003.rawRead 8-byte header → width, heightRead width × height × 2 bytes pixel datargb565_to_rgb888() per pixelSave snap003.png (standard RGB888 PNG)View screenshot in any image viewer

All tools require Python 3.7+. Install the required packages:

Terminal window
pip install esptool pyserial Pillow
PackageMinimum VersionUsed By
esptool≥ 4.xflash_all.py, flash_factory.py
pyserial≥ 3.xflash_all.py, flash_factory.py (port auto-detection)
Pillow≥ 9.xgenerate_font.py, snap2png.py

ESP-IDF virtual environment: Both flash scripts invoke esptool as sys.executable -m esptool, so they work inside the ESP-IDF Python venv without a separate installation when idf.py is already configured.


Terminal window
cd boards/esp32s3_hmi43v3/Factory/tools
# Auto-detect port — flash bootloader + partition table + factory recovery
python flash_all.py --recovery
# Specify port explicitly (Linux / Windows)
python flash_all.py --recovery --port /dev/ttyUSB0
python flash_all.py --recovery --port COM3
Terminal window
# Flash all four binaries in one operation
python flash_all.py --full --fw ../../../../build/firmware.bin --port COM5
Terminal window
# Re-flash only the application after idf.py build (fastest path)
python flash_all.py --fw ../../../../build/firmware.bin

Refresh only the factory recovery partition

Section titled “Refresh only the factory recovery partition”
Terminal window
# Update factory.bin without touching the bootloader or OTA firmware
python flash_factory.py --bin installer/factory.bin --port /dev/ttyACM0
# Manual offset override (bypasses CSV parsing)
python flash_factory.py --offset 0x7A0000

Generate a bitmap font for the factory app display

Section titled “Generate a bitmap font for the factory app display”
Terminal window
cd boards/esp32s3_hmi43v3/Factory/tools/generate_font
# Auto-detect a system monospace font, write C files to ../main/
python generate_font.py 8x16 ../main
# Use Perfect DOS VGA 437 for a CP437 DOS look
python generate_font.py 8x16 ../main --font "Perfect DOS VGA 437.ttf"
# Generate a larger cell for higher-resolution panels
python generate_font.py 12x24 ../main --font /path/to/MyMono.ttf

The generated font8x16.c and font8x16.h must be added to the factory app’s CMakeLists.txt source list before rebuilding.

Terminal window
cd boards/esp32s3_hmi43v3/Factory/tools/raw2png
# Single file (produces snap000.png in the same directory)
python snap2png.py snap000.raw
# Batch convert all snapshots copied from the SD card
python snap2png.py snap*.raw
# Save to a custom filename
python snap2png.py snap001.raw -o before_update.png

The four-script tools layout is a standardized pattern replicated across all factory-capable boards in this repository. The scripts are functionally identical across boards; only the partition table CSV (which determines the auto-detected factory offset) and the linked display driver differ.

BoardTools Module
pibot_pendant_v1_0pibot_pendant_v1_0_factory_app_tools
esp32s3_8048s070cesp32s3_8048s070c_factory_app_tools
esp32s3_bzm_tft35_gt911esp32s3_bzm_tft35_gt911_factory_app_tools
esp32s3_zx3d50ce02s_usrc_4832esp32s3_zx3d50ce02s_usrc_4832_factory_app

Board-specific differences are limited to:

  • The display driver the factory app links (RM68120 i80 for this board vs. ST7796 SPI, ST7262 RGB, or ILI9341 SPI on others)
  • The partition table CSV, which determines the auto-detected factory partition offset
  • The BSP board support layer used at firmware runtime

See also: