mirror of https://github.com/commaai/panda.git
cleanup MCU definitions (#1226)
* cleanup MCU definitions * rename * enum * enum * fix that
This commit is contained in:
parent
33e576214d
commit
76d0459182
13
__init__.py
13
__init__.py
|
@ -1,10 +1,5 @@
|
|||
from .python import (Panda, PandaDFU, # noqa: F401
|
||||
BASEDIR, pack_can_buffer, unpack_can_buffer, calculate_checksum,
|
||||
DEFAULT_FW_FN, DEFAULT_H7_FW_FN, MCU_TYPE_H7, MCU_TYPE_F4, DLC_TO_LEN, LEN_TO_DLC,
|
||||
ALTERNATIVE_EXPERIENCE, USBPACKET_MAX_SIZE, CANPACKET_HEAD_SIZE)
|
||||
|
||||
from .python.constants import McuType, BASEDIR # noqa: F401
|
||||
from .python.serial import PandaSerial # noqa: F401
|
||||
|
||||
from .python.config import (BOOTSTUB_ADDRESS, BLOCK_SIZE_FX, APP_ADDRESS_FX, # noqa: F401
|
||||
BLOCK_SIZE_H7, APP_ADDRESS_H7, DEVICE_SERIAL_NUMBER_ADDR_H7, # noqa: F401
|
||||
DEVICE_SERIAL_NUMBER_ADDR_FX)
|
||||
from .python import (Panda, PandaDFU, # noqa: F401
|
||||
pack_can_buffer, unpack_can_buffer, calculate_checksum,
|
||||
DLC_TO_LEN, LEN_TO_DLC, ALTERNATIVE_EXPERIENCE, USBPACKET_MAX_SIZE, CANPACKET_HEAD_SIZE)
|
||||
|
|
|
@ -13,8 +13,8 @@ from functools import wraps
|
|||
from typing import Optional
|
||||
from itertools import accumulate
|
||||
|
||||
from .config import DEFAULT_FW_FN, DEFAULT_H7_FW_FN, SECTOR_SIZES_FX, SECTOR_SIZES_H7
|
||||
from .dfu import PandaDFU, MCU_TYPE_F2, MCU_TYPE_F4, MCU_TYPE_H7
|
||||
from .constants import McuType
|
||||
from .dfu import PandaDFU
|
||||
from .isotp import isotp_send, isotp_recv
|
||||
from .spi import SpiHandle, PandaSpiException
|
||||
|
||||
|
@ -25,8 +25,6 @@ LOGLEVEL = os.environ.get('LOGLEVEL', 'INFO').upper()
|
|||
logging.basicConfig(level=LOGLEVEL, format='%(message)s')
|
||||
|
||||
|
||||
BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")
|
||||
|
||||
USBPACKET_MAX_SIZE = 0x40
|
||||
CANPACKET_HEAD_SIZE = 0x6
|
||||
DLC_TO_LEN = [0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64]
|
||||
|
@ -409,7 +407,7 @@ class Panda:
|
|||
assert fr[4:8] == b"\xde\xad\xd0\x0d"
|
||||
|
||||
# determine sectors to erase
|
||||
apps_sectors_cumsum = accumulate(SECTOR_SIZES_H7[1:] if mcu_type == MCU_TYPE_H7 else SECTOR_SIZES_FX[1:])
|
||||
apps_sectors_cumsum = accumulate(mcu_type.config.sector_sizes[1:])
|
||||
last_sector = next((i + 1 for i, v in enumerate(apps_sectors_cumsum) if v > len(code)), -1)
|
||||
assert last_sector >= 1, "Binary too small? No sector to erase."
|
||||
assert last_sector < 7, "Binary too large! Risk of overwriting provisioning chunk."
|
||||
|
@ -438,7 +436,7 @@ class Panda:
|
|||
|
||||
def flash(self, fn=None, code=None, reconnect=True):
|
||||
if not fn:
|
||||
fn = DEFAULT_H7_FW_FN if self._mcu_type == MCU_TYPE_H7 else DEFAULT_FW_FN
|
||||
fn = self._mcu_type.config.app_path
|
||||
assert os.path.isfile(fn)
|
||||
logging.debug("flash: main version is %s", self.get_version())
|
||||
if not self.bootstub:
|
||||
|
@ -602,15 +600,15 @@ class Panda:
|
|||
else:
|
||||
return (0, 0, 0)
|
||||
|
||||
def get_mcu_type(self):
|
||||
def get_mcu_type(self) -> McuType:
|
||||
hw_type = self.get_type()
|
||||
if hw_type in Panda.F2_DEVICES:
|
||||
return MCU_TYPE_F2
|
||||
return McuType.F2
|
||||
elif hw_type in Panda.F4_DEVICES:
|
||||
return MCU_TYPE_F4
|
||||
return McuType.F4
|
||||
elif hw_type in Panda.H7_DEVICES:
|
||||
return MCU_TYPE_H7
|
||||
return None
|
||||
return McuType.H7
|
||||
raise ValueError(f"unknown HW type: {hw_type}")
|
||||
|
||||
def has_obd(self):
|
||||
return self.get_type() in Panda.HAS_OBD
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
import os
|
||||
|
||||
BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")
|
||||
|
||||
BOOTSTUB_ADDRESS = 0x8000000
|
||||
|
||||
BLOCK_SIZE_FX = 0x800
|
||||
APP_ADDRESS_FX = 0x8004000
|
||||
SECTOR_SIZES_FX = [0x4000 for _ in range(4)] + [0x10000] + [0x20000 for _ in range(11)]
|
||||
DEVICE_SERIAL_NUMBER_ADDR_FX = 0x1FFF79C0
|
||||
DEFAULT_FW_FN = os.path.join(BASEDIR, "board", "obj", "panda.bin.signed")
|
||||
DEFAULT_BOOTSTUB_FN = os.path.join(BASEDIR, "board", "obj", "bootstub.panda.bin")
|
||||
|
||||
BLOCK_SIZE_H7 = 0x400
|
||||
APP_ADDRESS_H7 = 0x8020000
|
||||
SECTOR_SIZES_H7 = [0x20000 for _ in range(7)] # there is an 8th sector, but we use that for the provisioning chunk, so don't program over that!
|
||||
DEVICE_SERIAL_NUMBER_ADDR_H7 = 0x080FFFC0
|
||||
DEFAULT_H7_FW_FN = os.path.join(BASEDIR, "board", "obj", "panda_h7.bin.signed")
|
||||
DEFAULT_H7_BOOTSTUB_FN = os.path.join(BASEDIR, "board", "obj", "bootstub.panda_h7.bin")
|
|
@ -0,0 +1,50 @@
|
|||
import os
|
||||
import enum
|
||||
from typing import List, NamedTuple
|
||||
|
||||
BASEDIR = os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")
|
||||
|
||||
|
||||
class McuConfig(NamedTuple):
|
||||
mcu: str
|
||||
block_size: int
|
||||
sector_sizes: List[int]
|
||||
serial_number_address: int
|
||||
app_address: int
|
||||
app_path: str
|
||||
bootstub_address: int
|
||||
bootstub_path: str
|
||||
|
||||
Fx = (
|
||||
0x800,
|
||||
[0x4000 for _ in range(4)] + [0x10000] + [0x20000 for _ in range(11)],
|
||||
0x1FFF79C0,
|
||||
0x8004000,
|
||||
os.path.join(BASEDIR, "board", "obj", "panda.bin.signed"),
|
||||
0x8000000,
|
||||
os.path.join(BASEDIR, "board", "obj", "bootstub.panda.bin"),
|
||||
)
|
||||
F2Config = McuConfig("STM32F2", *Fx)
|
||||
F4Config = McuConfig("STM32F4", *Fx)
|
||||
|
||||
H7Config = McuConfig(
|
||||
"STM32H7",
|
||||
0x400,
|
||||
# there is an 8th sector, but we use that for the provisioning chunk, so don't program over that!
|
||||
[0x20000 for _ in range(7)],
|
||||
0x080FFFC0,
|
||||
0x8020000,
|
||||
os.path.join(BASEDIR, "board", "obj", "panda_h7.bin.signed"),
|
||||
0x8000000,
|
||||
os.path.join(BASEDIR, "board", "obj", "bootstub.panda_h7.bin"),
|
||||
)
|
||||
|
||||
@enum.unique
|
||||
class McuType(enum.Enum):
|
||||
F2 = F2Config
|
||||
F4 = F4Config
|
||||
H7 = H7Config
|
||||
|
||||
@property
|
||||
def config(self):
|
||||
return self.value
|
|
@ -1,12 +1,9 @@
|
|||
import usb1
|
||||
import struct
|
||||
import binascii
|
||||
from .config import BOOTSTUB_ADDRESS, APP_ADDRESS_H7, APP_ADDRESS_FX, BLOCK_SIZE_H7, BLOCK_SIZE_FX, DEFAULT_H7_BOOTSTUB_FN, DEFAULT_BOOTSTUB_FN
|
||||
|
||||
from .constants import McuType
|
||||
|
||||
MCU_TYPE_F2 = 0
|
||||
MCU_TYPE_F4 = 1
|
||||
MCU_TYPE_H7 = 2
|
||||
|
||||
# *** DFU mode ***
|
||||
DFU_DNLOAD = 1
|
||||
|
@ -15,8 +12,9 @@ DFU_GETSTATUS = 3
|
|||
DFU_CLRSTATUS = 4
|
||||
DFU_ABORT = 6
|
||||
|
||||
class PandaDFU(object):
|
||||
class PandaDFU:
|
||||
def __init__(self, dfu_serial):
|
||||
self._handle = None
|
||||
context = usb1.USBContext()
|
||||
for device in context.getDeviceList(skip_on_error=True):
|
||||
if device.getVendorID() == 0x0483 and device.getProductID() == 0xdf11:
|
||||
|
@ -25,10 +23,12 @@ class PandaDFU(object):
|
|||
except Exception:
|
||||
continue
|
||||
if this_dfu_serial == dfu_serial or dfu_serial is None:
|
||||
self._mcu_type = self.get_mcu_type(device)
|
||||
self._handle = device.open()
|
||||
return
|
||||
raise Exception("failed to open " + dfu_serial if dfu_serial is not None else "DFU device")
|
||||
self._mcu_type = self.get_mcu_type(device)
|
||||
break
|
||||
|
||||
if self._handle is None:
|
||||
raise Exception(f"failed to open DFU device {dfu_serial}")
|
||||
|
||||
@staticmethod
|
||||
def list():
|
||||
|
@ -46,18 +46,19 @@ class PandaDFU(object):
|
|||
return dfu_serials
|
||||
|
||||
@staticmethod
|
||||
def st_serial_to_dfu_serial(st, mcu_type=MCU_TYPE_F4):
|
||||
def st_serial_to_dfu_serial(st, mcu_type=McuType.F4):
|
||||
if st is None or st == "none":
|
||||
return None
|
||||
uid_base = struct.unpack("H" * 6, bytes.fromhex(st))
|
||||
if mcu_type == MCU_TYPE_H7:
|
||||
if mcu_type == McuType.H7:
|
||||
return binascii.hexlify(struct.pack("!HHH", uid_base[1] + uid_base[5], uid_base[0] + uid_base[4], uid_base[3])).upper().decode("utf-8")
|
||||
else:
|
||||
return binascii.hexlify(struct.pack("!HHH", uid_base[1] + uid_base[5], uid_base[0] + uid_base[4] + 0xA, uid_base[3])).upper().decode("utf-8")
|
||||
|
||||
# TODO: Find a way to detect F4 vs F2
|
||||
def get_mcu_type(self, dev):
|
||||
return MCU_TYPE_H7 if dev.getbcdDevice() == 512 else MCU_TYPE_F4
|
||||
def get_mcu_type(self, dev) -> McuType:
|
||||
# TODO: Find a way to detect F4 vs F2
|
||||
# TODO: also check F4 BCD, don't assume in else
|
||||
return McuType.H7 if dev.getbcdDevice() == 512 else McuType.F4
|
||||
|
||||
def status(self):
|
||||
while 1:
|
||||
|
@ -97,26 +98,18 @@ class PandaDFU(object):
|
|||
|
||||
def program_bootstub(self, code_bootstub):
|
||||
self.clear_status()
|
||||
self.erase(BOOTSTUB_ADDRESS)
|
||||
if self._mcu_type == MCU_TYPE_H7:
|
||||
self.erase(APP_ADDRESS_H7)
|
||||
self.program(BOOTSTUB_ADDRESS, code_bootstub, BLOCK_SIZE_H7)
|
||||
else:
|
||||
self.erase(APP_ADDRESS_FX)
|
||||
self.program(BOOTSTUB_ADDRESS, code_bootstub, BLOCK_SIZE_FX)
|
||||
self.erase(self._mcu_type.config.bootstub_address)
|
||||
self.erase(self._mcu_type.config.app_address)
|
||||
self.program(self._mcu_type.config.bootstub_address, code_bootstub, self._mcu_type.config.block_size)
|
||||
self.reset()
|
||||
|
||||
def recover(self):
|
||||
fn = DEFAULT_H7_BOOTSTUB_FN if self._mcu_type == MCU_TYPE_H7 else DEFAULT_BOOTSTUB_FN
|
||||
|
||||
with open(fn, "rb") as f:
|
||||
with open(self._mcu_type.config.bootstub_path, "rb") as f:
|
||||
code = f.read()
|
||||
|
||||
self.program_bootstub(code)
|
||||
|
||||
def reset(self):
|
||||
# **** Reset ****
|
||||
self._handle.controlWrite(0x21, DFU_DNLOAD, 0, 0, b"\x21" + struct.pack("I", BOOTSTUB_ADDRESS))
|
||||
self._handle.controlWrite(0x21, DFU_DNLOAD, 0, 0, b"\x21" + struct.pack("I", self._mcu_type.config.bootstub_address))
|
||||
self.status()
|
||||
try:
|
||||
self._handle.controlWrite(0x21, DFU_DNLOAD, 2, 0, b"")
|
||||
|
|
|
@ -1,16 +1,20 @@
|
|||
import os
|
||||
import time
|
||||
|
||||
from panda import Panda, PandaDFU, MCU_TYPE_H7, BASEDIR
|
||||
from panda import Panda, PandaDFU, McuType, BASEDIR
|
||||
from .helpers import test_all_pandas, panda_connect_and_init, check_signature
|
||||
|
||||
|
||||
@test_all_pandas
|
||||
@panda_connect_and_init
|
||||
def test_a_known_bootstub(p):
|
||||
# Test that compiled app can work with known production bootstub
|
||||
KNOWN_H7_BOOTSTUB_FN = os.path.join(BASEDIR, "tests", "hitl", "known_bootstub", "bootstub.panda_h7.bin")
|
||||
KNOWN_BOOTSTUB_FN = os.path.join(BASEDIR, "tests", "hitl", "known_bootstub", "bootstub.panda.bin")
|
||||
"""
|
||||
Test that compiled app can work with known production bootstub
|
||||
"""
|
||||
known_bootstubs = {
|
||||
McuType.F4: "bootstub.panda.bin",
|
||||
McuType.H7: "bootstub.panda_h7.bin",
|
||||
}
|
||||
|
||||
p.reset(enter_bootstub=True)
|
||||
p.reset(enter_bootloader=True)
|
||||
|
@ -19,8 +23,8 @@ def test_a_known_bootstub(p):
|
|||
assert Panda.wait_for_dfu(dfu_serial, timeout=30)
|
||||
|
||||
dfu = PandaDFU(dfu_serial)
|
||||
fn = KNOWN_H7_BOOTSTUB_FN if p._mcu_type == MCU_TYPE_H7 else KNOWN_BOOTSTUB_FN
|
||||
with open(fn, "rb") as f:
|
||||
fn = known_bootstubs[p._mcu_type]
|
||||
with open(os.path.join(BASEDIR, "tests/hitl/known_bootstub", fn), "rb") as f:
|
||||
code = f.read()
|
||||
|
||||
dfu.program_bootstub(code)
|
||||
|
|
|
@ -7,7 +7,7 @@ from functools import wraps, partial
|
|||
from nose.tools import assert_equal
|
||||
from parameterized import parameterized
|
||||
|
||||
from panda import Panda, DEFAULT_H7_FW_FN, DEFAULT_FW_FN, MCU_TYPE_H7
|
||||
from panda import Panda
|
||||
from panda_jungle import PandaJungle # pylint: disable=import-error
|
||||
|
||||
SPEED_NORMAL = 500
|
||||
|
@ -210,7 +210,6 @@ def clear_can_buffers(panda):
|
|||
|
||||
def check_signature(p):
|
||||
assert not p.bootstub, "Flashed firmware not booting. Stuck in bootstub."
|
||||
fn = DEFAULT_H7_FW_FN if p.get_mcu_type() == MCU_TYPE_H7 else DEFAULT_FW_FN
|
||||
firmware_sig = Panda.get_signature_from_firmware(fn)
|
||||
firmware_sig = Panda.get_signature_from_firmware(p.get_mcu_type().config.app_path)
|
||||
panda_sig = p.get_signature()
|
||||
assert_equal(panda_sig, firmware_sig)
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
#!/usr/bin/env python3
|
||||
import time
|
||||
import argparse
|
||||
from panda import Panda
|
||||
from panda.python.dfu import MCU_TYPE_F2
|
||||
from panda import Panda, McuType
|
||||
from panda.tests.pedal.canhandle import CanHandle
|
||||
|
||||
|
||||
|
@ -29,6 +28,6 @@ if __name__ == "__main__":
|
|||
time.sleep(0.1)
|
||||
print("flashing", args.fn)
|
||||
code = open(args.fn, "rb").read()
|
||||
Panda.flash_static(CanHandle(p, 0), code, mcu_type=MCU_TYPE_F2)
|
||||
Panda.flash_static(CanHandle(p, 0), code, mcu_type=McuType.F2)
|
||||
|
||||
print("can flash done")
|
||||
|
|
Loading…
Reference in New Issue