mirror of
https://jihulab.com/mr-one/openpilot.git
synced 2026-10-27 13:03:42 +08:00
102 lines
3.5 KiB
Bash
Executable File
102 lines
3.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# ============================================================
|
|
# 手动把 bootstub 烧进 SPI panda (STM32H725) 的 flash
|
|
# 适用: 新 panda / panda 固件损坏 / 需要重刷 bootstub 时
|
|
# 用法: ssh comma@<设备IP> 'bash /home/comma/flash_bootstub.sh'
|
|
# 注意: 烧完必须给 panda 完整断电再上电!
|
|
# ============================================================
|
|
export PATH=/usr/local/venv/bin:$PATH
|
|
export PYTHONPATH=/data/openpilot
|
|
cd /data/openpilot || { echo "ERROR: /data/openpilot not found"; exit 1; }
|
|
|
|
if [ ! -f panda/board/obj/bootstub.panda_h7.bin ]; then
|
|
echo "ERROR: bootstub.panda_h7.bin not found (need to build first: scons)"
|
|
exit 1
|
|
fi
|
|
echo "bootstub file: $(ls -la panda/board/obj/bootstub.panda_h7.bin | awk '{print $5}') bytes"
|
|
echo "firmware version: $(cat panda/board/obj/version 2>/dev/null)"
|
|
|
|
# 1) 进入 ROM bootloader: RST复位 + BOOT0=1 (保持高)
|
|
echo ">> entering ROM bootloader (BOOT0=1)..."
|
|
echo 1 > /sys/class/gpio/gpio124/value
|
|
echo 1 > /sys/class/gpio/gpio134/value
|
|
sleep 0.2
|
|
echo 0 > /sys/class/gpio/gpio124/value
|
|
sleep 1
|
|
|
|
# 2) 单 handle 分块刷写 bootstub (带重试 + 读回校验)
|
|
python3 << 'PYEOF'
|
|
import time, sys
|
|
from panda.python.spi import STBootloaderSPIHandle
|
|
from panda.python.constants import FW_PATH, McuType
|
|
import os
|
|
|
|
BS = 256
|
|
fn = os.path.join(FW_PATH, McuType.H7.config.bootstub_fn)
|
|
code = open(fn, "rb").read()
|
|
nblocks = (len(code) + BS - 1) // BS
|
|
print(f"bootstub {len(code)} bytes, {nblocks} blocks")
|
|
|
|
def w(pin, val):
|
|
with open(f"/sys/class/gpio/gpio{pin}/value", "w") as f:
|
|
f.write(str(val))
|
|
|
|
for attempt in range(30):
|
|
# reset with BOOT0 held high (each retry)
|
|
w(124, 1); w(134, 1); time.sleep(0.2); w(124, 0); time.sleep(1)
|
|
try:
|
|
h = STBootloaderSPIHandle()
|
|
except Exception:
|
|
print(f" attempt {attempt}: connect fail")
|
|
continue
|
|
print(f" attempt {attempt}: connected, chipid={hex(h.get_chip_id())}")
|
|
for round_ in range(8):
|
|
try:
|
|
h.erase_sector(0); h.erase_sector(1)
|
|
except Exception as e:
|
|
print(f" erase err {e}")
|
|
break
|
|
ok = True
|
|
for i in range(nblocks):
|
|
block = code[i*BS:(i+1)*BS].ljust(BS, b"\xFF")
|
|
addr = 0x08000000 + i*BS
|
|
success = False
|
|
for r in range(6):
|
|
try:
|
|
h.program(addr, block)
|
|
if h.read(addr, BS) == block:
|
|
success = True
|
|
break
|
|
except Exception:
|
|
pass
|
|
if not success:
|
|
ok = False
|
|
print(f" round {round_}: block {i} failed")
|
|
break
|
|
if ok:
|
|
v = h.read(0x08000000, 32)
|
|
print(f" *** BOOTSTUB FLASH SUCCESS *** head={v.hex()}")
|
|
sys.exit(0)
|
|
try:
|
|
h.close()
|
|
except Exception:
|
|
pass
|
|
|
|
print("FLASH FAILED after all retries")
|
|
sys.exit(1)
|
|
PYEOF
|
|
|
|
# 3) 恢复正常模式 (BOOT0=0)
|
|
echo 0 > /sys/class/gpio/gpio134/value
|
|
echo 1 > /sys/class/gpio/gpio124/value
|
|
sleep 0.3
|
|
echo 0 > /sys/class/gpio/gpio124/value
|
|
|
|
echo ""
|
|
echo "=============================================================="
|
|
echo " bootstub 已烧入 flash!"
|
|
echo " 现在必须给 panda 完整断电再上电:"
|
|
echo " 拔掉 panda 电源 / 关掉供电开关, 等 2~3 秒, 再上电"
|
|
echo " 上电后 panda 绿灯会闪烁(soft flasher), pandad 会自动刷 app"
|
|
echo "=============================================================="
|