fix stm8loader.py

This commit is contained in:
2025-12-21 02:03:20 +08:00
parent 3a168ac41b
commit 537f8505bb
2 changed files with 247 additions and 223 deletions

BIN
scripts/boot2.bin Normal file

Binary file not shown.

View File

@@ -35,7 +35,7 @@ class STM8BootloaderError(Exception):
pass
class STM8Bootloader:
def __init__(self, port: str, verbose: bool = False, reset_pin: str = 'rts+dtr'):
def __init__(self, port: str, verbose: bool = False, reset_pin: str = 'rts+dtr', boot2_file: str = None):
"""
Initialize STM8 Bootloader
@@ -43,6 +43,7 @@ class STM8Bootloader:
port: Serial port name
verbose: Whether to display detailed debug information
reset_pin: Reset pin type ('rts+dtr', 'rts', 'dtr' or 'none')
boot2_file: boot2 binary file path
"""
self.port = port
self.verbose = verbose
@@ -53,6 +54,9 @@ class STM8Bootloader:
self.in_boot2 = False
self.script_dir = os.path.dirname(os.path.abspath(__file__))
# Store boot2 file path
self.default_boot2_file = boot2_file
def log(self, message: str, level: str = "INFO"):
"""
Print log information
@@ -229,9 +233,15 @@ class STM8Bootloader:
True: Send successful, False: Send failed
"""
try:
# If file path is not absolute, make it relative to script directory
# If file path is not absolute, make it relative to current working directory
if not os.path.isabs(bin_file):
bin_file = os.path.join(self.script_dir, bin_file)
# Try to find file in current directory first
current_dir_file = os.path.join(os.getcwd(), bin_file)
if os.path.exists(current_dir_file):
bin_file = current_dir_file
else:
# Fallback to script directory
bin_file = os.path.join(self.script_dir, bin_file)
with open(bin_file, 'rb') as f:
data = f.read()
@@ -240,7 +250,7 @@ class STM8Bootloader:
self.log(f"File {bin_file} is empty", "ERROR")
return False
self.log(f"Read {len(data)} bytes of boot2 program", "DEBUG")
self.log(f"Read {len(data)} bytes of boot2 program from {bin_file}", "DEBUG")
# Byte reversal
reversed_data = bytes(reversed(data))
@@ -420,16 +430,25 @@ class STM8Bootloader:
self.in_boot2 = False
return False
def upload_boot2(self, boot2_file: str = "boot2.bin") -> bool:
def upload_boot2(self, boot2_file: str = None) -> bool:
"""
Upload boot2 program to MCU
Args:
boot2_file: boot2 binary file path
boot2_file: boot2 binary file path (if None, use default)
Returns:
True: Upload successful, False: Upload failed
"""
# Use provided file or default
if boot2_file is None:
if self.default_boot2_file:
boot2_file = self.default_boot2_file
else:
# Fallback to script directory
boot2_file = os.path.join(self.script_dir, "boot2.bin")
self.log("Starting boot2 program upload...", "INFO")
# 1. Switch to 9600 bps
self.close()
@@ -717,9 +736,10 @@ class STM8Bootloader:
self.list_directory(path)
elif cmd == 'reload':
# Reset and upload boot2
# Reset and upload boot2 with optional file path
boot2_file = args[1] if len(args) > 1 else None
self.log("Executing reset and to upload boot2...", "INFO")
if not self.upload_boot2():
if not self.upload_boot2(boot2_file):
self.log("Reset upload failed", "ERROR")
else:
self.log("Reset upload successful", "INFO")
@@ -838,7 +858,7 @@ Command List:
ls [path] - List directory contents, files show size, directories only names
reload - Reset MCU and upload boot2 program
reload [file] - Reset MCU and upload boot2 program
help - Display this help information
@@ -865,23 +885,23 @@ def main():
formatter_class=argparse.RawDescriptionHelpFormatter,
epilog="""
Examples:
%(prog)s COM3 # Enter interactive mode
%(prog)s COM3 -r 0x8000 256 # Read memory
%(prog)s COM3 -w 0x8000 firmware.bin # Write file
%(prog)s COM3 -w 0x8000 "AABBCC" # Write hex string
%(prog)s COM3 -g 0x8000 # Jump execution
%(prog)s --list-ports # List available serial ports
%(prog)s /dev/ttyUSB0 # Enter interactive mode
%(prog)s /dev/ttyUSB0 -r 0x8000 256 # Read memory
%(prog)s /dev/ttyUSB0 -w 0x8000 firmware.bin # Write file
%(prog)s /dev/ttyUSB0 -w 0x8000 "AABBCC" # Write hex string
%(prog)s /dev/ttyUSB0 -g 0x8000 # Jump execution
%(prog)s --list-ports # List available serial ports
"""
)
# Serial port related parameters
parser.add_argument('port', nargs='?', help='Serial port name (e.g., COM3, /dev/ttyUSB0)')
parser.add_argument('port', nargs='?', help='Serial port name (e.g., /dev/ttyUSB0, COM3)')
parser.add_argument('-b', '--baudrate', type=int, default=BOOT2_BAUDRATE,
help=f'Serial port baud rate (default: {BOOT2_BAUDRATE})')
# boot2 upload parameters
parser.add_argument('--boot2', default='boot2.bin',
help='boot2 program file path (default: boot2.bin in script directory)')
help='boot2 program file path (default: boot2.bin in current directory or script directory)')
parser.add_argument('--skip-boot2', action='store_true',
help='Skip automatic boot2 upload, directly enter interactive mode')
@@ -922,8 +942,12 @@ Examples:
return 1
try:
# Handle boot2 file path
boot2_file = args.boot2
# Create bootloader instance
loader = STM8Bootloader(args.port, verbose=args.verbose, reset_pin=args.reset_pin)
loader = STM8Bootloader(args.port, verbose=args.verbose,
reset_pin=args.reset_pin, boot2_file=boot2_file)
# Open serial port
loader.open(baudrate=args.baudrate)
@@ -934,7 +958,7 @@ Examples:
# If not in boot2 and not skipping boot2 upload, must upload boot2
if not in_boot2 and not args.skip_boot2:
print("[INFO] Not in boot2 mode, starting boot2 program upload...")
if not loader.upload_boot2(args.boot2):
if not loader.upload_boot2():
print("[ERROR] boot2 upload failed")
loader.close()
return 1