mirror of
https://github.com/firestar5683/StarPilot.git
synced 2026-08-24 01:33:46 +08:00
bb09fd0d4e
* boardd: reset safety mode on exit old-commit-hash: dd18ccbf0a9ab72ace0a7533632d5939c0719953 * comment old-commit-hash: 01b598e8dde93548f7783be19b1cb37d22fadc23 * log it old-commit-hash: 181c4d412e9e3a9c576934e16fc26a9b6e07a117 * logmessaged might not be alive old-commit-hash: 7483ba0eac42875a822df97596d23ff277bf3865 * reproduction, manager gets SIGTERM from python_process old-commit-hash: b90402bd776c3933bfe3dd60998f9913b4bd0068 * even smaller repro old-commit-hash: 03dd430b7131da2b48243714df0513c6a1e594f0 * should work old-commit-hash: 388c4273385ee4c67b1a229ccb9abac6dd94dd0f * let's not change that rn old-commit-hash: d057299058503e8fb792b5a765d0da4af6bef943 * something like this old-commit-hash: 123d6ed845d662aec2bd95d1ccf9c2782308d693 * pandad.cc should receive same SIGTERM and exit old-commit-hash: afc5ef6b916c54ac2ec471d144f601ead71250cb * stash old-commit-hash: e02e0dc488de51c5d40d227c4c2202ba40436d8d * remove debugging old-commit-hash: ac170d0ca32a4285be22e28ec7730fcba3d0697d * remove debugging old-commit-hash: 50949600aeed231347cc4c600a8a7d24accde674 * match behavior old-commit-hash: 5f24167c58caf98b641af2f63f839015e404c349 * convention old-commit-hash: 1664113a232c4b1a3aa67073e9e8cebef414518f * systemd option old-commit-hash: 95183ff77842fcb9592715db07396be28d778197 * manager option old-commit-hash: 2071893299cb32c3a7cd8a444d8d386c5fa96511 * just curious if this works, change to ELM327 on exit old-commit-hash: 9674ed525134aa03f995942b18163cb047a59c5b * Revert "just curious if this works, change to ELM327 on exit" This reverts commit d4ae294d419dc3d787d11dee4474799f3fb2acef. old-commit-hash: 6d24edd1635ddd0b8ed68a4a4fc8aaaa88984e45 * check onroad same update * useless * comment * fix * debug * Revert "debug" This reverts commit 2bb138610ea7b26d8610d36ef3f0bbb2d6ada388. * Update common/util.h * double wait does not work, blocking in signal handler not good, exit on do_exit, change to SIGINT, use existing stop to support ctrl+c nope * organize? * no sys * None --------- Co-authored-by: Shane Smiskol <shane@smiskol.com>
180 lines
6.0 KiB
Python
Executable File
180 lines
6.0 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# simple pandad wrapper that updates the panda first
|
|
import os
|
|
import usb1
|
|
import time
|
|
import signal
|
|
import subprocess
|
|
|
|
from panda import Panda, PandaDFU, PandaProtocolMismatch, FW_PATH
|
|
from openpilot.common.basedir import BASEDIR
|
|
from openpilot.common.params import Params
|
|
from openpilot.system.hardware import HARDWARE
|
|
from openpilot.common.swaglog import cloudlog
|
|
|
|
|
|
def get_expected_signature(panda: Panda) -> bytes:
|
|
try:
|
|
fn = os.path.join(FW_PATH, panda.get_mcu_type().config.app_fn)
|
|
return Panda.get_signature_from_firmware(fn)
|
|
except Exception:
|
|
cloudlog.exception("Error computing expected signature")
|
|
return b""
|
|
|
|
def flash_panda(panda_serial: str) -> Panda:
|
|
try:
|
|
panda = Panda(panda_serial)
|
|
except PandaProtocolMismatch:
|
|
cloudlog.warning("detected protocol mismatch, reflashing panda")
|
|
HARDWARE.recover_internal_panda()
|
|
raise
|
|
|
|
fw_signature = get_expected_signature(panda)
|
|
internal_panda = panda.is_internal()
|
|
|
|
panda_version = "bootstub" if panda.bootstub else panda.get_version()
|
|
panda_signature = b"" if panda.bootstub else panda.get_signature()
|
|
cloudlog.warning(f"Panda {panda_serial} connected, version: {panda_version}, signature {panda_signature.hex()[:16]}, expected {fw_signature.hex()[:16]}")
|
|
|
|
if panda.bootstub or panda_signature != fw_signature:
|
|
cloudlog.info("Panda firmware out of date, update required")
|
|
panda.flash()
|
|
cloudlog.info("Done flashing")
|
|
|
|
if panda.bootstub:
|
|
bootstub_version = panda.get_version()
|
|
cloudlog.info(f"Flashed firmware not booting, flashing development bootloader. {bootstub_version=}, {internal_panda=}")
|
|
if internal_panda:
|
|
HARDWARE.recover_internal_panda()
|
|
panda.recover(reset=(not internal_panda))
|
|
cloudlog.info("Done flashing bootstub")
|
|
|
|
if panda.bootstub:
|
|
cloudlog.info("Panda still not booting, exiting")
|
|
raise AssertionError
|
|
|
|
panda_signature = panda.get_signature()
|
|
if panda_signature != fw_signature:
|
|
cloudlog.info("Version mismatch after flashing, exiting")
|
|
raise AssertionError
|
|
|
|
return panda
|
|
|
|
|
|
def main() -> None:
|
|
# signal pandad to close the relay and exit
|
|
def signal_handler(signum, frame):
|
|
cloudlog.info(f"Caught signal {signum}, exiting")
|
|
nonlocal do_exit
|
|
do_exit = True
|
|
if process is not None:
|
|
process.send_signal(signal.SIGINT)
|
|
|
|
process = None
|
|
do_exit = False
|
|
signal.signal(signal.SIGINT, signal_handler)
|
|
|
|
count = 0
|
|
first_run = True
|
|
params = Params()
|
|
no_internal_panda_count = 0
|
|
|
|
while not do_exit:
|
|
try:
|
|
count += 1
|
|
cloudlog.event("pandad.flash_and_connect", count=count)
|
|
params.remove("PandaSignatures")
|
|
|
|
# TODO: remove this in the next AGNOS
|
|
# wait until USB is up before counting
|
|
if time.monotonic() < 25.:
|
|
no_internal_panda_count = 0
|
|
|
|
# Handle missing internal panda
|
|
if no_internal_panda_count > 0:
|
|
if no_internal_panda_count == 3:
|
|
cloudlog.info("No pandas found, putting internal panda into DFU")
|
|
HARDWARE.recover_internal_panda()
|
|
else:
|
|
cloudlog.info("No pandas found, resetting internal panda")
|
|
HARDWARE.reset_internal_panda()
|
|
time.sleep(3) # wait to come back up
|
|
|
|
# Flash all Pandas in DFU mode
|
|
dfu_serials = PandaDFU.list()
|
|
if len(dfu_serials) > 0:
|
|
for serial in dfu_serials:
|
|
cloudlog.info(f"Panda in DFU mode found, flashing recovery {serial}")
|
|
PandaDFU(serial).recover()
|
|
time.sleep(1)
|
|
|
|
panda_serials = Panda.list()
|
|
if len(panda_serials) == 0:
|
|
no_internal_panda_count += 1
|
|
continue
|
|
|
|
cloudlog.info(f"{len(panda_serials)} panda(s) found, connecting - {panda_serials}")
|
|
|
|
# Flash pandas
|
|
pandas: list[Panda] = []
|
|
for serial in panda_serials:
|
|
pandas.append(flash_panda(serial))
|
|
|
|
# Ensure internal panda is present if expected
|
|
internal_pandas = [panda for panda in pandas if panda.is_internal()]
|
|
if HARDWARE.has_internal_panda() and len(internal_pandas) == 0:
|
|
cloudlog.error("Internal panda is missing, trying again")
|
|
no_internal_panda_count += 1
|
|
continue
|
|
no_internal_panda_count = 0
|
|
|
|
# sort pandas to have deterministic order
|
|
# * the internal one is always first
|
|
# * then sort by hardware type
|
|
# * as a last resort, sort by serial number
|
|
pandas.sort(key=lambda x: (not x.is_internal(), x.get_type(), x.get_usb_serial()))
|
|
panda_serials = [p.get_usb_serial() for p in pandas]
|
|
|
|
# log panda fw versions
|
|
params.put("PandaSignatures", b','.join(p.get_signature() for p in pandas))
|
|
|
|
for panda in pandas:
|
|
# check health for lost heartbeat
|
|
health = panda.health()
|
|
if health["heartbeat_lost"]:
|
|
params.put_bool("PandaHeartbeatLost", True)
|
|
cloudlog.event("heartbeat lost", deviceState=health, serial=panda.get_usb_serial())
|
|
if health["som_reset_triggered"]:
|
|
params.put_bool("PandaSomResetTriggered", True)
|
|
cloudlog.event("panda.som_reset_triggered", health=health, serial=panda.get_usb_serial())
|
|
|
|
if first_run:
|
|
# reset panda to ensure we're in a good state
|
|
cloudlog.info(f"Resetting panda {panda.get_usb_serial()}")
|
|
panda.reset(reconnect=True)
|
|
|
|
for p in pandas:
|
|
p.close()
|
|
# TODO: wrap all panda exceptions in a base panda exception
|
|
except (usb1.USBErrorNoDevice, usb1.USBErrorPipe):
|
|
# a panda was disconnected while setting everything up. let's try again
|
|
cloudlog.exception("Panda USB exception while setting up")
|
|
continue
|
|
except PandaProtocolMismatch:
|
|
cloudlog.exception("pandad.protocol_mismatch")
|
|
continue
|
|
except Exception:
|
|
cloudlog.exception("pandad.uncaught_exception")
|
|
continue
|
|
|
|
first_run = False
|
|
|
|
# run pandad with all connected serials as arguments
|
|
os.environ['MANAGER_DAEMON'] = 'pandad'
|
|
process = subprocess.Popen(["./pandad", *panda_serials], cwd=os.path.join(BASEDIR, "selfdrive/pandad"))
|
|
process.wait()
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|