From d9ed70b850513f65e2a69707835f818409fe6052 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Thu, 23 Jul 2026 09:31:26 -0700 Subject: [PATCH 1/3] rm pycryptodome (#2418) --- SConscript | 26 ++++++++++++++++---------- board/crypto/sign.py | 24 ++++++++++++++++++++---- pyproject.toml | 1 - 3 files changed, 36 insertions(+), 15 deletions(-) diff --git a/SConscript b/SConscript index de770920385..018603f505b 100644 --- a/SConscript +++ b/SConscript @@ -1,5 +1,6 @@ import os import hashlib +import base64 import opendbc import subprocess @@ -32,23 +33,28 @@ def get_version(builder, build_type): return f"{builder}-{git}-{build_type}" def get_key_header(name): - from Crypto.PublicKey import RSA - public_fn = File(f'./board/certs/{name}.pub').srcnode().get_path() - with open(public_fn) as f: - rsa = RSA.importKey(f.read()) - assert(rsa.size_in_bits() == 1024) - - rr = pow(2**1024, 2, rsa.n) - n0inv = 2**32 - pow(rsa.n, -1, 2**32) + with open(public_fn, "rb") as f: + key = base64.b64decode(f.read().split()[1]) + values = [] + for _ in range(3): + length = int.from_bytes(key[:4], "big") + values.append(key[4:4 + length]) + key = key[4 + length:] + _, e, n = values + e, n = int.from_bytes(e, "big"), int.from_bytes(n, "big") + assert n.bit_length() == 1024 + + rr = pow(2**1024, 2, n) + n0inv = 2**32 - pow(n, -1, 2**32) r = [ f"RSAPublicKey {name}_rsa_key = {{", f" .len = 0x20,", f" .n0inv = {n0inv}U,", - f" .n = {to_c_uint32(rsa.n)},", + f" .n = {to_c_uint32(n)},", f" .rr = {to_c_uint32(rr)},", - f" .exponent = {rsa.e},", + f" .exponent = {e},", f"}};", ] return r diff --git a/board/crypto/sign.py b/board/crypto/sign.py index daea38630c5..bde1ef18f1a 100755 --- a/board/crypto/sign.py +++ b/board/crypto/sign.py @@ -3,15 +3,31 @@ import sys import struct import hashlib -from Crypto.PublicKey import RSA import binascii +import base64 + + +def read_der(dat): + length = dat[1] + offset = 2 + if length & 0x80: + length_bytes = length & 0x7f + length = int.from_bytes(dat[offset:offset + length_bytes], "big") + offset += length_bytes + return dat[offset:offset + length], dat[offset + length:] # increment this to make new hardware not run old versions VERSION = 2 if __name__ == "__main__": - with open(sys.argv[3]) as k: - rsa = RSA.importKey(k.read()) + with open(sys.argv[3], "rb") as k: + pem = b"".join(k.read().splitlines()[1:-1]) + der, _ = read_der(base64.b64decode(pem)) + values = [] + while der: + value, der = read_der(der) + values.append(int.from_bytes(value, "big")) + _, rsa_n, _, rsa_d = values[:4] with open(sys.argv[1], "rb") as f: dat = f.read() @@ -32,7 +48,7 @@ print("hash:", str(binascii.hexlify(dd), "utf-8")) dd = b"\x00\x01" + b"\xff" * 0x69 + b"\x00" + dd - rsa_out = pow(int.from_bytes(dd, byteorder='big', signed=False), rsa.d, rsa.n) + rsa_out = pow(int.from_bytes(dd, byteorder='big', signed=False), rsa_d, rsa_n) sig = (hex(rsa_out)[2:].rjust(0x100, '0')) x += binascii.unhexlify(sig) f.write(x) diff --git a/pyproject.toml b/pyproject.toml index e30b39954d2..5d95f632642 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -21,7 +21,6 @@ dependencies = [ [project.optional-dependencies] dev = [ "scons", - "pycryptodome >= 3.9.8", "cffi", "flaky", "pytest", From a63aed56c9a0780c9bdd8cd3ead482de32b61ab7 Mon Sep 17 00:00:00 2001 From: Henry <43358667+probablyanasian@users.noreply.github.com> Date: Sun, 26 Jul 2026 16:36:27 -0700 Subject: [PATCH 2/3] pull pyproject deps in CI (#2420) * pull origin/master in CI * hard reset first * retrigger CI * rerun ci * retry tests * attempt at using the uv opendbc * fix error during uv sync * use test dir to cache uv * rerun * preserve cache * rerun * retry * do not use shimmed uv * don't preserve .venv between runs * prune cache after uv syncs --------- Co-authored-by: Robbe Derks --- Jenkinsfile | 7 +++++-- tests/setup_device_ci.sh | 10 +++++++--- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/Jenkinsfile b/Jenkinsfile index 6872ed250bb..c1b38c75042 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -30,10 +30,13 @@ export TEST_DIR=${env.TEST_DIR} export SOURCE_DIR=${env.SOURCE_DIR} export GIT_BRANCH=${env.GIT_BRANCH} export GIT_COMMIT=${env.GIT_COMMIT} -export PYTHONPATH=${env.TEST_DIR}/../ export PYTHONWARNINGS=error export LOGLEVEL=debug -ln -sf /data/openpilot/opendbc_repo/opendbc /data/opendbc + +unset PYTHONPATH +if [ -f "${env.TEST_DIR}/.venv/bin/activate" ]; then + source "${env.TEST_DIR}/.venv/bin/activate" +fi # TODO: this is an agnos issue export PYTEST_ADDOPTS="-p no:asyncio" diff --git a/tests/setup_device_ci.sh b/tests/setup_device_ci.sh index fe28b8612cb..2ad42e1122e 100755 --- a/tests/setup_device_ci.sh +++ b/tests/setup_device_ci.sh @@ -45,8 +45,6 @@ sleep infinity EOF chmod +x $CONTINUE_PATH - -# set up environment if [ ! -d "$SOURCE_DIR" ]; then git clone https://github.com/commaai/panda.git $SOURCE_DIR fi @@ -71,6 +69,12 @@ git clean -xdff echo "git checkout done, t=$SECONDS" du -hs $SOURCE_DIR $SOURCE_DIR/.git -rsync -a --delete $SOURCE_DIR $TEST_DIR +rsync -a --delete "$SOURCE_DIR" "$TEST_DIR" + +# /usr/comma/shims/uv wraps uv in sudo, which roots the venv — use the real binary +UV=$(type -ap uv | grep -vF /usr/comma/shims | head -n1) +# use panda's environment so dependencies come from its pyproject.toml +PYTHONWARNINGS=default "$UV" sync --project "$TEST_DIR" --cache-dir="/data/uv_cache" --all-extras --upgrade-package opendbc +"$UV" cache prune --cache-dir=/data/uv_cache echo "$TEST_DIR synced with $GIT_COMMIT, t=$SECONDS" From dd8a5b3df77706337a11555377e7180c5adc8726 Mon Sep 17 00:00:00 2001 From: Henry <43358667+probablyanasian@users.noreply.github.com> Date: Mon, 27 Jul 2026 00:05:40 -0700 Subject: [PATCH 3/3] add digital temperature sensor to health packet (#2414) * add digital temperature sensor to health packet * add prescaler to dts for calibration * fix mismatch * fix power_saving.h DTS config divergence * whitespace, one-line the dts CFGR1 clear * remove _c from temperature field * del print * move dts enable to peripherals --- board/health.h | 1 + board/main.c | 1 + board/main_comms.h | 2 ++ board/stm32h7/board.h | 1 + board/stm32h7/lldts.h | 32 ++++++++++++++++++++++++++++++++ board/stm32h7/peripherals.h | 1 + board/sys/power_saving.h | 6 ++++++ python/__init__.py | 1 + 8 files changed, 45 insertions(+) create mode 100644 board/stm32h7/lldts.h diff --git a/board/health.h b/board/health.h index f585cd636b4..5f15a0ccba6 100644 --- a/board/health.h +++ b/board/health.h @@ -27,6 +27,7 @@ struct __attribute__((packed)) health_t { uint16_t sbu2_voltage_mV; uint8_t som_reset_triggered; uint16_t sound_output_level_pkt; + float temperature; }; typedef struct __attribute__((packed)) { diff --git a/board/main.c b/board/main.c index ba60de57fd6..f08953d82d3 100644 --- a/board/main.c +++ b/board/main.c @@ -283,6 +283,7 @@ int main(void) { led_set(LED_RED, true); led_set(LED_GREEN, true); adc_init(ADC1); + dts_init(); // print hello print("\n\n\n************************ MAIN START ************************\n"); diff --git a/board/main_comms.h b/board/main_comms.h index 8229a47ab9a..42f4265f2b6 100644 --- a/board/main_comms.h +++ b/board/main_comms.h @@ -44,6 +44,8 @@ static int get_health_pkt(void *dat) { health->sound_output_level_pkt = sound_output_level; + health->temperature = dts_get_temperature(); + return sizeof(*health); } diff --git a/board/stm32h7/board.h b/board/stm32h7/board.h index 05c5c5e7155..39293fbe772 100644 --- a/board/stm32h7/board.h +++ b/board/stm32h7/board.h @@ -6,6 +6,7 @@ // ///// Board definition and detection ///// // #include "board/stm32h7/lladc.h" +#include "board/stm32h7/lldts.h" #include "board/drivers/harness.h" #include "board/drivers/fan.h" #include "board/stm32h7/llfan.h" diff --git a/board/stm32h7/lldts.h b/board/stm32h7/lldts.h new file mode 100644 index 00000000000..614a09f9a23 --- /dev/null +++ b/board/stm32h7/lldts.h @@ -0,0 +1,32 @@ +#pragma once + +// Digital temperature sensor (DTS) + +#define DTS_SMP_TIME 15U // sensor periods per measurement (1 nibble) +#define DTS_PCLK_FREQ 60000000U // APB4 frequency, see clock.h +#define DTS_HSREF_DIV 64U // calibration counter must run below 1MHz + +void dts_init(void) { + // set sampling time, pclk reference, software trigger, calibrated measurement, calibration clock prescaler + register_set(&(DTS->CFGR1), (((uint32_t) DTS_SMP_TIME << DTS_CFGR1_TS1_SMP_TIME_Pos) | ((uint32_t) DTS_HSREF_DIV << DTS_CFGR1_HSREF_CLK_DIV_Pos)), + (DTS_CFGR1_TS1_SMP_TIME_Msk | DTS_CFGR1_REFCLK_SEL_Msk | DTS_CFGR1_Q_MEAS_OPT_Msk | DTS_CFGR1_HSREF_CLK_DIV_Msk | DTS_CFGR1_TS1_INTRIG_SEL_Msk)); + register_set_bits(&(DTS->CFGR1), DTS_CFGR1_TS1_EN); + while ((DTS->SR & DTS_SR_TS1_RDY) == 0U); + // continuous measurements w/ sw trigger + register_set_bits(&(DTS->CFGR1), DTS_CFGR1_TS1_START); +} + +float dts_get_temperature(void) { + // formula with pclk used + float ret = 0.0f; + uint32_t measurement_cycles = DTS->DR & DTS_DR_TS1_MFREQ_Msk; + uint32_t reference_frequency = (DTS->T0VALR1 & DTS_T0VALR1_TS1_FMT0_Msk) * 100U; // T0 value as Hz + uint32_t ramp_coefficient = DTS->RAMPVALR & DTS_RAMPVALR_TS1_RAMP_COEFF_Msk; // Hz per deg C + float reference_temperature = (((DTS->T0VALR1 & DTS_T0VALR1_TS1_T0_Msk) >> DTS_T0VALR1_TS1_T0_Pos) == 0U) ? 30.0f : 130.0f; // t0 reference temp + + if ((measurement_cycles != 0U) && (ramp_coefficient != 0U)) { + float measurement_frequency = ((float) DTS_PCLK_FREQ * (float) DTS_SMP_TIME) / (float) measurement_cycles; + ret = reference_temperature + ((measurement_frequency - (float) reference_frequency) / (float) ramp_coefficient); + } + return ret; +} diff --git a/board/stm32h7/peripherals.h b/board/stm32h7/peripherals.h index 8eb384307f3..4cebbcf7e5d 100644 --- a/board/stm32h7/peripherals.h +++ b/board/stm32h7/peripherals.h @@ -96,6 +96,7 @@ void peripherals_init(void) { RCC->AHB1ENR |= RCC_AHB1ENR_DMA2EN; // SPI DMA RCC->APB4ENR |= RCC_APB4ENR_SYSCFGEN; RCC->AHB4ENR |= RCC_AHB4ENR_BDMAEN; // Audio DMA + RCC->APB4ENR |= RCC_APB4ENR_DTSEN; // Digital Temperature Sensor // Connectivity RCC->APB2ENR |= RCC_APB2ENR_SPI4EN; // SPI diff --git a/board/sys/power_saving.h b/board/sys/power_saving.h index 3bcafa403cd..791353c4e44 100644 --- a/board/sys/power_saving.h +++ b/board/sys/power_saving.h @@ -75,6 +75,12 @@ static void enter_stop_mode(void) { ADC2->CR &= ~(ADC_CR_ADEN); ADC2->CR |= ADC_CR_DEEPPWD; + // disable DTS + register_clear_bits(&(DTS->CFGR1), DTS_CFGR1_TS1_START); + register_clear_bits(&(DTS->CFGR1), DTS_CFGR1_TS1_EN); + register_set(&(DTS->CFGR1), 0U, (DTS_CFGR1_TS1_SMP_TIME_Msk | DTS_CFGR1_REFCLK_SEL_Msk | DTS_CFGR1_Q_MEAS_OPT_Msk | DTS_CFGR1_HSREF_CLK_DIV_Msk | DTS_CFGR1_TS1_INTRIG_SEL_Msk)); + RCC->APB4ENR &= ~(RCC_APB4ENR_DTSEN); + // disable HSI48: 48 MHz USB clock register_clear_bits(&(RCC->CR), RCC_CR_HSI48ON); // disable SRAM retention in stop mode diff --git a/python/__init__.py b/python/__init__.py index 4c954b23950..9344961409b 100644 --- a/python/__init__.py +++ b/python/__init__.py @@ -543,6 +543,7 @@ def health(self): "sbu2_voltage_mV": a[23], "som_reset_triggered": a[24], "sound_output_level": a[25], + "temperature": a[26], } @ensure_health_packet_version