stm8loader add exec
This commit is contained in:
2
Makefile
2
Makefile
@@ -42,7 +42,7 @@ CFLAGS += --stack-auto --noinduction --use-non-free
|
||||
LDFLAGS = -m$(ARCH) -l$(ARCH) --out-fmt-ihx
|
||||
|
||||
OPTION_BOOT := 0x480D
|
||||
RAM_BOOT := 0x0232
|
||||
RAM_BOOT := 0x023E
|
||||
OPTFLAGS = -Wl-bOPTION=0x4800 -Wl-bOPTION_BOOT=$(OPTION_BOOT)
|
||||
B2FLAGS = -Wl-bRAM_BOOT=$(RAM_BOOT)
|
||||
|
||||
|
||||
Binary file not shown.
@@ -96,15 +96,15 @@ _main_loop:
|
||||
|
||||
_invalid_cmd_error:
|
||||
; 未知命令,发送错误响应
|
||||
mov tx_state, #ERR_INVCMD
|
||||
ld A, #ERR_INVCMD
|
||||
_ack_then_back:
|
||||
call send_ack_state_response
|
||||
jra _main_loop
|
||||
|
||||
_checksum_error:
|
||||
; 校验和错误响应
|
||||
mov tx_state, #ERR_CHECKSUM
|
||||
call send_ack_state_response
|
||||
jra _main_loop
|
||||
ld A, #ERR_CHECKSUM
|
||||
jra _ack_then_back
|
||||
|
||||
_cmd_read:
|
||||
; 读取内存命令
|
||||
@@ -127,7 +127,8 @@ _cmd_exec:
|
||||
ld A, #0x81 ; ret code
|
||||
ld (X), A ; X point to checksum already
|
||||
call rx_buffer
|
||||
jra _main_loop
|
||||
ld A, #SUCCESS_CODE
|
||||
jra _ack_then_back
|
||||
|
||||
receive_frame:
|
||||
; 初始化接收状态
|
||||
@@ -204,12 +205,18 @@ _verify_loop:
|
||||
ret
|
||||
|
||||
send_response_pkg:
|
||||
clr calc_checksum
|
||||
; set header
|
||||
ldw X, #tx_buffer
|
||||
ld A, #ACK_HEADER
|
||||
ld (X), A
|
||||
|
||||
; tx_data_length += 5
|
||||
ld A, tx_data_length
|
||||
add A, #5
|
||||
ld temp_var1, A
|
||||
|
||||
; send data
|
||||
clr calc_checksum
|
||||
_send_loop:
|
||||
ld A, (X)
|
||||
ld UART1_DR, A
|
||||
@@ -222,49 +229,39 @@ _wait_tx1:
|
||||
incw X
|
||||
dec temp_var1
|
||||
jrne _send_loop
|
||||
|
||||
; send checksum
|
||||
ld A, calc_checksum
|
||||
ld UART1_DR, A
|
||||
_wait_tx2:
|
||||
btjf UART1_SR, #7, _wait_tx2
|
||||
|
||||
; finish
|
||||
ret
|
||||
|
||||
; 发送应答状态帧
|
||||
send_ack_state_response:
|
||||
; set header
|
||||
ldw X, #tx_buffer
|
||||
ld A, #ACK_HEADER
|
||||
; set data
|
||||
ldw X, #tx_buffer+5
|
||||
ld (X), A
|
||||
|
||||
; set length
|
||||
addw X, #4
|
||||
decw X
|
||||
ld A, #1
|
||||
ld (X), A
|
||||
ld tx_data_length, A
|
||||
|
||||
; set data
|
||||
incw X
|
||||
ld A, tx_state
|
||||
ld (X), A
|
||||
|
||||
callr send_response_pkg
|
||||
ret
|
||||
|
||||
; 发送应答数据帧
|
||||
send_ack_data_response:
|
||||
; set header
|
||||
ldw X, #tx_buffer
|
||||
ld A, #ACK_HEADER
|
||||
ld (X), A
|
||||
|
||||
; set length
|
||||
addw X, #4
|
||||
ldw X, #tx_buffer+4
|
||||
ld A, tx_data_length
|
||||
ld (X), A
|
||||
|
||||
; already set data
|
||||
|
||||
callr send_response_pkg
|
||||
ret
|
||||
|
||||
@@ -333,6 +330,7 @@ _mem_write:
|
||||
incw Y
|
||||
dec temp_var1
|
||||
jrne _mem_write
|
||||
ld A, #SUCCESS_CODE
|
||||
callr send_ack_state_response
|
||||
ret
|
||||
|
||||
@@ -378,6 +376,7 @@ _write_end:
|
||||
mov FLASH_NCR2, #0xFF
|
||||
; lock FLASH/DATA
|
||||
callr lock_flash
|
||||
ld A, tx_state
|
||||
call send_ack_state_response
|
||||
ret
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@ from typing import Optional, List, Tuple, Union, BinaryIO
|
||||
CMD_READ = 0xF1 # Read memory command
|
||||
CMD_WRITE = 0xF2 # Write memory command
|
||||
CMD_GO = 0xF3 # Jump execution command
|
||||
CMD_EXEC = 0xF4 # Execute machine code command
|
||||
|
||||
CMD_HEADER = 0x5A # Frame header sent to MCU
|
||||
ACK_HEADER = 0xA5 # MCU response frame header
|
||||
@@ -259,6 +260,17 @@ class STM8Bootloader:
|
||||
self.serial.write(reversed_data)
|
||||
self.serial.flush()
|
||||
|
||||
# Log sent data in hex format
|
||||
if self.verbose:
|
||||
# Show first and last 64 bytes to avoid too much output
|
||||
if len(reversed_data) <= 128:
|
||||
self.log(f"Sent data (hex): {reversed_data.hex()}", "DEBUG")
|
||||
else:
|
||||
first_part = reversed_data[:64].hex()
|
||||
last_part = reversed_data[-64:].hex()
|
||||
self.log(f"Sent data (first 64 bytes): {first_part}", "DEBUG")
|
||||
self.log(f"Sent data (last 64 bytes): {last_part}", "DEBUG")
|
||||
|
||||
self.log(f"Sent {len(data)} bytes (reversed)", "DEBUG")
|
||||
return True
|
||||
|
||||
@@ -389,6 +401,11 @@ class STM8Bootloader:
|
||||
|
||||
# Create and send command frame
|
||||
frame = self.create_command_frame(cmd, addr, data)
|
||||
|
||||
# Log sent frame in hex format
|
||||
if self.verbose:
|
||||
self.log(f"Sending command frame (hex): {frame.hex()}", "DEBUG")
|
||||
|
||||
self.serial.write(frame)
|
||||
self.serial.flush()
|
||||
|
||||
@@ -401,6 +418,10 @@ class STM8Bootloader:
|
||||
if not response:
|
||||
raise STM8BootloaderError("No response received")
|
||||
|
||||
# Log received response in hex format
|
||||
if self.verbose:
|
||||
self.log(f"Received response (hex): {response.hex()}", "DEBUG")
|
||||
|
||||
return self.parse_response_frame(response)
|
||||
|
||||
def check_boot2(self) -> bool:
|
||||
@@ -590,6 +611,31 @@ class STM8Bootloader:
|
||||
|
||||
return True
|
||||
|
||||
def exec_machine_code(self, addr: int, machine_code: bytes) -> bool:
|
||||
"""
|
||||
Execute machine code at specified address
|
||||
|
||||
Args:
|
||||
addr: Execution address
|
||||
machine_code: Machine code to execute
|
||||
|
||||
Returns:
|
||||
True: Command sent successfully
|
||||
"""
|
||||
if not self.in_boot2:
|
||||
raise STM8BootloaderError("Not in boot2 mode")
|
||||
|
||||
if len(machine_code) > MAX_DATA_SIZE:
|
||||
raise STM8BootloaderError(f"Machine code length exceeds {MAX_DATA_SIZE} byte limit")
|
||||
|
||||
try:
|
||||
# exec command doesn't care wait for response
|
||||
self.send_command(CMD_EXEC, addr, machine_code, wait_response=True)
|
||||
self.log(f"Sent execute machine code at 0x{addr:04X} command", "DEBUG")
|
||||
return True
|
||||
except Exception as e:
|
||||
raise STM8BootloaderError(f"Failed to send execute command: {e}")
|
||||
|
||||
def go_execute(self, addr: int) -> bool:
|
||||
"""
|
||||
Jump to specified address for execution
|
||||
@@ -711,7 +757,7 @@ class STM8Bootloader:
|
||||
def interactive_mode(self):
|
||||
"""Interactive mode"""
|
||||
self.log("\n=== STM8 Bootloader Interactive Mode ===", "INFO")
|
||||
self.log("Available commands: read, write, go, info, ls, reload, help, exit", "INFO")
|
||||
self.log("Available commands: read, write, exec, go, info, ls, reload, help, exit", "INFO")
|
||||
self.log("Type 'help' for detailed usage\n", "INFO")
|
||||
|
||||
while True:
|
||||
@@ -808,6 +854,32 @@ class STM8Bootloader:
|
||||
except Exception as e:
|
||||
self.log(f"Error: {e}", "ERROR")
|
||||
|
||||
elif cmd == 'exec':
|
||||
if len(args) < 2:
|
||||
self.log("Usage: exec <hex_string>", "ERROR")
|
||||
self.log("Example: exec 4F9D (CLR A; NOP)", "INFO")
|
||||
continue
|
||||
|
||||
try:
|
||||
addr = 0 # run in #boot2.rx_buffer
|
||||
hex_str = args[1]
|
||||
|
||||
# Parse hex string
|
||||
hex_str = hex_str.replace('0x', '').replace(' ', '')
|
||||
if len(hex_str) % 2 != 0:
|
||||
raise ValueError("Hex string length must be even")
|
||||
machine_code = bytes.fromhex(hex_str)
|
||||
|
||||
if len(machine_code) > MAX_DATA_SIZE:
|
||||
self.log(f"Error: Machine code too long (max {MAX_DATA_SIZE} bytes)", "ERROR")
|
||||
continue
|
||||
|
||||
if self.exec_machine_code(addr, machine_code):
|
||||
self.log(f"Execute command sent: {len(machine_code)} bytes at 0x{addr:04X}", "INFO")
|
||||
|
||||
except Exception as e:
|
||||
self.log(f"Error: {e}", "ERROR")
|
||||
|
||||
elif cmd == 'go':
|
||||
if len(args) < 2:
|
||||
self.log("Usage: go <addr>", "ERROR")
|
||||
@@ -851,6 +923,9 @@ Command List:
|
||||
Example: write 0x8000 firmware.bin
|
||||
Example: write 0x8000 AABBCCDDEEFF
|
||||
|
||||
exec <hex_str> - Execute machine code at specified address
|
||||
Example: exec 4F9D (CLR A; NOP;)
|
||||
|
||||
go <addr> - Jump to specified address for execution
|
||||
Example: go 0x8000
|
||||
|
||||
@@ -925,7 +1000,7 @@ Examples:
|
||||
parser.add_argument('-i', '--interactive', action='store_true',
|
||||
help='Enter interactive mode after executing command')
|
||||
parser.add_argument('-v', '--verbose', action='store_true',
|
||||
help='Display detailed debug information')
|
||||
help='Display detailed debug information including serial data hex dumps')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user