stm8loader pesudo ok

This commit is contained in:
2025-12-20 23:47:23 +08:00
parent e1d432bfab
commit 34293ea313
4 changed files with 45 additions and 31 deletions

Binary file not shown.

View File

@@ -60,8 +60,8 @@ temp_var3 = 79 ; 临时变量
;; Bootloader body (load in ram ?-0x03D0) ;; Bootloader body (load in ram ?-0x03D0)
.area RAM_BOOT .area RAM_BOOT
.db (BOOT2_SP-(_end-_start)+1)>>8 .db (BOOT2_SP-(_end-_start)+3)>>8
.db (BOOT2_SP-(_end-_start)+1)&0xFF .db (BOOT2_SP-(_end-_start)+3)&0xFF
_start: _start:
; 配置UART1: 128000波特率, 8N1, 启用TX/RX ; 配置UART1: 128000波特率, 8N1, 启用TX/RX
@@ -228,6 +228,7 @@ send_ack_state_response:
addw X, #4 addw X, #4
ld A, #1 ld A, #1
ld (X), A ld (X), A
ld tx_data_length, A
; set data ; set data
incw X incw X

View File

@@ -64,16 +64,7 @@ class STM8Bootloader:
if level == "DEBUG" and not self.verbose: if level == "DEBUG" and not self.verbose:
return return
prefix = f"[{level}]" prefix = f"[{level}] {message}"
if level == "DEBUG":
prefix = f"[DEBUG] {message}"
elif level == "ERROR":
prefix = f"[ERROR] {message}"
elif level == "WARNING":
prefix = f"[WARNING] {message}"
else:
prefix = f"[INFO] {message}"
print(prefix) print(prefix)
def open(self, baudrate: int = BOOT2_BAUDRATE): def open(self, baudrate: int = BOOT2_BAUDRATE):
@@ -85,7 +76,7 @@ class STM8Bootloader:
bytesize=serial.EIGHTBITS, bytesize=serial.EIGHTBITS,
parity=serial.PARITY_NONE, parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE, stopbits=serial.STOPBITS_ONE,
timeout=0.2 # 200ms超时 timeout=0 # 设置为0非阻塞模式
) )
self.log(f"串口 {self.port} 已打开,波特率 {baudrate}", "DEBUG") self.log(f"串口 {self.port} 已打开,波特率 {baudrate}", "DEBUG")
@@ -161,20 +152,17 @@ class STM8Bootloader:
self.log("等待boot1握手信号(0x00 0x0D)...", "DEBUG") self.log("等待boot1握手信号(0x00 0x0D)...", "DEBUG")
# 设置非阻塞读取 # 清除输入缓冲区
self.serial.timeout = 0 # 非阻塞 self.serial.reset_input_buffer()
try: try:
# 清除输入缓冲区
self.serial.reset_input_buffer()
# 持续读取最多等待200ms # 持续读取最多等待200ms
start_time = time.time() start_time = time.time()
buffer = bytearray() buffer = bytearray()
while time.time() - start_time < 0.2: # 200ms超时 while time.time() - start_time < 0.2: # 200ms超时
# 读取所有可用数据 # 读取所有可用数据
while self.serial.in_waiting > 0: if self.serial.in_waiting > 0:
data = self.serial.read(self.serial.in_waiting) data = self.serial.read(self.serial.in_waiting)
buffer.extend(data) buffer.extend(data)
@@ -189,6 +177,7 @@ class STM8Bootloader:
time.sleep(0.001) # 1ms time.sleep(0.001) # 1ms
# 超时,未收到信号 # 超时,未收到信号
self.log("200ms内未收到boot1信号", "DEBUG")
return False return False
except Exception as e: except Exception as e:
@@ -202,17 +191,16 @@ class STM8Bootloader:
Returns: Returns:
True: 成功, False: 用户中断或失败 True: 成功, False: 用户中断或失败
""" """
self.log("等待boot1握手信号...", "INFO") self.log("等待boot1握手信号请手动按下MCU复位键", "INFO")
self.log("请手动按下MCU复位键", "INFO")
self.log("按 Ctrl+C 退出程序", "INFO") self.log("按 Ctrl+C 退出程序", "INFO")
# 设置非阻塞读取 # 清除输入缓冲区
self.serial.timeout = 0 self.serial.reset_input_buffer()
try: try:
while True: while True:
# 检查是否有数据 # 检查是否有数据
while self.serial.in_waiting > 0: if self.serial.in_waiting > 0:
data = self.serial.read(self.serial.in_waiting) data = self.serial.read(self.serial.in_waiting)
# 简单检查如果数据包含0x00 0x0D # 简单检查如果数据包含0x00 0x0D
@@ -347,8 +335,31 @@ class STM8Bootloader:
return cmd, addr, data return cmd, addr, data
def read_with_timeout(self, size: int, timeout: float) -> bytes:
"""
读取指定数量的字节,带超时
Args:
size: 要读取的字节数
timeout: 超时时间(秒)
Returns:
读取到的数据
"""
data = bytearray()
start_time = time.time()
while len(data) < size and time.time() - start_time < timeout:
if self.serial.in_waiting > 0:
chunk = self.serial.read(min(self.serial.in_waiting, size - len(data)))
data.extend(chunk)
else:
time.sleep(0.001) # 短暂休眠避免CPU占用过高
return bytes(data)
def send_command(self, cmd: int, addr: int, data: bytes = b'', def send_command(self, cmd: int, addr: int, data: bytes = b'',
wait_response: bool = True, timeout: float = 0.2) -> Optional[Tuple[int, int, bytes]]: wait_response: bool = True, timeout: float = 0.5) -> Optional[Tuple[int, int, bytes]]:
""" """
发送命令并接收响应 发送命令并接收响应
@@ -377,8 +388,7 @@ class STM8Bootloader:
return None return None
# 等待响应 # 等待响应
self.serial.timeout = timeout response = self.read_with_timeout(FRAME_SIZE, timeout)
response = self.serial.read(FRAME_SIZE)
if not response: if not response:
raise STM8BootloaderError("未收到响应") raise STM8BootloaderError("未收到响应")
@@ -394,7 +404,8 @@ class STM8Bootloader:
""" """
try: try:
self.log("检查是否在boot2中...", "DEBUG") self.log("检查是否在boot2中...", "DEBUG")
response = self.send_command(CMD_READ, HANDSHAKE_ADDR, b'', timeout=0.5) # 发送读取命令数据字段为要读取的长度8字节
response = self.send_command(CMD_READ, HANDSHAKE_ADDR, b'\x08', timeout=0.5)
if response: if response:
cmd, addr, data = response cmd, addr, data = response
@@ -601,8 +612,8 @@ class STM8Bootloader:
raise STM8BootloaderError("信息数据长度不足") raise STM8BootloaderError("信息数据长度不足")
# 解析握手数据 # 解析握手数据
boot0_addr = (data[1] << 8) | data[0] # 注意字节序 boot0_addr = (data[2] << 8) | data[3] # 注意字节序
main_addr = (data[7] << 8) | data[6] # 注意字节序 main_addr = (data[6] << 8) | data[7] # 注意字节序
info = { info = {
'boot0_address': boot0_addr, 'boot0_address': boot0_addr,

View File

@@ -14,6 +14,7 @@ void main(void) {
UART1_BRR2 = 0x00; UART1_BRR2 = 0x00;
UART1_CR2 = 0x0C; UART1_CR2 = 0x0C;
#if 0
while(1) { while(1) {
volatile uint8_t *ptr = (volatile uint8_t *)0x0230; volatile uint8_t *ptr = (volatile uint8_t *)0x0230;
delay_ms(2000); delay_ms(2000);
@@ -26,10 +27,11 @@ void main(void) {
PB_ODR ^= (1 << LED_PIN); PB_ODR ^= (1 << LED_PIN);
} }
} }
#else
while(1) { while(1) {
PB_ODR ^= (1 << LED_PIN); PB_ODR ^= (1 << LED_PIN);
UART1_DR = PB_ODR; UART1_DR = PB_ODR;
delay_ms(500); delay_ms(500);
} }
#endif
} }