feat: complete assembly mesh relay control path

- synchronize STM8 application and external flash layout updates\n- add assembly bootloader and assembly application test projects\n- add UART1 interrupt receive ring buffer\n- parse JDY-28M Mesh outer frames and source addresses\n- add CRC-16/MODBUS validation\n- implement relay control command 0x01 and response 0x81\n- support unicast and broadcast relay control frames\n- update host protocol, OTA documents, and serial tools
This commit is contained in:
十七
2026-11-05 16:12:51 +08:00
parent df1aad3d16
commit ebef6a8694
40 changed files with 2133 additions and 307 deletions
+66
View File
@@ -0,0 +1,66 @@
#!/usr/bin/env python3
"""合并Bootloader和主程序的Intel HEX文件。"""
from __future__ import annotations
import argparse
from pathlib import Path
EOF_RECORD = ":00000001FF"
def read_records(path: Path) -> list[str]:
"""读取HEX记录,并去掉输入文件末尾的EOF记录。"""
records = []
for raw_line in path.read_text(encoding="ascii").splitlines():
line = raw_line.strip().upper()
if not line:
continue
if not line.startswith(":"):
raise ValueError(f"{path}包含非法HEX记录:{line}")
if line != EOF_RECORD:
records.append(line)
return records
def record_range(record: str) -> tuple[int, int] | None:
"""返回数据记录地址范围,用于检查两个镜像是否重叠。"""
count = int(record[1:3], 16)
record_type = int(record[7:9], 16)
if record_type != 0x00 or count == 0:
return None
address = int(record[3:7], 16)
return address, address + count
def merge(output: Path, inputs: list[Path]) -> None:
"""合并绝对地址HEX文件,并检查数据区间重叠。"""
occupied: list[tuple[int, int, Path]] = []
records: list[str] = []
for path in inputs:
for record in read_records(path):
current = record_range(record)
if current is not None:
start, end = current
for old_start, old_end, old_path in occupied:
if start < old_end and old_start < end:
raise ValueError(
f"HEX地址重叠:{path} 0x{start:04X}~0x{end - 1:04X},"
f"与 {old_path} 冲突"
)
occupied.append((start, end, path))
records.append(record)
output.write_text("\n".join(records + [EOF_RECORD]) + "\n", encoding="ascii")
def main() -> None:
"""解析参数并执行HEX合并。"""
parser = argparse.ArgumentParser(description="合并STM8 Bootloader和主程序HEX")
parser.add_argument("output", type=Path, help="输出HEX文件")
parser.add_argument("inputs", nargs="+", type=Path, help="输入HEX文件")
args = parser.parse_args()
merge(args.output, args.inputs)
if __name__ == "__main__":
main()