Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
94 changes: 47 additions & 47 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,52 +32,52 @@ jobs:
- name: Build panda in release mode
run: ${{ env.RUN }} "CERT=certs/debug RELEASE=1 scons -j4"

test:
name: ./test.sh
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
os: ['macos-latest', 'ubuntu-latest']
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- run: ./test.sh
# test:
# name: ./test.sh
# runs-on: ${{ matrix.os }}
# strategy:
# fail-fast: false
# matrix:
# os: ['macos-latest', 'ubuntu-latest']
# timeout-minutes: 10
# steps:
# - uses: actions/checkout@v4
# - run: ./test.sh

misra_linter:
name: MISRA C:2012 Linter
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Cache cppcheck
id: cppcheck-cache
uses: actions/cache@v4
with:
path: tests/misra/cppcheck
key: cppcheck-${{ hashFiles('tests/misra/*') }}
- run: ./setup.sh
- name: Build FW
run: ${{ env.RUN }} "scons -j$(nproc)"
- name: Run MISRA C:2012 analysis
run: ${{ env.RUN }} "cd tests/misra && ./test_misra.sh"
# misra_linter:
# name: MISRA C:2012 Linter
# runs-on: ubuntu-latest
# timeout-minutes: 10
# steps:
# - uses: actions/checkout@v4
# - name: Cache cppcheck
# id: cppcheck-cache
# uses: actions/cache@v4
# with:
# path: tests/misra/cppcheck
# key: cppcheck-${{ hashFiles('tests/misra/*') }}
# - run: ./setup.sh
# - name: Build FW
# run: ${{ env.RUN }} "scons -j$(nproc)"
# - name: Run MISRA C:2012 analysis
# run: ${{ env.RUN }} "cd tests/misra && ./test_misra.sh"

misra_mutation:
name: MISRA C:2012 Mutation
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@v4
- name: Cache cppcheck
id: cppcheck-cache
uses: actions/cache@v4
with:
path: tests/misra/cppcheck
key: cppcheck-${{ hashFiles('tests/misra/*') }}
- run: ./setup.sh
- name: Build FW
run: ${{ env.RUN }} "scons -j$(nproc)"
- name: tests/misra/install.sh
run: ${{ env.RUN }} "cd tests/misra && ./install.sh"
- name: MISRA mutation tests
run: ${{ env.RUN }} "cd tests/misra && pytest test_mutation.py"
# misra_mutation:
# name: MISRA C:2012 Mutation
# runs-on: ubuntu-latest
# timeout-minutes: 10
# steps:
# - uses: actions/checkout@v4
# - name: Cache cppcheck
# id: cppcheck-cache
# uses: actions/cache@v4
# with:
# path: tests/misra/cppcheck
# key: cppcheck-${{ hashFiles('tests/misra/*') }}
# - run: ./setup.sh
# - name: Build FW
# run: ${{ env.RUN }} "scons -j$(nproc)"
# - name: tests/misra/install.sh
# run: ${{ env.RUN }} "cd tests/misra && ./install.sh"
# - name: MISRA mutation tests
# run: ${{ env.RUN }} "cd tests/misra && pytest test_mutation.py"
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ classifiers = [
]
dependencies = [
"libusb1",
"opendbc @ git+ssh://git@github.com/Ever-Cars/opendbc.git@polar-bear#egg=opendbc",
"opendbc @ git+https://github.com/Ever-Cars/opendbc.git@polar-bear#egg=opendbc",
]

[project.optional-dependencies]
Expand All @@ -22,7 +22,6 @@ dev = [
"pycryptodome >= 3.9.8",
"cffi",
"flaky",
"prettytable",
"pytest",
"pytest-mock",
"pytest-timeout",
Expand Down
60 changes: 15 additions & 45 deletions python/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,28 +112,22 @@ class Panda:

# from https://github.com/commaai/openpilot/blob/103b4df18cbc38f4129555ab8b15824d1a672bdf/cereal/log.capnp#L648
HW_TYPE_UNKNOWN = b'\x00'
HW_TYPE_WHITE = b'\x01'
HW_TYPE_BLACK = b'\x03'
HW_TYPE_RED_PANDA = b'\x07'
HW_TYPE_TRES = b'\x09'
HW_TYPE_CUATRO = b'\x0a'
HW_TYPE_BODY = b'\xb1'

CAN_PACKET_VERSION = 4
HEALTH_PACKET_VERSION = 17
CAN_HEALTH_PACKET_VERSION = 5
HEALTH_STRUCT = struct.Struct("<IIIIIIIIBBBBBHBBBHfBBHHHB")
CAN_HEALTH_STRUCT = struct.Struct("<BIBBBBBBBBIIIIIIIHHBBBIIII")

H7_DEVICES = [HW_TYPE_RED_PANDA, HW_TYPE_TRES, HW_TYPE_CUATRO]
H7_DEVICES = [HW_TYPE_RED_PANDA, HW_TYPE_TRES, HW_TYPE_CUATRO, HW_TYPE_BODY]
SUPPORTED_DEVICES = H7_DEVICES

INTERNAL_DEVICES = (HW_TYPE_TRES, HW_TYPE_CUATRO)

MAX_FAN_RPMs = {
HW_TYPE_TRES: 6600,
HW_TYPE_CUATRO: 5000,
}

HARNESS_STATUS_NC = 0
HARNESS_STATUS_NORMAL = 1
HARNESS_STATUS_FLIPPED = 2
Expand All @@ -147,11 +141,10 @@ def __init__(self, serial: str | None = None, claim: bool = True, disable_checks
self._can_speed_kbps = can_speed_kbps

if cli and serial is None:
self._connect_serial = self._cli_select_panda()
self._connect_serial = self._cli_select_panda()
else:
self._connect_serial = serial
self._connect_serial = serial

# connect and set mcu type
self.connect(claim)

def _cli_select_panda(self):
Expand Down Expand Up @@ -208,14 +201,9 @@ def connect(self, claim=True, wait=False):
self._serial = serial
self._connect_serial = serial
self._handle_open = True
self._mcu_type = self.get_mcu_type()
self.health_version, self.can_version, self.can_health_version = self.get_packets_versions()
logger.debug("connected")

hw_type = self.get_type()
if hw_type not in self.SUPPORTED_DEVICES:
print("WARNING: Using deprecated HW")

# disable openpilot's heartbeat checks
if self._disable_checks:
self.set_heartbeat_disabled()
Expand Down Expand Up @@ -286,7 +274,7 @@ def usb_connect(cls, serial, claim=True, no_error=False):
handle = device.open()
if sys.platform not in ("win32", "cygwin", "msys", "darwin"):
handle.setAutoDetachKernelDriver(True)
if claim:
if claim or sys.platform == "darwin":
handle.claimInterface(0)
# handle.setInterfaceAltSetting(0, 0) # Issue in USB stack

Expand Down Expand Up @@ -342,6 +330,9 @@ def spi_list(cls):
return []

def reset(self, enter_bootstub=False, enter_bootloader=False, reconnect=True):
if enter_bootstub or enter_bootloader:
assert (hw_type := self.get_type()) in self.SUPPORTED_DEVICES, f"Unknown HW: {hw_type}"

# no response is expected since it resets right away
timeout = 5000 if isinstance(self._handle, PandaSpiHandle) else 15000
try:
Expand Down Expand Up @@ -371,7 +362,7 @@ def reconnect(self):
# wait up to 15 seconds
for _ in range(15*10):
try:
self.connect(wait=True)
self.connect(claim=False, wait=True)
success = True
break
except Exception:
Expand Down Expand Up @@ -421,16 +412,14 @@ def flash_static(handle, code, mcu_type):
pass

def flash(self, fn=None, code=None, reconnect=True):
assert (hw_type := self.get_type()) in self.SUPPORTED_DEVICES, f"Unknown HW: {hw_type}"

if self.up_to_date(fn=fn):
logger.info("flash: already up to date")
return

hw_type = self.get_type()
if hw_type not in self.SUPPORTED_DEVICES:
raise RuntimeError(f"HW type {hw_type.hex()} is deprecated and can no longer be flashed.")

if not fn:
fn = os.path.join(FW_PATH, self._mcu_type.config.app_fn)
fn = os.path.join(FW_PATH, McuType.H7.config.app_fn)
assert os.path.isfile(fn)
logger.debug("flash: main version is %s", self.get_version())
if not self.bootstub:
Expand All @@ -445,7 +434,7 @@ def flash(self, fn=None, code=None, reconnect=True):
logger.debug("flash: bootstub version is %s", self.get_version())

# do flash
Panda.flash_static(self._handle, code, mcu_type=self._mcu_type)
Panda.flash_static(self._handle, code, mcu_type=McuType.H7)

# reconnect
if reconnect:
Expand Down Expand Up @@ -496,7 +485,7 @@ def wait_for_panda(cls, serial: str | None, timeout: int) -> bool:
def up_to_date(self, fn=None) -> bool:
current = self.get_signature()
if fn is None:
fn = os.path.join(FW_PATH, self.get_mcu_type().config.app_fn)
fn = os.path.join(FW_PATH, McuType.H7.config.app_fn)
expected = Panda.get_signature_from_firmware(fn)
return (current == expected)

Expand Down Expand Up @@ -608,12 +597,6 @@ def get_packets_versions(self):
else:
return (0, 0, 0)

def get_mcu_type(self) -> McuType:
hw_type = self.get_type()
if hw_type in Panda.H7_DEVICES:
return McuType.H7
raise ValueError(f"unknown HW type: {hw_type}")

def is_internal(self):
return self.get_type() in Panda.INTERNAL_DEVICES

Expand All @@ -634,7 +617,7 @@ def get_usb_serial(self):
return self._serial

def get_dfu_serial(self):
return PandaDFU.st_serial_to_dfu_serial(self._serial, self._mcu_type)
return PandaDFU.st_serial_to_dfu_serial(self._serial, McuType.H7)

def get_uid(self):
"""
Expand Down Expand Up @@ -694,10 +677,6 @@ def set_uart_parity(self, uart, parity):
def set_uart_callback(self, uart, install):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe3, uart, int(install), b'')

# LED stuff
def set_led(self, led, state):
self._handle.controlWrite(Panda.REQUEST_OUT, 0xe9, led, state, b'')

# ******************* can *******************

# The panda will NAK CAN writes when there is CAN congestion.
Expand Down Expand Up @@ -742,15 +721,6 @@ def can_clear(self, bus):

"""
self._handle.controlWrite(Panda.REQUEST_OUT, 0xf1, bus, 0, b'')

def get_can_rx_slots(self):
"""Returns the number of empty RX slots in the internal CAN ringbuffer.

Returns:
int: number of empty RX slots.
"""
dat = self._handle.controlRead(Panda.REQUEST_IN, 0xc7, 0, 0, 2)
return struct.unpack("H", dat)[0]

# ******************* serial *******************

Expand Down
Loading