Files
openpilot/flash_bootstub.sh

105 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 0.1
echo 0 > /sys/class/gpio/gpio134/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(0.1); w(134, 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 "=============================================================="