mirror of
https://github.com/justcallmekoko/ESP32Marauder.git
synced 2025-12-05 20:40:25 -08:00
164 lines
7.1 KiB
Python
164 lines
7.1 KiB
Python
# === ESP32-C5 Auto Flasher Script By: AWOK ===
|
|
|
|
import sys
|
|
import subprocess
|
|
import os
|
|
import platform # Placeholder for possible OS checks
|
|
import glob
|
|
import time
|
|
import shutil
|
|
import argparse
|
|
|
|
def ensure_package(pkg):
|
|
try:
|
|
__import__(pkg if pkg != 'gitpython' else 'git')
|
|
except ImportError:
|
|
print(f"Installing missing package: {pkg}")
|
|
subprocess.check_call([sys.executable, '-m', 'pip', 'install', '--upgrade', pkg])
|
|
|
|
try:
|
|
import serial.tools.list_ports
|
|
except ImportError:
|
|
ensure_package('pyserial')
|
|
try:
|
|
import esptool
|
|
except ImportError:
|
|
ensure_package('esptool')
|
|
try:
|
|
from colorama import Fore, Style
|
|
except ImportError:
|
|
ensure_package('colorama')
|
|
|
|
# Dependency check and install if needed
|
|
REQUIRED_PACKAGES = [
|
|
'pyserial',
|
|
'esptool',
|
|
'colorama'
|
|
]
|
|
|
|
def ensure_requirements():
|
|
for pkg in REQUIRED_PACKAGES:
|
|
ensure_package(pkg)
|
|
ensure_requirements()
|
|
|
|
# Finds the first file from a list of possible names in the bins folder
|
|
def find_file(name_options, bins_dir):
|
|
for name in name_options:
|
|
files = glob.glob(os.path.join(bins_dir, name))
|
|
if files:
|
|
return files[0]
|
|
return None
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description="ESP32-C5 Auto Flasher (bins subdir)")
|
|
parser.parse_args()
|
|
|
|
bins_dir = os.path.join(os.path.dirname(__file__), 'bins')
|
|
if not os.path.isdir(bins_dir):
|
|
print(Fore.RED + f"Bins directory not found: {bins_dir}\nPlease create a 'bins' folder with your .bin files." + Style.RESET_ALL)
|
|
exit(1)
|
|
|
|
# Logo and splash, both centered and purple
|
|
terminal_width = shutil.get_terminal_size((100, 20)).columns
|
|
def center(text): return text.center(terminal_width)
|
|
logo_lines = [
|
|
" @@@@@@ ",
|
|
" @@@@@@@@ @@@@@ @@@@ ",
|
|
" @@@ @@@@@@@ @@@ @@@@@@@@ ",
|
|
" @@@@@@@@@@@@@ @@@@@ @@@ @@@@ @@@ ",
|
|
" @@@ @@@@@ @@@ @@@@@@ @@@ ",
|
|
" @@@ @@@ @@ @@@@ @@@ ",
|
|
" @@@@@@@@@@@@ @@ @ @@@ @@@ @@ ",
|
|
" @@@ @@@@@ @@ @@@ @@ @@@@@@@@@@@@@@ ",
|
|
" @@@ @@@ @@ @@@ @@@@@ @@@@",
|
|
" @@@ @@ @@@@ @@@ @@@",
|
|
" @@@@@ @@ @@@@ @@@",
|
|
" @@@@@@ @@ @@ @ @@@ @@@@ ",
|
|
" @@@ @@ @@ @ @@@@@@ ",
|
|
" @@@ @@ @@@ @@ @@@@@@@@@@@@@@@ ",
|
|
"@@@ @@@@ @ @@@@ @@@@@ @@@ @ @@@@ @@@ @@@ ",
|
|
"@@@ @@@@@@@ @@@ @@@@@@@@@@@@@@@@@@@ @@ @@@ @@@ ",
|
|
"@@@ @@@@@ @@@ @@@@@ @@@@ @@@@ @@@@@@@@@@ @@@@ @@@ ",
|
|
"@@@@ @@@@@@@@@@@@@@@@ @@@ @@@ @@ @@@@@@@@@@@@ @@@ ",
|
|
" @@@@ @@@@@@@@@@@@@@@@ @@@ @@ @@@@@@@@@@@@ @@@ ",
|
|
" @@@@@@ @@@@@ @@@ @@ @ @@ @@ @@@@ @@@@ ",
|
|
" @@@@@@@@@@@@@ @@@ @@ @@ @@ @@@@@@@@@@@ ",
|
|
" @@@@@@@@@@@@ @@@ @@ @@@ @ @@@@@@@@ ",
|
|
" @@ @@ @@@ @@ @@@ ",
|
|
" @ @@ @@ @@@ ",
|
|
" @@@ @@@ ",
|
|
" @@@ ",
|
|
""
|
|
]
|
|
splash_lines = [
|
|
"-- ESP32 C5 Flasher --",
|
|
"By AWOK",
|
|
"Inspired from LordSkeletonMans ESP32 FZEasyFlasher",
|
|
"Shout out to JCMK for the inspiration on setting up the C5",
|
|
""
|
|
]
|
|
print(Fore.MAGENTA + "\n" + "\n".join(center(line) for line in logo_lines + splash_lines) + Style.RESET_ALL)
|
|
|
|
# Wait for ESP32 device to show up as a new serial port
|
|
existing_ports = set([port.device for port in serial.tools.list_ports.comports()])
|
|
print(Fore.YELLOW + "Waiting for ESP32-C5 device to be connected..." + Style.RESET_ALL)
|
|
while True:
|
|
current_ports = set([port.device for port in serial.tools.list_ports.comports()])
|
|
new_ports = current_ports - existing_ports
|
|
if new_ports:
|
|
serial_port = new_ports.pop()
|
|
break
|
|
time.sleep(0.5)
|
|
print(Fore.GREEN + f"Detected ESP32-C5 on port: {serial_port}" + Style.RESET_ALL)
|
|
|
|
# Find bin files for each firmware component
|
|
bootloader = find_file(['bootloader.bin'], bins_dir)
|
|
partitions = find_file(['partition-table.bin', 'partitions.bin'], bins_dir)
|
|
ota_data = find_file(['ota_data_initial.bin'], bins_dir)
|
|
|
|
# Main firmware: largest bin in the folder that's not bootloader, partition, or OTA
|
|
all_bins = glob.glob(os.path.join(bins_dir, "*.bin"))
|
|
exclude = {bootloader, partitions, ota_data}
|
|
firmware_bins = [f for f in all_bins if f not in exclude and os.path.isfile(f)]
|
|
if not firmware_bins:
|
|
print(Fore.RED + "No application firmware .bin file found in the 'bins' folder!" + Style.RESET_ALL)
|
|
exit(1)
|
|
app_bin = max(firmware_bins, key=lambda f: os.path.getsize(f))
|
|
|
|
# Print summary, ask for confirmation before flashing
|
|
print(Fore.CYAN + f"\nBootloader: {bootloader or 'NOT FOUND'}")
|
|
print(f"Partitions: {partitions or 'NOT FOUND'}")
|
|
print(f"OTA Data: {ota_data or 'NOT FOUND'}")
|
|
print(f"App (main): {app_bin}\n" + Style.RESET_ALL)
|
|
if not (bootloader and partitions):
|
|
print(Fore.RED + "Missing bootloader or partition table. Both are required for a complete flash!" + Style.RESET_ALL)
|
|
exit(1)
|
|
confirm = input(Fore.YELLOW + "Ready to flash these files to ESP32-C5? (y/N): " + Style.RESET_ALL)
|
|
if confirm.strip().lower() != 'y':
|
|
print("Aborting.")
|
|
exit(0)
|
|
|
|
# Flash using esptool, with offsets for C5
|
|
esptool_args = [
|
|
'--chip', 'esp32c5',
|
|
'--port', serial_port,
|
|
'--baud', '921600',
|
|
'--before', 'default_reset',
|
|
'--after', 'hard_reset',
|
|
'write_flash', '-z',
|
|
'0x2000', bootloader,
|
|
'0x8000', partitions,
|
|
]
|
|
if ota_data:
|
|
esptool_args += ['0xd000', ota_data]
|
|
esptool_args += ['0x10000', app_bin]
|
|
|
|
print(Fore.YELLOW + "Flashing ESP32-C5 with bootloader, partition table, and application..." + Style.RESET_ALL)
|
|
try:
|
|
esptool.main(esptool_args)
|
|
print(Fore.GREEN + "Flashing complete!" + Style.RESET_ALL)
|
|
except Exception as e:
|
|
print(Fore.RED + f"Flashing failed: {e}" + Style.RESET_ALL)
|
|
|
|
if __name__ == "__main__":
|
|
main() |