feat(nordic): add nrf/ble functionality to T3T2
What changed, and why it matters
This commit adds Bluetooth Low Energy (BLE) support for the Trezor T3T2 hardware model. It introduces new board configuration files, pin mappings, build scripts, and firmware binaries for the Nordic nRF54LS05A BLE radio used in T3T2. There is no indication in the commit that this fixes a security bug; it appears to be a feature addition enabling BLE functionality on a new device variant.
No security action required. Treat as normal feature enablement. If reviewing for supply-chain assurance, verify the two precompiled binary blobs (trezor-ble.bin, trezor-ble-dev.bin) against reproducible build artifacts or source build instructions, and confirm the new BLE attack surface is covered by the existing threat model and pairing/authentication design.
Security signals we found
No strong security signals were identified.
Evidence from the diff
The change extends the existing Trezor BLE gateway (nordic/trezor) to support the T3T2 devkit built around the nRF54LS05B application core. It adds devicetree and Kconfig board definitions, pinctrl mappings for SPI and UART links to the STM32 main SoC, MCUboot partition layout, build script aliases, and prebuilt binary blobs (trezor-ble.bin / trezor-ble-dev.bin). The STM32 side gets corresponding SPI/UART/GPIO pin definitions and the T3T2 model is marked ble_capable=True in trezorlib. The commit message is a feature title with [no changelog].
Changed components
core/embed/models/T3T2 board definitionsnordic/trezor board support for t3t2_dk/nrf54ls05b/cpuappnordic/trezor/trezor-ble application overlays and configsnordic/trezor/scripts/build_sign_flash.shpython/src/trezorlib/_modeldata/T3T2.pyInspect captured patch +526 / −9
diff --git a/core/embed/models/T3T2/boards/devkit.h b/core/embed/models/T3T2/boards/devkit.h
index 56167f14..87e545b1 100644
--- a/core/embed/models/T3T2/boards/devkit.h
+++ b/core/embed/models/T3T2/boards/devkit.h
@@ -110,6 +110,87 @@
#define OPTIGA_PWR_PIN GPIO_PIN_12
#define OPTIGA_PWR_CLK_EN __HAL_RCC_GPIOF_CLK_ENABLE
+// Nordic nRF54LS05A BLE radio.
+// STM32 is the SPI slave (nRF is master) on SPI1; USART1 is the test/SMP link.
+#define NRF_SPI_INSTANCE SPI1
+#define NRF_SPI_CLK_EN __HAL_RCC_SPI1_CLK_ENABLE
+#define NRF_SPI_CLK_DIS __HAL_RCC_SPI1_CLK_DISABLE
+#define NRF_SPI_FORCE_RESET __HAL_RCC_SPI1_FORCE_RESET
+#define NRF_SPI_RELEASE_RESET __HAL_RCC_SPI1_RELEASE_RESET
+#define NRF_SPI_PIN_AF GPIO_AF5_SPI1
+#define NRF_SPI_DMA_RX_REQUEST GPDMA1_REQUEST_SPI1_RX
+#define NRF_SPI_DMA_TX_REQUEST GPDMA1_REQUEST_SPI1_TX
+#define NRF_SPI_INTERRUPT_HANDLER SPI1_IRQHandler
+#define NRF_SPI_IRQN SPI1_IRQn
+// BLE_SCK = PG2
+#define NRF_SPI_SCK_PORT GPIOG
+#define NRF_SPI_SCK_PIN GPIO_PIN_2
+#define NRF_SPI_SCK_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+// BLE_NSS = PE1
+#define NRF_SPI_NSS_PORT GPIOE
+#define NRF_SPI_NSS_PIN GPIO_PIN_1
+#define NRF_SPI_NSS_CLK_EN __HAL_RCC_GPIOE_CLK_ENABLE
+// BLE_MISO = PB4
+#define NRF_SPI_MISO_PORT GPIOB
+#define NRF_SPI_MISO_PIN GPIO_PIN_4
+#define NRF_SPI_MISO_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+// BLE_MOSI = PB5
+#define NRF_SPI_MOSI_PORT GPIOB
+#define NRF_SPI_MOSI_PIN GPIO_PIN_5
+#define NRF_SPI_MOSI_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+
+// SPI_READY: STM32 -> nRF (BLE_GPIO1 = PC13)
+#define NRF_OUT_SPI_READY_PIN GPIO_PIN_13
+#define NRF_OUT_SPI_READY_PORT GPIOC
+#define NRF_OUT_SPI_READY_CLK_ENA __HAL_RCC_GPIOC_CLK_ENABLE
+// SPI_REQUEST: nRF -> STM32, EXTI (BLE_GPIO0 = PE0)
+#define NRF_IN_SPI_REQUEST_PIN GPIO_PIN_0
+#define NRF_IN_SPI_REQUEST_PORT GPIOE
+#define NRF_IN_SPI_REQUEST_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
+#define NRF_EXTI_INTERRUPT_GPIOSEL EXTI_GPIOE
+#define NRF_EXTI_INTERRUPT_LINE EXTI_LINE_0
+#define NRF_EXTI_INTERRUPT_PIN GPIO_PIN_0
+#define NRF_EXTI_INTERRUPT_NUM EXTI0_IRQn
+#define NRF_EXTI_INTERRUPT_HANDLER EXTI0_IRQHandler
+
+// RESERVED: nRF -> STM32 (BLE_GPIO3 = PC7)
+#define NRF_IN_RESERVED_PIN GPIO_PIN_7
+#define NRF_IN_RESERVED_PORT GPIOC
+#define NRF_IN_RESERVED_CLK_ENA __HAL_RCC_GPIOC_CLK_ENABLE
+// RESET: STM32 -> nRF (BLE_RESET = PB7)
+#define NRF_OUT_RESET_PIN GPIO_PIN_7
+#define NRF_OUT_RESET_PORT GPIOB
+#define NRF_OUT_RESET_CLK_ENA __HAL_RCC_GPIOB_CLK_ENABLE
+// STAY_IN_BLD: STM32 -> nRF (BLE_GPIO2 = PE2)
+#define NRF_OUT_STAY_IN_BLD_PIN GPIO_PIN_2
+#define NRF_OUT_STAY_IN_BLD_PORT GPIOE
+#define NRF_OUT_STAY_IN_BLD_CLK_ENA __HAL_RCC_GPIOE_CLK_ENABLE
+
+#define NRF_UART_INSTANCE USART1
+#define NRF_UART_CLK_EN __HAL_RCC_USART1_CLK_ENABLE
+#define NRF_UART_CLK_DIS __HAL_RCC_USART1_CLK_DISABLE
+#define NRF_UART_FORCE_RESET __HAL_RCC_USART1_FORCE_RESET
+#define NRF_UART_RELEASE_RESET __HAL_RCC_USART1_RELEASE_RESET
+#define NRF_UART_INTERRUPT_HANDLER USART1_IRQHandler
+#define NRF_UART_IRQN USART1_IRQn
+#define NRF_UART_PIN_AF GPIO_AF7_USART1
+// BLE_TX = PB6
+#define NRF_UART_TX_PORT GPIOB
+#define NRF_UART_TX_PIN GPIO_PIN_6
+#define NRF_UART_TX_CLK_EN __HAL_RCC_GPIOB_CLK_ENABLE
+// BLE_RX = PG10
+#define NRF_UART_RX_PORT GPIOG
+#define NRF_UART_RX_PIN GPIO_PIN_10
+#define NRF_UART_RX_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+// BLE_RTS = PG12
+#define NRF_UART_RTS_PORT GPIOG
+#define NRF_UART_RTS_PIN GPIO_PIN_12
+#define NRF_UART_RTS_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+// BLE_CTS = PG11
+#define NRF_UART_CTS_PORT GPIOG
+#define NRF_UART_CTS_PIN GPIO_PIN_11
+#define NRF_UART_CTS_CLK_EN __HAL_RCC_GPIOG_CLK_ENABLE
+
// reserved, replace with real pins when available
#define HW_REVISION_PUPD GPIO_PULLUP
#define HW_REVISION_0_PIN GPIO_PIN_6
diff --git a/core/embed/models/T3T2/boards/devkit.toml b/core/embed/models/T3T2/boards/devkit.toml
index 8d2fbce9..e3f74a10 100644
--- a/core/embed/models/T3T2/boards/devkit.toml
+++ b/core/embed/models/T3T2/boards/devkit.toml
@@ -14,3 +14,8 @@ panel = "io/touch_panel_lx154a2422cpt23"
[optiga]
+[ble]
+
+[nrf]
+
+[nrf_auth]
diff --git a/core/embed/models/T3T2/model.toml b/core/embed/models/T3T2/model.toml
index d220dc18..c63f65f1 100644
--- a/core/embed/models/T3T2/model.toml
+++ b/core/embed/models/T3T2/model.toml
@@ -18,6 +18,7 @@ features = [
"secret",
"secure_aes",
"serial_number",
+ "smp",
"framebuffer",
"tamper",
"thp",
diff --git a/core/embed/models/T3T2/model_T3T2.h b/core/embed/models/T3T2/model_T3T2.h
index bf9cbb28..9b7391a6 100644
--- a/core/embed/models/T3T2/model_T3T2.h
+++ b/core/embed/models/T3T2/model_T3T2.h
@@ -32,6 +32,7 @@
#define MODEL_USB_MANUFACTURER "Trezor Company"
#define MODEL_USB_PRODUCT MODEL_FULL_NAME
#define MODEL_HOMESCREEN_MAXSIZE 16384
+#define MODEL_BLE_CODE 7
// todo replace with production keys
#define MODEL_BOARDLOADER_KEYS \
diff --git a/core/embed/models/T3T2/trezor-ble-dev.bin b/core/embed/models/T3T2/trezor-ble-dev.bin
new file mode 100644
index 00000000..67d9ec13
Binary files /dev/null and b/core/embed/models/T3T2/trezor-ble-dev.bin differ
diff --git a/core/embed/models/T3T2/trezor-ble.bin b/core/embed/models/T3T2/trezor-ble.bin
new file mode 100644
index 00000000..67d9ec13
Binary files /dev/null and b/core/embed/models/T3T2/trezor-ble.bin differ
diff --git a/nordic/trezor/README.md b/nordic/trezor/README.md
index 50059714..74d64074 100644
--- a/nordic/trezor/README.md
+++ b/nordic/trezor/README.md
@@ -2,7 +2,10 @@
Welcome to the **Trezor BLE Gateway** project!
This repository contains the source code and instructions to build and flash the
-application.
+application. Two boards are supported, each tied to a specific nRF Connect SDK:
+the `t3w1_revA_nrf52832` board on the regulatory-frozen **NCS v2.9.0**, and the
+`t3t2_dk` (nRF54LS05B) board on the default **NCS v3.3.0** — see
+[Selecting the nRF Connect SDK version](#selecting-the-nrf-connect-sdk-version).
## Table of Contents
@@ -100,8 +103,12 @@ west update
Each board is tied to one SDK — build the matching board for the active manifest:
| Manifest | SDK | Board to build |
+|-------------------|------------|-------------------------------|
+| `west.yml` | NCS v3.3.0 | `t3t2_dk/nrf54ls05b/cpuapp` |
| `west-ncs2.9.yml` | NCS v2.9.0 | `t3w1_revA_nrf52832` |
+The nRF54L (t3t2_dk) is not supported on NCS 2.9, so it can only be built under
+the default manifest.
Notes:
- Only one SDK is checked out at a time, so always rebuild with
@@ -123,9 +130,21 @@ Notes:
### Building and signing using script: debug, production
To be invoked from nix-shell in nordic/trezor folder.
+
+`-b` accepts either a full board target (e.g. `t3t2_dk/nrf54ls05b/cpuapp`) or a
+short model alias that expands to that model's default board: `t3t2` →
+`t3t2_dk/nrf54ls05b/cpuapp`, `t3w1` → `t3w1_revA_nrf52832`.
+```sh
+./scripts/build_sign_flash.sh -b t3w1 -d -s
+./scripts/build_sign_flash.sh -b t3w1 -p -s
+```
+
+For the `t3t2_dk` (nRF54LS05B) board, first make sure the default NCS v3.3.0
+manifest and toolchain are active (see
+[Selecting the nRF Connect SDK version](#selecting-the-nrf-connect-sdk-version)):
```sh
-./scripts/build_sign_flash.sh -b t3w1_revA_nrf52832 -d -s
-./scripts/build_sign_flash.sh -b t3w1_revA_nrf52832 -p -s
+./scripts/build_sign_flash.sh -b t3t2 -d -s
+./scripts/build_sign_flash.sh -b t3t2 -p -s
```
## Alternative build methods
@@ -160,6 +179,13 @@ Build the application for the t3w1_revA_nrf52832 board:
west build ./trezor-ble -b t3w1_revA_nrf52832 --sysbuild -- -DOVERLAY_CONFIG=debug.conf
```
+To build for the `t3t2_dk` (nRF54LS05B) board, switch to the default NCS v3.3.0
+manifest first (see [Selecting the nRF Connect SDK version](#selecting-the-nrf-connect-sdk-version)):
+
+```sh
+west build ./trezor-ble -b t3t2_dk/nrf54ls05b/cpuapp --sysbuild -- -DOVERLAY_CONFIG=debug.conf
+```
+
### Build Radio test application
```sh
diff --git a/nordic/trezor/boards/arm/t3t2_dk/Kconfig.defconfig b/nordic/trezor/boards/arm/t3t2_dk/Kconfig.defconfig
new file mode 100644
index 00000000..d47d7fa3
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/Kconfig.defconfig
@@ -0,0 +1,16 @@
+# Copyright (c) 2025 Nordic Semiconductor ASA
+# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+
+if BOARD_T3T2_DK_NRF54LS05B_CPUAPP
+
+config ROM_START_OFFSET
+ default 0 if PARTITION_MANAGER_ENABLED
+ default 0x800 if BOOTLOADER_MCUBOOT
+
+config SOC_NRF54LX_SKIP_GLITCHDETECTOR_DISABLE
+ default y
+
+config NRF_RRAM_WRITE_BUFFER_SIZE
+ default 8
+
+endif # BOARD_T3T2_DK_NRF54LS05B_CPUAPP
diff --git a/nordic/trezor/boards/arm/t3t2_dk/Kconfig.t3t2_dk b/nordic/trezor/boards/arm/t3t2_dk/Kconfig.t3t2_dk
new file mode 100644
index 00000000..6456bcfa
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/Kconfig.t3t2_dk
@@ -0,0 +1,5 @@
+# Copyright (c) 2025 Nordic Semiconductor ASA
+# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+
+config BOARD_T3T2_DK
+ select SOC_NRF54LS05B_CPUAPP if BOARD_T3T2_DK_NRF54LS05B_CPUAPP
diff --git a/nordic/trezor/boards/arm/t3t2_dk/board.cmake b/nordic/trezor/boards/arm/t3t2_dk/board.cmake
new file mode 100644
index 00000000..ce41e05e
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/board.cmake
@@ -0,0 +1,9 @@
+# Copyright (c) 2025 Nordic Semiconductor ASA
+# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+
+if(CONFIG_SOC_NRF54LS05B_CPUAPP)
+ board_runner_args(jlink "--device=nRF54LS05B_M33" "--speed=4000")
+endif()
+
+include(${ZEPHYR_BASE}/boards/common/nrfutil.board.cmake)
+include(${ZEPHYR_BASE}/boards/common/jlink.board.cmake)
diff --git a/nordic/trezor/boards/arm/t3t2_dk/board.yml b/nordic/trezor/boards/arm/t3t2_dk/board.yml
new file mode 100644
index 00000000..a645d1da
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/board.yml
@@ -0,0 +1,6 @@
+board:
+ name: t3t2_dk
+ full_name: t3t2_dk
+ vendor: trezor
+ socs:
+ - name: nrf54ls05b
diff --git a/nordic/trezor/boards/arm/t3t2_dk/nrf54ls05b_cpuapp_common.dtsi b/nordic/trezor/boards/arm/t3t2_dk/nrf54ls05b_cpuapp_common.dtsi
new file mode 100644
index 00000000..f2a8fc2b
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/nrf54ls05b_cpuapp_common.dtsi
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2025 Nordic Semiconductor ASA
+ *
+ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+ */
+
+#include <nordic/nrf54ls05b_cpuapp.dtsi>
+#include "t3t2_dk_nrf54ls05b-common.dtsi"
+
+/ {
+ chosen {
+ zephyr,console = &uart20;
+ zephyr,shell-uart = &uart20;
+ zephyr,uart-mcumgr = &uart20;
+ zephyr,bt-mon-uart = &uart20;
+ zephyr,bt-c2h-uart = &uart20;
+ zephyr,flash-controller = &rram_controller;
+ zephyr,flash = &cpuapp_rram;
+ zephyr,bt-hci = &bt_hci_sdc;
+ };
+};
+
+&cpuapp_sram {
+ status = "okay";
+};
+
+&hfxo {
+ load-capacitors = "internal";
+ load-capacitance-femtofarad = <15000>;
+};
+
+&vregmain {
+ status = "okay";
+ regulator-initial-mode = <NRF5X_REG_MODE_DCDC>;
+};
+
+&grtc {
+ owned-channels = <0 1 2 3 4 5 6 7 8 9 10 11>;
+ /* Channels 7-11 reserved for Zero Latency IRQs */
+ child-owned-channels = <7 8 9 10 11>;
+ status = "okay";
+};
+
+&cpuapp_rram {
+ partitions {
+ compatible = "fixed-partitions";
+ #address-cells = <1>;
+ #size-cells = <1>;
+ ranges;
+
+ /* nRF54L mcuboot FPROTECT can protect at most 62 KB, and with
+ * SB_CONFIG_PARTITION_MANAGER=n it protects the whole boot
+ * partition. Keep this <= 62 KB (60 KB, 4 KB-aligned). slot0
+ * stays at 0x10000, leaving a small unused gap after mcuboot. */
+ boot_partition: partition@0 {
+ label = "mcuboot";
+ reg = <0x0 DT_SIZE_K(60)>;
+ };
+
+ /* Single-slot mcuboot (see trezor-ble/sysbuild.conf:
+ * SB_CONFIG_MCUBOOT_MODE_SINGLE_APP=y) - no secondary slot is
+ * needed, so slot0 spans the space a slot1 would have used,
+ * matching the t3w1 layout. */
+ slot0_partition: partition@10000 {
+ label = "image-0";
+ reg = <0x10000 DT_SIZE_K(408)>;
+ };
+
+ storage_partition: partition@76000 {
+ label = "storage";
+ reg = <0x76000 DT_SIZE_K(36)>;
+ };
+ };
+};
+
+&uart20 {
+ status = "okay";
+};
+
+&gpio0 {
+ status = "okay";
+};
+
+&gpio1 {
+ status = "okay";
+};
+
+&gpiote20 {
+ status = "okay";
+};
+
+&gpiote30 {
+ status = "okay";
+};
+
+&radio {
+ status = "okay";
+};
+
+&temp {
+ status = "okay";
+};
+
+&clock {
+ status = "okay";
+};
diff --git a/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b-common.dtsi b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b-common.dtsi
new file mode 100644
index 00000000..f65a35e4
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b-common.dtsi
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2025 Trezor Company s.r.o.
+ *
+ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+ */
+
+#include "t3t2_dk_nrf54ls05b-pinctrl.dtsi"
+
+/ {
+ aliases {
+ watchdog0 = &wdt30;
+ };
+};
+
+/* UART link to the STM32 main SoC, shared with the console (as on t3w1).
+ * 1 Mbaud with hardware RTS/CTS flow control to match the STM side. */
+&uart20 {
+ current-speed = <1000000>;
+ hw-flow-control;
+ pinctrl-0 = <&uart20_default>;
+ pinctrl-1 = <&uart20_sleep>;
+ pinctrl-names = "default", "sleep";
+};
diff --git a/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b-pinctrl.dtsi b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b-pinctrl.dtsi
new file mode 100644
index 00000000..f850e834
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b-pinctrl.dtsi
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2025 Trezor Company s.r.o.
+ *
+ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+ */
+
+&pinctrl {
+ /*
+ * UART link to the STM32 main SoC (USART1 on the STM side).
+ * Pin/net mapping per schematic (PICO_MCU / Bluetooth Low Energy Radio):
+ * nRF UART_TX P1.00 -> net BLE_RX (STM RX, PG10)
+ * nRF UART_RX P1.03 <- net BLE_TX (STM TX, PB6)
+ * nRF UART_RTS P1.01 -> net BLE_CTS (STM CTS, PG11)
+ * nRF UART_CTS P1.02 <- net BLE_RTS (STM RTS, PG12)
+ */
+ uart20_default: uart20_default {
+ group1 {
+ psels = <NRF_PSEL(UART_TX, 1, 0)>,
+ <NRF_PSEL(UART_RTS, 1, 1)>;
+ };
+ group2 {
+ psels = <NRF_PSEL(UART_RX, 1, 3)>,
+ <NRF_PSEL(UART_CTS, 1, 2)>;
+ bias-pull-up;
+ };
+ };
+
+ uart20_sleep: uart20_sleep {
+ group1 {
+ psels = <NRF_PSEL(UART_TX, 1, 0)>,
+ <NRF_PSEL(UART_RX, 1, 3)>,
+ <NRF_PSEL(UART_RTS, 1, 1)>,
+ <NRF_PSEL(UART_CTS, 1, 2)>;
+ low-power-enable;
+ };
+ };
+
+ /*
+ * SPI master to the STM32 main SoC (nRF is SPI master, STM is slave).
+ * nRF SPIM_SCK P1.08 -> net BLE_SCK (STM PG2)
+ * nRF SPIM_MOSI P1.06 -> net BLE_MOSI (STM PB5)
+ * nRF SPIM_MISO P1.07 <- net BLE_MISO (STM PB4)
+ * CS (BLE_NSS, P1.05) is driven as a GPIO, see cs-gpios on &spi21.
+ */
+ spi_default: spi_default {
+ group1 {
+ psels = <NRF_PSEL(SPIM_SCK, 1, 8)>,
+ <NRF_PSEL(SPIM_MOSI, 1, 6)>,
+ <NRF_PSEL(SPIM_MISO, 1, 7)>;
+ };
+ };
+
+ spi_sleep: spi_sleep {
+ group1 {
+ psels = <NRF_PSEL(SPIM_SCK, 1, 8)>,
+ <NRF_PSEL(SPIM_MOSI, 1, 6)>,
+ <NRF_PSEL(SPIM_MISO, 1, 7)>;
+ low-power-enable;
+ };
+ };
+};
diff --git a/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b_cpuapp.dts b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b_cpuapp.dts
new file mode 100644
index 00000000..b91f8af7
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b_cpuapp.dts
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2025 Trezor Company s.r.o.
+ *
+ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+ */
+
+/dts-v1/;
+
+#include "nrf54ls05b_cpuapp_common.dtsi"
+
+/ {
+ compatible = "trezor,t3t2_dk_nrf54ls05b-cpuapp";
+ model = "T3T2 DK NRF54LS05B Application MCU";
+
+ chosen {
+ zephyr,code-partition = &slot0_partition;
+ zephyr,sram = &cpuapp_sram;
+ zephyr,bt-hci = &bt_hci_sdc;
+ };
+
+ /*
+ * GPIO handshake / control signals to the STM32 main SoC.
+ * These are defined at board level (not in the app overlay) so the
+ * separate MCUboot image sees them too. Net mapping per schematic:
+ * output_1 spi-request BLE_GPIO0 P1.18 (nRF -> STM, STM PE0)
+ * input_1 spi-ready BLE_GPIO1 P1.19 (STM -> nRF, STM PC13)
+ * input_0 stay-in-bootloader BLE_GPIO2 P1.20 (STM -> nRF, STM PE2)
+ * output_0 reserved-output BLE_GPIO3 P1.21 (nRF -> STM, STM PC7)
+ */
+ outputs {
+ compatible = "gpio-leds";
+ output_0: output_0 {
+ gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
+ };
+ output_1: output_1 {
+ gpios = <&gpio1 18 GPIO_ACTIVE_HIGH>;
+ };
+ };
+
+ inputs {
+ compatible = "gpio-keys";
+ input_0: input_0 {
+ gpios = <&gpio1 20 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
+ };
+ input_1: input_1 {
+ gpios = <&gpio1 19 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
+ };
+ };
+
+ aliases {
+ /* MCUboot serial-recovery entry is the STM-driven stay-in-bootloader
+ * line; there is no dedicated recovery button (as on t3w1). */
+ mcuboot-button0 = &input_0;
+ spi-ready = &input_1;
+ spi-request = &output_1;
+ stay-in-bootloader = &input_0;
+ reserved-output = &output_0;
+ };
+};
+
+&bt_hci_sdc {
+ status = "okay";
+};
+
+&bt_hci_controller {
+ status = "disabled";
+};
+
+&spi21 {
+ compatible = "nordic,nrf-spim";
+ status = "okay";
+ pinctrl-0 = <&spi_default>;
+ pinctrl-1 = <&spi_sleep>;
+ pinctrl-names = "default", "sleep";
+ /* CS = BLE_NSS, P1.05 */
+ cs-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;
+ trezor_spi_dev: spi-dev-a@0 {
+ reg = <0>;
+ };
+};
diff --git a/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b_cpuapp.yaml b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b_cpuapp.yaml
new file mode 100644
index 00000000..7ef79399
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b_cpuapp.yaml
@@ -0,0 +1,21 @@
+# Copyright (c) 2025 Nordic Semiconductor ASA
+# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+
+identifier: t3t2_dk/nrf54ls05b/cpuapp
+name: t3t2-dk-Application
+type: mcu
+arch: arm
+toolchain:
+ - gnuarmemb
+ - zephyr
+sysbuild: true
+ram: 96
+flash: 444
+supported:
+ - adc
+ - counter
+ - gpio
+ - i2c
+ - pwm
+ - spi
+ - watchdog
diff --git a/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b_cpuapp_defconfig b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b_cpuapp_defconfig
new file mode 100644
index 00000000..3084bd1f
--- /dev/null
+++ b/nordic/trezor/boards/arm/t3t2_dk/t3t2_dk_nrf54ls05b_cpuapp_defconfig
@@ -0,0 +1,17 @@
+# Copyright (c) 2025 Nordic Semiconductor ASA
+# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+
+# Enable UART driver
+CONFIG_SERIAL=y
+
+# Enable console
+CONFIG_CONSOLE=y
+CONFIG_UART_CONSOLE=y
+
+# Enable GPIO
+CONFIG_GPIO=y
+
+# Enable hardware stack protection
+CONFIG_HW_STACK_PROTECTION=y
+
+CONFIG_MODEL_IDENTIFIER=844378964
diff --git a/nordic/trezor/scripts/build_sign_flash.sh b/nordic/trezor/scripts/build_sign_flash.sh
index 89837b9c..af7832e7 100755
--- a/nordic/trezor/scripts/build_sign_flash.sh
+++ b/nordic/trezor/scripts/build_sign_flash.sh
@@ -74,7 +74,8 @@ usage() {
echo "$0 [-b board_name] [-a app_dir] [-p] [-d] [-r] [-s] [-f]"
cat <<END
Parameters:
- -b board_name: build with board name as param
+ -b board: full board target (e.g. t3t2_dk/nrf54ls05b/cpuapp) or a model
+ alias (t3t2, t3w1) that expands to that model's default board
-a app_dir: specify application directory (default: trezor-ble)
-p: production build
-d: use debug overlay when building
@@ -117,14 +118,15 @@ parse_partition_info() {
}
# Verify the active nRF Connect SDK / toolchain match the target board before
-# building. Each board is pinned to one SDK: t3w1 -> NCS 2.9 (west-ncs2.9.yml).
-# Building with the wrong SDK or toolchain active produces confusing,
-# hard-to-diagnose failures.
+# building. Each board is pinned to one SDK: t3w1 -> NCS 2.9 (west-ncs2.9.yml),
+# t3t2_dk/nRF54L -> NCS 3.3 (west.yml, default). Building with the wrong SDK or
+# toolchain active produces confusing, hard-to-diagnose failures.
verify_environment() {
local board="$1"
local required_major expected_manifest
case "$board" in
t3w1*) required_major=2; expected_manifest="west-ncs2.9.yml" ;;
+ t3t2_dk*) required_major=3; expected_manifest="west.yml" ;;
*)
echo "verify: board '$board' has no known SDK pairing; skipping SDK/toolchain check."
return 0
@@ -195,6 +197,19 @@ Install it with:
echo "verify: OK - board '$board' <-> NCS v${sdk_version}, toolchain ${NCS_TOOLCHAIN_VERSION:-<pre-set>} (manifest ${expected_manifest})."
}
+# Resolve a friendly board alias to its canonical Zephyr board target. Lets you
+# pass just a model name (e.g. "t3t2") and get that model's default board, while
+# a full board target (anything containing '/', e.g. "t3t2_dk/nrf54ls05b/cpuapp")
+# or any unrecognised value passes through unchanged - so a specific board can
+# always be selected explicitly.
+resolve_board() {
+ case "$1" in
+ t3t2) echo "t3t2_dk/nrf54ls05b/cpuapp" ;;
+ t3w1) echo "t3w1_revA_nrf52832" ;;
+ *) echo "$1" ;;
+ esac
+}
+
while getopts ${OPTSTRING} opt; do
case ${opt} in
b)
@@ -229,6 +244,11 @@ while getopts ${OPTSTRING} opt; do
done
if [ -n "$BOARD" ]; then
+ resolved_board=$(resolve_board "$BOARD")
+ if [ "$resolved_board" != "$BOARD" ]; then
+ echo "board: alias '$BOARD' -> '$resolved_board'"
+ BOARD="$resolved_board"
+ fi
verify_environment "$BOARD"
run_under_ncs_subshell \
"west build ./$APP_DIR -b $BOARD --sysbuild $PRISTINE $DEBUG $PRODUCTION"
diff --git a/nordic/trezor/trezor-ble/boards/t3t2_dk_nrf54ls05b_cpuapp.conf b/nordic/trezor/trezor-ble/boards/t3t2_dk_nrf54ls05b_cpuapp.conf
new file mode 100644
index 00000000..d43775ab
--- /dev/null
+++ b/nordic/trezor/trezor-ble/boards/t3t2_dk_nrf54ls05b_cpuapp.conf
@@ -0,0 +1,14 @@
+#
+# Copyright (c) 2025 Trezor Company s.r.o.
+#
+# SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+#
+# Board-specific Kconfig for the t3t2_dk (nRF54LS05B) board, auto-merged by
+# Zephyr for this board only.
+
+# Device Information Service identity. NCS 3.3 (Zephyr 4.x) renamed the DIS
+# manufacturer/model options; use the new symbol names here (the deprecated
+# BT_DIS_MANUF/BT_DIS_MODEL would emit deprecation warnings on 3.3).
+CONFIG_BT_DIS_MANUF_NAME_STR="Trezor Company s.r.o."
+# TODO: set to the actual product/model name for this board.
+CONFIG_BT_DIS_MODEL_NUMBER_STR="Trezor T3T2"
diff --git a/nordic/trezor/trezor-ble/boards/t3t2_dk_nrf54ls05b_cpuapp.overlay b/nordic/trezor/trezor-ble/boards/t3t2_dk_nrf54ls05b_cpuapp.overlay
new file mode 100644
index 00000000..310eb09f
--- /dev/null
+++ b/nordic/trezor/trezor-ble/boards/t3t2_dk_nrf54ls05b_cpuapp.overlay
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2025 Trezor Company s.r.o.
+ *
+ * SPDX-License-Identifier: LicenseRef-Nordic-5-Clause
+ *
+ * trezor-ble application devicetree glue for the t3t2_dk board.
+ *
+ * The UART link, SPI master (incl. trezor_spi_dev / CS) and the GPIO
+ * handshake signals (spi-ready, spi-request, stay-in-bootloader,
+ * reserved-output) are defined at board level in
+ * boards/arm/t3t2_dk/, so they are shared with the MCUboot
+ * image. This overlay only binds the app's logical contract to them, the
+ * same way the t3w1 app overlay does.
+ */
+
+/ {
+ chosen {
+ /* Shares uart20 with the console, as t3w1 shares uart0. */
+ trezor,trz-uart = &uart20;
+ };
+
+ aliases {
+ spi-master = &spi21;
+ };
+};
diff --git a/nordic/trezor/trezor-ble/boards/t3w1_revA_nrf52832.conf b/nordic/trezor/trezor-ble/boards/t3w1_revA_nrf52832.conf
index e0d2655e..c22274c4 100644
--- a/nordic/trezor/trezor-ble/boards/t3w1_revA_nrf52832.conf
+++ b/nordic/trezor/trezor-ble/boards/t3w1_revA_nrf52832.conf
@@ -15,5 +15,5 @@ CONFIG_SOC_NRF52832_ALLOW_SPIM_DESPITE_PAN_58=y
# Device Information Service identity. NCS 2.9 (Zephyr 3.7) uses these symbol
# names; they are deprecated/renamed on 3.3, so they live in the board conf.
-CONFIG_BT_DIS_MANUF="Trezor Company s.r.o"
+CONFIG_BT_DIS_MANUF="Trezor Company s.r.o."
CONFIG_BT_DIS_MODEL="Trezor Safe 7"
diff --git a/python/src/trezorlib/_modeldata/T3T2.py b/python/src/trezorlib/_modeldata/T3T2.py
index f80d1bd5..186b64bd 100644
--- a/python/src/trezorlib/_modeldata/T3T2.py
+++ b/python/src/trezorlib/_modeldata/T3T2.py
@@ -32,7 +32,7 @@ MODEL = ModelData(
aliases=(),
model_class=ModelClass.CORE,
layout=Layout.DELIZIA,
- ble_capable=False,
+ ble_capable=True,
prod_keys=KeySet(
production=True,
# TODO replace with production keys (matches firmware/models.py today)
Why this scored 15/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.