From 5898d8a406aa5a5f933a799e56d1ef12e0fdd2f1 Mon Sep 17 00:00:00 2001 From: tychovrahe Date: Wed, 26 Feb 2025 13:18:27 +0100 Subject: [PATCH] feat(core/prodtest): add hw-revision command and driver --- core/SConscript.prodtest | 3 +- .../models/T3B1/boards/trezor_t3b1_revB.h | 14 +++ .../models/T3T1/boards/trezor_t3t1_revE.h | 16 ++- .../models/T3W1/boards/trezor_t3w1_revA.h | 11 ++ .../models/T3W1/boards/trezor_t3w1_revA0.h | 11 ++ .../models/T3W1/boards/trezor_t3w1_revB.h | 11 ++ .../projects/prodtest/.changelog.d/4682.added | 1 + core/embed/projects/prodtest/README.md | 9 ++ .../prodtest/cmd/prodtest_hw_revision.c | 40 ++++++ core/embed/projects/prodtest/main.c | 7 ++ .../util/hw_revision/inc/util/hw_revision.h | 28 +++++ .../util/hw_revision/stm32/hw_revision.c | 114 ++++++++++++++++++ .../models/T3B1/trezor_t3b1_revB.py | 5 + .../models/T3T1/trezor_t3t1_revE.py | 5 + .../models/T3W1/trezor_t3w1_revB.py | 5 + 15 files changed, 278 insertions(+), 2 deletions(-) create mode 100644 core/embed/projects/prodtest/.changelog.d/4682.added create mode 100644 core/embed/projects/prodtest/cmd/prodtest_hw_revision.c create mode 100644 core/embed/util/hw_revision/inc/util/hw_revision.h create mode 100644 core/embed/util/hw_revision/stm32/hw_revision.c diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest index d5f6106cb97..a01ec73ba05 100644 --- a/core/SConscript.prodtest +++ b/core/SConscript.prodtest @@ -10,7 +10,7 @@ BOOTLOADER_DEVEL = ARGUMENTS.get('BOOTLOADER_DEVEL', '0') == '1' HW_REVISION = ARGUMENTS.get('HW_REVISION', None) UI_DEBUG_OVERLAY = ARGUMENTS.get('UI_DEBUG_OVERLAY', '0') == '1' -FEATURES_WANTED = ["input", "sbu", "nfc", "sd_card", "rgb_led", "usb", "consumption_mask", "optiga", "haptic", "tropic", "ble"] +FEATURES_WANTED = ["input", "sbu", "nfc", "sd_card", "rgb_led", "usb", "consumption_mask", "optiga", "haptic", "tropic", "ble", "hw_revision"] CCFLAGS_MOD = '' CPPPATH_MOD = [] @@ -108,6 +108,7 @@ SOURCE_PRODTEST = [ 'embed/projects/prodtest/cmd/prodtest_get_cpuid.c', 'embed/projects/prodtest/cmd/prodtest_haptic.c', 'embed/projects/prodtest/cmd/prodtest_help.c', + 'embed/projects/prodtest/cmd/prodtest_hw_revision.c', 'embed/projects/prodtest/cmd/prodtest_nfc.c', 'embed/projects/prodtest/cmd/prodtest_nrf.c', 'embed/projects/prodtest/cmd/prodtest_optiga.c', diff --git a/core/embed/models/T3B1/boards/trezor_t3b1_revB.h b/core/embed/models/T3B1/boards/trezor_t3b1_revB.h index f46b908758f..65408283739 100644 --- a/core/embed/models/T3B1/boards/trezor_t3b1_revB.h +++ b/core/embed/models/T3B1/boards/trezor_t3b1_revB.h @@ -64,4 +64,18 @@ #define SBU_2_PORT GPIOA #define SBU_2_CLK_ENA __HAL_RCC_GPIOA_CLK_ENABLE +#define HW_REVISION_PUPD GPIO_PULLUP +#define HW_REVISION_0_PIN GPIO_PIN_0 +#define HW_REVISION_0_PORT GPIOF +#define HW_REVISION_0_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE() +#define HW_REVISION_1_PIN GPIO_PIN_1 +#define HW_REVISION_1_PORT GPIOF +#define HW_REVISION_1_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE() +#define HW_REVISION_2_PIN GPIO_PIN_2 +#define HW_REVISION_2_PORT GPIOF +#define HW_REVISION_2_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE() +#define HW_REVISION_3_PIN GPIO_PIN_3 +#define HW_REVISION_3_PORT GPIOF +#define HW_REVISION_3_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE() + #endif //_TREZOR_T3B1_H diff --git a/core/embed/models/T3T1/boards/trezor_t3t1_revE.h b/core/embed/models/T3T1/boards/trezor_t3t1_revE.h index eb5d894de07..1860a1b8800 100644 --- a/core/embed/models/T3T1/boards/trezor_t3t1_revE.h +++ b/core/embed/models/T3T1/boards/trezor_t3t1_revE.h @@ -127,4 +127,18 @@ #define SBU_2_PORT GPIOA #define SBU_2_CLK_ENA __HAL_RCC_GPIOA_CLK_ENABLE -#endif //_TREZOR_T_H +#define HW_REVISION_PUPD GPIO_PULLUP +#define HW_REVISION_0_PIN GPIO_PIN_0 +#define HW_REVISION_0_PORT GPIOF +#define HW_REVISION_0_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE() +#define HW_REVISION_1_PIN GPIO_PIN_1 +#define HW_REVISION_1_PORT GPIOF +#define HW_REVISION_1_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE() +#define HW_REVISION_2_PIN GPIO_PIN_2 +#define HW_REVISION_2_PORT GPIOF +#define HW_REVISION_2_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE() +#define HW_REVISION_3_PIN GPIO_PIN_3 +#define HW_REVISION_3_PORT GPIOF +#define HW_REVISION_3_CLOCK_ENABLE() __HAL_RCC_GPIOF_CLK_ENABLE() + +#endif //_TREZOR_T3T1_H diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h index 64330ac3a2e..507937fa6f2 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revA.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revA.h @@ -187,4 +187,15 @@ #define NFC_EXTI_INTERRUPT_NUM EXTI10_IRQn #define NFC_EXTI_INTERRUPT_HANDLER EXTI10_IRQHandler +#define HW_REVISION_PUPD GPIO_PULLDOWN +#define HW_REVISION_0_PIN GPIO_PIN_1 +#define HW_REVISION_0_PORT GPIOI +#define HW_REVISION_0_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() +#define HW_REVISION_1_PIN GPIO_PIN_2 +#define HW_REVISION_1_PORT GPIOI +#define HW_REVISION_1_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() +#define HW_REVISION_2_PIN GPIO_PIN_3 +#define HW_REVISION_2_PORT GPIOI +#define HW_REVISION_2_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() + #endif // TREZOR_T3W1_REVA_H_ diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revA0.h b/core/embed/models/T3W1/boards/trezor_t3w1_revA0.h index 75d311fc614..315d2191a3f 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revA0.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revA0.h @@ -160,4 +160,15 @@ #define NRF_OUT_FW_RUNNING_PORT GPIOE #define NRF_OUT_FW_RUNNING_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE +#define HW_REVISION_PUPD GPIO_PULLDOWN +#define HW_REVISION_0_PIN GPIO_PIN_1 +#define HW_REVISION_0_PORT GPIOI +#define HW_REVISION_0_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() +#define HW_REVISION_1_PIN GPIO_PIN_2 +#define HW_REVISION_1_PORT GPIOI +#define HW_REVISION_1_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() +#define HW_REVISION_2_PIN GPIO_PIN_3 +#define HW_REVISION_2_PORT GPIOI +#define HW_REVISION_2_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() + #endif // TREZOR_T3W1_REVA_H_ diff --git a/core/embed/models/T3W1/boards/trezor_t3w1_revB.h b/core/embed/models/T3W1/boards/trezor_t3w1_revB.h index 7d08569ba3e..a95ba44924b 100644 --- a/core/embed/models/T3W1/boards/trezor_t3w1_revB.h +++ b/core/embed/models/T3W1/boards/trezor_t3w1_revB.h @@ -187,4 +187,15 @@ #define NFC_EXTI_INTERRUPT_NUM EXTI10_IRQn #define NFC_EXTI_INTERRUPT_HANDLER EXTI10_IRQHandler +#define HW_REVISION_PUPD GPIO_PULLDOWN +#define HW_REVISION_0_PIN GPIO_PIN_1 +#define HW_REVISION_0_PORT GPIOI +#define HW_REVISION_0_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() +#define HW_REVISION_1_PIN GPIO_PIN_2 +#define HW_REVISION_1_PORT GPIOI +#define HW_REVISION_1_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() +#define HW_REVISION_2_PIN GPIO_PIN_3 +#define HW_REVISION_2_PORT GPIOI +#define HW_REVISION_2_CLOCK_ENABLE() __HAL_RCC_GPIOI_CLK_ENABLE() + #endif // TREZOR_T3W1_REVA_H_ diff --git a/core/embed/projects/prodtest/.changelog.d/4682.added b/core/embed/projects/prodtest/.changelog.d/4682.added new file mode 100644 index 00000000000..2d5226121cc --- /dev/null +++ b/core/embed/projects/prodtest/.changelog.d/4682.added @@ -0,0 +1 @@ +[T3B1,T3T1] Added hw-revision command. diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md index 4026a03fb62..b2e04aa5b2c 100644 --- a/core/embed/projects/prodtest/README.md +++ b/core/embed/projects/prodtest/README.md @@ -268,6 +268,15 @@ haptic-test 3000 OK ``` +### hw-revision +Retrieves the hardware revision of the device. The command returns `OK` followed by the hardware revision. + +Example: +``` +hw-revision +OK 1 +``` + ### nrf-communication Tests the internal communication between the main MCU and NRF MCU. The command returns `OK` if the communication is successful. diff --git a/core/embed/projects/prodtest/cmd/prodtest_hw_revision.c b/core/embed/projects/prodtest/cmd/prodtest_hw_revision.c new file mode 100644 index 00000000000..1d8a940141c --- /dev/null +++ b/core/embed/projects/prodtest/cmd/prodtest_hw_revision.c @@ -0,0 +1,40 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifdef USE_HW_REVISION +#include + +#include +#include + +static void prodtest_hw_revision(cli_t* cli) { + uint8_t rev = hw_revision_get(); + + cli_ok(cli, "%d", rev); +} + +// clang-format off + +PRODTEST_CLI_CMD( + .name = "hw-revision", + .func = prodtest_hw_revision, + .info = "Read the HW revision", + .args = "" +); + +#endif diff --git a/core/embed/projects/prodtest/main.c b/core/embed/projects/prodtest/main.c index 89e573c744c..372f06ed21d 100644 --- a/core/embed/projects/prodtest/main.c +++ b/core/embed/projects/prodtest/main.c @@ -86,6 +86,10 @@ #include "cmd/prodtest_ble.h" #endif +#ifdef USE_HW_REVISION +#include +#endif + #ifdef TREZOR_MODEL_T2T1 #define MODEL_IDENTIFIER "TREZOR2-" #else @@ -207,6 +211,9 @@ static void drivers_init(void) { #ifdef USE_TROPIC tropic_init(); #endif +#ifdef USE_HW_REVISION + hw_revision_init(); +#endif } #define BACKLIGHT_NORMAL 150 diff --git a/core/embed/util/hw_revision/inc/util/hw_revision.h b/core/embed/util/hw_revision/inc/util/hw_revision.h new file mode 100644 index 00000000000..bccd3220975 --- /dev/null +++ b/core/embed/util/hw_revision/inc/util/hw_revision.h @@ -0,0 +1,28 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#include + +void hw_revision_init(void); + +void hw_revision_deinit(void); + +uint8_t hw_revision_get(void); diff --git a/core/embed/util/hw_revision/stm32/hw_revision.c b/core/embed/util/hw_revision/stm32/hw_revision.c new file mode 100644 index 00000000000..829fc2e9179 --- /dev/null +++ b/core/embed/util/hw_revision/stm32/hw_revision.c @@ -0,0 +1,114 @@ +/* + * This file is part of the Trezor project, https://trezor.io/ + * + * Copyright (c) SatoshiLabs + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifdef KERNEL_MODE + +#include +#include +#include + +#include + +typedef struct { + uint8_t revision; + bool initialized; +} hw_revision_t; + +static hw_revision_t g_hw_revision; + +uint8_t hw_revision_read(void) { + bool rev0 = + GPIO_PIN_SET == HAL_GPIO_ReadPin(HW_REVISION_0_PORT, HW_REVISION_0_PIN); + bool rev1 = + GPIO_PIN_SET == HAL_GPIO_ReadPin(HW_REVISION_1_PORT, HW_REVISION_1_PIN); + bool rev2 = + GPIO_PIN_SET == HAL_GPIO_ReadPin(HW_REVISION_2_PORT, HW_REVISION_2_PIN); + bool rev3 = false; +#ifdef HW_REVISION_3_PIN + rev3 = + GPIO_PIN_SET == HAL_GPIO_ReadPin(HW_REVISION_3_PORT, HW_REVISION_3_PIN); +#endif + + uint8_t revision = 0; + revision |= rev0 ? 1 : 0; + revision |= rev1 ? 2 : 0; + revision |= rev2 ? 4 : 0; + revision |= rev3 ? 8 : 0; + + return revision; +} + +void hw_revision_init(void) { + GPIO_InitTypeDef GPIO_InitStructure = {0}; + + HW_REVISION_0_CLOCK_ENABLE(); + GPIO_InitStructure.Pin = HW_REVISION_0_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = HW_REVISION_PUPD; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + HAL_GPIO_Init(HW_REVISION_0_PORT, &GPIO_InitStructure); + + HW_REVISION_1_CLOCK_ENABLE(); + GPIO_InitStructure.Pin = HW_REVISION_1_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = HW_REVISION_PUPD; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + HAL_GPIO_Init(HW_REVISION_1_PORT, &GPIO_InitStructure); + + HW_REVISION_2_CLOCK_ENABLE(); + GPIO_InitStructure.Pin = HW_REVISION_2_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = HW_REVISION_PUPD; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + HAL_GPIO_Init(HW_REVISION_2_PORT, &GPIO_InitStructure); + +#ifdef HW_REVISION_3_PIN + GPIO_InitStructure.Pin = HW_REVISION_3_PIN; + GPIO_InitStructure.Mode = GPIO_MODE_INPUT; + GPIO_InitStructure.Pull = HW_REVISION_PUPD; + GPIO_InitStructure.Speed = GPIO_SPEED_LOW; + HAL_GPIO_Init(HW_REVISION_3_PORT, &GPIO_InitStructure); +#endif + + memset(&g_hw_revision, 0, sizeof(hw_revision_t)); + g_hw_revision.revision = hw_revision_read(); + g_hw_revision.initialized = true; + + // deinit the GPIOs to save power + HAL_GPIO_DeInit(HW_REVISION_0_PORT, HW_REVISION_0_PIN); + HAL_GPIO_DeInit(HW_REVISION_1_PORT, HW_REVISION_1_PIN); + HAL_GPIO_DeInit(HW_REVISION_2_PORT, HW_REVISION_2_PIN); +#ifdef HW_REVISION_3_PIN + HAL_GPIO_DeInit(HW_REVISION_3_PORT, HW_REVISION_3_PIN); +#endif +} + +void hw_revision_deinit(void) { + memset(&g_hw_revision, 0, sizeof(hw_revision_t)); +} + +uint8_t hw_revision_get(void) { + hw_revision_t *hw_revision = &g_hw_revision; + if (!hw_revision->initialized) { + hw_revision_init(); + } + + return hw_revision->revision; +} + +#endif diff --git a/core/site_scons/models/T3B1/trezor_t3b1_revB.py b/core/site_scons/models/T3B1/trezor_t3b1_revB.py index 15c54182cb6..f307a852b32 100644 --- a/core/site_scons/models/T3B1/trezor_t3b1_revB.py +++ b/core/site_scons/models/T3B1/trezor_t3b1_revB.py @@ -96,6 +96,11 @@ def configure( paths += ["embed/sec/consumption_mask/inc"] defines += [("USE_CONSUMPTION_MASK", "1")] + if "hw_revision" in features_wanted: + defines += [("USE_HW_REVISION", "1")] + paths += ["embed/util/hw_revision/inc"] + sources += ["embed/util/hw_revision/stm32/hw_revision.c"] + defines += [ ("USE_HASH_PROCESSOR", "1"), ("USE_STORAGE_HWKEY", "1"), diff --git a/core/site_scons/models/T3T1/trezor_t3t1_revE.py b/core/site_scons/models/T3T1/trezor_t3t1_revE.py index 8fc439590e9..6ed6184ad0a 100644 --- a/core/site_scons/models/T3T1/trezor_t3t1_revE.py +++ b/core/site_scons/models/T3T1/trezor_t3t1_revE.py @@ -129,6 +129,11 @@ def configure( features_available.append("optiga") defines += [("USE_OPTIGA", "1")] + if "hw_revision" in features_wanted: + defines += [("USE_HW_REVISION", "1")] + paths += ["embed/util/hw_revision/inc"] + sources += ["embed/util/hw_revision/stm32/hw_revision.c"] + defines += [ ("USE_HASH_PROCESSOR", "1"), ("USE_STORAGE_HWKEY", "1"), diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revB.py b/core/site_scons/models/T3W1/trezor_t3w1_revB.py index f4e118b8f2e..6e2dc30805e 100644 --- a/core/site_scons/models/T3W1/trezor_t3w1_revB.py +++ b/core/site_scons/models/T3W1/trezor_t3w1_revB.py @@ -189,6 +189,11 @@ def configure( paths += ["embed/io/usb/inc"] defines += [("USE_USB", "1")] + if "hw_revision" in features_wanted: + defines += [("USE_HW_REVISION", "1")] + paths += ["embed/util/hw_revision/inc"] + sources += ["embed/util/hw_revision/stm32/hw_revision.c"] + defines += [ "FRAMEBUFFER", "DISPLAY_RGBA8888",