diff --git a/core/SConscript.prodtest b/core/SConscript.prodtest
index dd9e46e312..d5f6106cb9 100644
--- a/core/SConscript.prodtest
+++ b/core/SConscript.prodtest
@@ -109,6 +109,7 @@ SOURCE_PRODTEST = [
'embed/projects/prodtest/cmd/prodtest_haptic.c',
'embed/projects/prodtest/cmd/prodtest_help.c',
'embed/projects/prodtest/cmd/prodtest_nfc.c',
+ 'embed/projects/prodtest/cmd/prodtest_nrf.c',
'embed/projects/prodtest/cmd/prodtest_optiga.c',
'embed/projects/prodtest/cmd/prodtest_otp_batch.c',
'embed/projects/prodtest/cmd/prodtest_otp_variant.c',
diff --git a/core/embed/io/nrf/crc8.h b/core/embed/io/nrf/crc8.h
index f26e33730a..e8df6d64ec 100644
--- a/core/embed/io/nrf/crc8.h
+++ b/core/embed/io/nrf/crc8.h
@@ -17,12 +17,9 @@
* along with this program. If not, see .
*/
-#ifndef TREZORHAL_NRF_CRC8_H
-#define TREZORHAL_NRF_CRC8_H
+#pragma once
#include
uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial,
uint8_t initial_value, bool reversed);
-
-#endif
diff --git a/core/embed/io/nrf/inc/io/nrf.h b/core/embed/io/nrf/inc/io/nrf.h
index 73c4c04439..c903362744 100644
--- a/core/embed/io/nrf/inc/io/nrf.h
+++ b/core/embed/io/nrf/inc/io/nrf.h
@@ -17,8 +17,7 @@
* along with this program. If not, see .
*/
-#ifndef TREZORHAL_NRF_H
-#define TREZORHAL_NRF_H
+#pragma once
#include
@@ -28,6 +27,8 @@
typedef enum {
NRF_SERVICE_BLE = 0,
NRF_SERVICE_BLE_MANAGER = 1,
+ NRF_SERVICE_MANAGEMENT = 2,
+ NRF_SERVICE_PRODTEST = 3,
NRF_SERVICE_CNT // Number of services
} nrf_service_id_t;
@@ -39,6 +40,18 @@ typedef enum {
NRF_STATUS_ABORTED = 3, // Packet was aborted
} nrf_status_t;
+typedef struct {
+ uint8_t version_major;
+ uint8_t version_minor;
+ uint8_t version_patch;
+ uint8_t version_tweak;
+
+ bool in_trz_ready;
+ bool in_stay_in_bootloader;
+ bool out_nrf_ready;
+ bool out_reserved;
+} nrf_info_t;
+
typedef void (*nrf_rx_callback_t)(const uint8_t *data, uint32_t len);
typedef void (*nrf_tx_callback_t)(nrf_status_t status, void *context);
@@ -74,4 +87,23 @@ int32_t nrf_send_msg(nrf_service_id_t service, const uint8_t *data,
// the message is being sent, it will be sent. The callback will not be called.
bool nrf_abort_msg(int32_t id);
-#endif
+// Reads version and other info from NRF application.
+// Blocking function.
+bool nrf_get_info(nrf_info_t *info);
+
+// TEST only functions
+
+// Test SPI communication with NRF
+bool nrf_test_spi_comm(void);
+
+// Test UART communication with NRF
+bool nrf_test_uart_comm(void);
+
+// Test reboot to bootloader
+bool nrf_test_reboot_to_bootloader(void);
+
+bool nrf_test_gpio_trz_ready(void);
+
+bool nrf_test_gpio_stay_in_bld(void);
+
+bool nrf_test_gpio_reserved(void);
diff --git a/core/embed/io/nrf/nrf_internal.h b/core/embed/io/nrf/nrf_internal.h
index c6bdc2b1b5..870d621ac8 100644
--- a/core/embed/io/nrf/nrf_internal.h
+++ b/core/embed/io/nrf/nrf_internal.h
@@ -17,11 +17,19 @@
* along with this program. If not, see .
*/
-#ifndef TREZORHAL_NRF_INTERNAL_H
-#define TREZORHAL_NRF_INTERNAL_H
+#pragma once
#include
+typedef enum {
+ MGMT_CMD_SYSTEM_OFF = 0x00,
+ MGMT_CMD_INFO = 0x01,
+} management_cmd_t;
+
+typedef enum {
+ MGMT_RESP_INFO = 0,
+} management_resp_t;
+
void nrf_dfu_comm_send(const uint8_t *data, uint32_t len);
uint32_t nrf_dfu_comm_receive(uint8_t *data, uint32_t len);
@@ -36,4 +44,5 @@ bool nrf_reboot_to_bootloader(void);
void nrf_signal_running(void);
void nrf_signal_off(void);
-#endif
+void nrf_stay_in_bootloader(bool set);
+bool nrf_in_reserved_gpio(void);
diff --git a/core/embed/io/nrf/stm32u5/nrf.c b/core/embed/io/nrf/stm32u5/nrf.c
index bf22ab84fd..ccdc750c63 100644
--- a/core/embed/io/nrf/stm32u5/nrf.c
+++ b/core/embed/io/nrf/stm32u5/nrf.c
@@ -83,6 +83,8 @@ typedef struct {
nrf_rx_callback_t service_listeners[NRF_SERVICE_CNT];
+ bool info_valid;
+ nrf_info_t info;
} nrf_driver_t;
static nrf_driver_t g_nrf_driver = {0};
@@ -142,6 +144,22 @@ static void nrf_stop(void) {
irq_unlock(key);
}
+void nrf_management_rx_cb(const uint8_t *data, uint32_t len) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return;
+ }
+
+ switch (data[0]) {
+ case MGMT_RESP_INFO:
+ drv->info_valid = true;
+ memcpy(&drv->info, &data[1], sizeof(drv->info));
+ break;
+ default:
+ break;
+ }
+}
+
void nrf_init(void) {
nrf_driver_t *drv = &g_nrf_driver;
@@ -307,6 +325,8 @@ void nrf_init(void) {
drv->tx_request_id = -1;
drv->initialized = true;
+ nrf_register_listener(NRF_SERVICE_MANAGEMENT, nrf_management_rx_cb);
+
nrf_start();
}
@@ -694,11 +714,25 @@ bool nrf_reboot_to_bootloader(void) {
HAL_GPIO_WritePin(NRF_OUT_RESET_PORT, NRF_OUT_RESET_PIN, GPIO_PIN_SET);
- systick_delay_ms(1000);
+ systick_delay_ms(100);
return true;
}
+void nrf_stay_in_bootloader(bool set) {
+ if (set) {
+ HAL_GPIO_WritePin(NRF_OUT_STAY_IN_BLD_PORT, NRF_OUT_STAY_IN_BLD_PIN,
+ GPIO_PIN_SET);
+ } else {
+ HAL_GPIO_WritePin(NRF_OUT_STAY_IN_BLD_PORT, NRF_OUT_STAY_IN_BLD_PIN,
+ GPIO_PIN_RESET);
+ }
+}
+
+bool nrf_in_reserved_gpio(void) {
+ return HAL_GPIO_ReadPin(NRF_IN_GPIO0_PORT, NRF_IN_GPIO0_PIN) != 0;
+}
+
bool nrf_reboot(void) {
HAL_GPIO_WritePin(NRF_OUT_RESET_PORT, NRF_OUT_RESET_PIN, GPIO_PIN_RESET);
HAL_GPIO_WritePin(NRF_OUT_STAY_IN_BLD_PORT, NRF_OUT_STAY_IN_BLD_PIN,
@@ -735,6 +769,31 @@ bool nrf_is_running(void) {
return drv->comm_running;
}
+bool nrf_get_info(nrf_info_t *info) {
+ nrf_driver_t *drv = &g_nrf_driver;
+ if (!drv->initialized) {
+ return false;
+ }
+
+ drv->info_valid = false;
+
+ uint8_t data[1] = {MGMT_CMD_INFO};
+ if (!nrf_send_msg(NRF_SERVICE_MANAGEMENT, data, 1, NULL, NULL)) {
+ return false;
+ }
+
+ uint32_t timeout = ticks_timeout(100);
+
+ while (!ticks_expired(timeout)) {
+ if (drv->info_valid) {
+ memcpy(info, &drv->info, sizeof(nrf_info_t));
+ return true;
+ }
+ }
+
+ return false;
+}
+
void nrf_set_dfu_mode(void) {
nrf_driver_t *drv = &g_nrf_driver;
diff --git a/core/embed/io/nrf/stm32u5/nrf_test.c b/core/embed/io/nrf/stm32u5/nrf_test.c
new file mode 100644
index 0000000000..ff5ea5e54a
--- /dev/null
+++ b/core/embed/io/nrf/stm32u5/nrf_test.c
@@ -0,0 +1,249 @@
+/*
+ * 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 .
+ */
+
+#include
+#ifdef KERNEL_MODE
+
+#include
+#include
+
+#include
+
+#include "../nrf_internal.h"
+
+typedef enum {
+ PRODTEST_CMD_SPI_DATA = 0x00,
+ PRODTEST_CMD_UART_DATA = 0x01,
+ PRODTEST_CMD_SET_OUTPUT = 0x02,
+} prodtest_cmd_t;
+
+typedef enum {
+ PRODTEST_RESP_SPI = 0x00,
+ PRODTEST_RESP_UART = 0x01,
+} prodtest_resp_t;
+
+typedef struct {
+ bool answered_spi;
+ bool answered_uart;
+
+} nrf_test_t;
+
+static nrf_test_t g_nrf_test;
+
+void nrf_test_cb(const uint8_t *data, uint32_t len) {
+ switch (data[0]) {
+ case PRODTEST_RESP_SPI:
+ g_nrf_test.answered_spi = true;
+ break;
+ case PRODTEST_RESP_UART:
+ g_nrf_test.answered_uart = true;
+ break;
+ default:
+ break;
+ }
+}
+
+bool nrf_test_spi_comm(void) {
+ nrf_register_listener(NRF_SERVICE_PRODTEST, nrf_test_cb);
+
+ g_nrf_test.answered_spi = false;
+
+ uint8_t data[1] = {PRODTEST_CMD_SPI_DATA};
+
+ if (!nrf_send_msg(NRF_SERVICE_PRODTEST, data, 1, NULL, NULL)) {
+ return false;
+ }
+
+ uint32_t timeout = ticks_timeout(100);
+
+ while (!ticks_expired(timeout)) {
+ if (g_nrf_test.answered_spi) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool nrf_test_uart_comm(void) {
+ nrf_register_listener(NRF_SERVICE_PRODTEST, nrf_test_cb);
+
+ g_nrf_test.answered_uart = false;
+
+ uint8_t data[1] = {PRODTEST_CMD_UART_DATA};
+
+ if (!nrf_send_msg(NRF_SERVICE_PRODTEST, data, 1, NULL, NULL)) {
+ return false;
+ }
+
+ uint32_t timeout = ticks_timeout(100);
+
+ while (!ticks_expired(timeout)) {
+ if (g_nrf_test.answered_uart) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool nrf_test_reboot_to_bootloader(void) {
+ bool result = false;
+
+ if (!nrf_firmware_running()) {
+ return false;
+ }
+
+ if (!nrf_reboot_to_bootloader()) {
+ return false;
+ }
+
+ uint32_t timeout = ticks_timeout(10);
+
+ while (!ticks_expired(timeout)) {
+ if (!nrf_firmware_running()) {
+ result = true;
+ break;
+ }
+ }
+
+ systick_delay_ms(10);
+
+ // todo test UART communication with MCUboot
+
+ if (!nrf_reboot()) {
+ return false;
+ }
+
+ timeout = ticks_timeout(1000);
+ while (!ticks_expired(timeout)) {
+ if (nrf_firmware_running()) {
+ return result;
+ }
+ }
+
+ return false;
+}
+
+bool nrf_test_gpio_trz_ready(void) {
+ bool result = false;
+ nrf_signal_running();
+ systick_delay_ms(10);
+
+ nrf_info_t info = {0};
+ if (!nrf_get_info(&info)) {
+ result = false;
+ goto cleanup;
+ }
+
+ if (!info.in_trz_ready) {
+ result = false;
+ goto cleanup;
+ }
+
+ nrf_signal_off();
+ systick_delay_ms(10);
+ if (!nrf_get_info(&info)) {
+ result = false;
+ goto cleanup;
+ }
+
+ if (info.in_trz_ready) {
+ result = false;
+ goto cleanup;
+ }
+
+ result = true;
+
+cleanup:
+ nrf_signal_running();
+ return result;
+}
+
+bool nrf_test_gpio_stay_in_bld(void) {
+ bool result = false;
+ nrf_stay_in_bootloader(false);
+ systick_delay_ms(10);
+
+ nrf_info_t info = {0};
+ if (!nrf_get_info(&info)) {
+ result = false;
+ goto cleanup;
+ }
+
+ if (info.in_stay_in_bootloader) {
+ result = false;
+ goto cleanup;
+ }
+
+ nrf_stay_in_bootloader(true);
+ systick_delay_ms(10);
+ if (!nrf_get_info(&info)) {
+ result = false;
+ goto cleanup;
+ }
+
+ if (!info.in_stay_in_bootloader) {
+ result = false;
+ goto cleanup;
+ }
+
+ result = true;
+
+cleanup:
+ nrf_stay_in_bootloader(false);
+ return result;
+}
+
+bool nrf_test_gpio_reserved(void) {
+ bool result = false;
+ uint8_t data[2] = {PRODTEST_CMD_SET_OUTPUT, 0};
+ if (!nrf_send_msg(NRF_SERVICE_PRODTEST, data, sizeof(data), NULL, NULL)) {
+ return false;
+ }
+
+ systick_delay_ms(10);
+
+ if (nrf_in_reserved_gpio()) {
+ result = false;
+ goto cleanup;
+ }
+
+ data[1] = 1;
+ if (!nrf_send_msg(NRF_SERVICE_PRODTEST, data, sizeof(data), NULL, NULL)) {
+ result = false;
+ goto cleanup;
+ }
+
+ systick_delay_ms(10);
+
+ if (!nrf_in_reserved_gpio()) {
+ result = false;
+ goto cleanup;
+ }
+
+ result = true;
+
+cleanup:
+ data[1] = 0;
+ nrf_send_msg(NRF_SERVICE_PRODTEST, data, sizeof(data), NULL, NULL);
+ return result;
+}
+
+#endif
diff --git a/core/embed/projects/prodtest/README.md b/core/embed/projects/prodtest/README.md
index eb614133b8..4026a03fb6 100644
--- a/core/embed/projects/prodtest/README.md
+++ b/core/embed/projects/prodtest/README.md
@@ -268,6 +268,30 @@ haptic-test 3000
OK
```
+### nrf-communication
+Tests the internal communication between the main MCU and NRF MCU. The command returns `OK` if the communication is successful.
+
+Example:
+```
+nrf-communication
+# Testing SPI communication...
+# Testing UART communication...
+# Testing reboot to bootloader...
+# Testing GPIO TRZ ready...
+# Testing GPIO stay in bootloader...
+# Testing GPIO reserved...
+OK
+```
+
+### nrf-version
+Retrieves the version of the NRF52 MCU. The command returns `OK` followed by the version in the format `...`.
+
+Example:
+```
+nrf-version
+OK 0.1.2.3
+```
+
### touch-draw
Starts a drawing canvas, where user can draw with finger on pen. Canvas is exited by sending CTRL+C command.
```
diff --git a/core/embed/projects/prodtest/cmd/prodtest_nrf.c b/core/embed/projects/prodtest/cmd/prodtest_nrf.c
new file mode 100644
index 0000000000..32542fa019
--- /dev/null
+++ b/core/embed/projects/prodtest/cmd/prodtest_nrf.c
@@ -0,0 +1,94 @@
+/*
+ * 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_BLE
+
+#include
+
+#include
+#include
+
+static void prodtest_nrf_communication(cli_t* cli) {
+ cli_trace(cli, "Testing SPI communication...");
+ if (!nrf_test_spi_comm()) {
+ cli_error(cli, CLI_ERROR, "SPI communication failed.");
+ return;
+ }
+
+ cli_trace(cli, "Testing UART communication...");
+ if (!nrf_test_uart_comm()) {
+ cli_error(cli, CLI_ERROR, "UART communication failed.");
+ return;
+ }
+
+ cli_trace(cli, "Testing reboot to bootloader...");
+ if (!nrf_test_reboot_to_bootloader()) {
+ cli_error(cli, CLI_ERROR, "Reboot to bootloader failed.");
+ return;
+ }
+
+ cli_trace(cli, "Testing GPIO TRZ ready...");
+ if (!nrf_test_gpio_trz_ready()) {
+ cli_error(cli, CLI_ERROR, "TRZ ready GPIO failed.");
+ return;
+ }
+
+ cli_trace(cli, "Testing GPIO stay in bootloader...");
+ if (!nrf_test_gpio_stay_in_bld()) {
+ cli_error(cli, CLI_ERROR, "Stay in bootloader GPIO failed.");
+ return;
+ }
+
+ cli_trace(cli, "Testing GPIO reserved...");
+ if (!nrf_test_gpio_reserved()) {
+ cli_error(cli, CLI_ERROR, "Reserved GPIO failed.");
+ return;
+ }
+
+ cli_ok(cli, "");
+}
+
+static void prodtest_nrf_version(cli_t* cli) {
+ nrf_info_t info = {0};
+ if (!nrf_get_info(&info)) {
+ cli_error(cli, CLI_ERROR, "Could not read version.");
+ return;
+ }
+
+ cli_ok(cli, "%d.%d.%d.%d", info.version_major, info.version_minor,
+ info.version_patch, info.version_tweak);
+}
+
+// clang-format off
+
+PRODTEST_CLI_CMD(
+ .name = "nrf-communication",
+ .func = prodtest_nrf_communication,
+ .info = "Tests NRF communication and GPIOs",
+ .args = ""
+);
+
+PRODTEST_CLI_CMD(
+ .name = "nrf-version",
+ .func = prodtest_nrf_version,
+ .info = "Reads NRF firmware version",
+ .args = ""
+);
+
+#endif
diff --git a/core/site_scons/models/T3W1/trezor_t3w1_revB.py b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
index 31f3d08867..f4e118b8f2 100644
--- a/core/site_scons/models/T3W1/trezor_t3w1_revB.py
+++ b/core/site_scons/models/T3W1/trezor_t3w1_revB.py
@@ -84,6 +84,7 @@ def configure(
features_available.append("ble")
defines += [("USE_BLE", "1")]
sources += ["embed/io/nrf/stm32u5/nrf.c"]
+ sources += ["embed/io/nrf/stm32u5/nrf_test.c"]
sources += ["embed/io/nrf/crc8.c"]
paths += ["embed/io/nrf/inc"]
sources += [
diff --git a/nordic/trezor/boards/arm/t3w1_revA_nrf52832/t3w1_revA_nrf52832.dts b/nordic/trezor/boards/arm/t3w1_revA_nrf52832/t3w1_revA_nrf52832.dts
index bc700d196e..23fa72dcd7 100644
--- a/nordic/trezor/boards/arm/t3w1_revA_nrf52832/t3w1_revA_nrf52832.dts
+++ b/nordic/trezor/boards/arm/t3w1_revA_nrf52832/t3w1_revA_nrf52832.dts
@@ -28,11 +28,11 @@
compatible = "gpio-leds";
led0: led_0 {
gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>;
- label = "Green LED 0";
+ label = "Reserved output";
};
led1: led_1 {
gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;
- label = "Green LED 1";
+ label = "NRF ready";
};
};
@@ -40,7 +40,7 @@
compatible = "gpio-keys";
button0: button_0 {
gpios = <&gpio0 14 (GPIO_PULL_DOWN | GPIO_ACTIVE_HIGH)>;
- label = "Push button switch 0";
+ label = "Stay in bootloader";
zephyr,code = ;
};
trezor_ready: trezor_ready {
diff --git a/nordic/trezor/trezor-ble/CMakeLists.txt b/nordic/trezor/trezor-ble/CMakeLists.txt
index 81e6f3e8c4..45b0e9dc90 100644
--- a/nordic/trezor/trezor-ble/CMakeLists.txt
+++ b/nordic/trezor/trezor-ble/CMakeLists.txt
@@ -18,7 +18,8 @@ target_sources(app PRIVATE
src/ble/bonds.c
src/ble/pairing.c
src/ble/ble.c
- src/power_management/power_management.c
+ src/management/management.c
+ src/prodtest/prodtest.c
src/trz_comm/uart.c
src/trz_comm/spi.c
src/trz_comm/trz_comm.c
@@ -28,7 +29,8 @@ target_sources(app PRIVATE
include_directories(src/signals/inc)
include_directories(src/trz_comm/inc)
include_directories(src/ble/inc)
-include_directories(src/power_management/inc)
+include_directories(src/management/inc)
+include_directories(src/prodtest/inc)
# NORDIC SDK APP END
diff --git a/nordic/trezor/trezor-ble/src/ble/pairing.c b/nordic/trezor/trezor-ble/src/ble/pairing.c
index 91c034b3fc..1c79898340 100644
--- a/nordic/trezor/trezor-ble/src/ble/pairing.c
+++ b/nordic/trezor/trezor-ble/src/ble/pairing.c
@@ -54,9 +54,9 @@ void auth_passkey_confirm(struct bt_conn *conn, unsigned int passkey) {
uint8_t passkey_str[6];
passkey_to_str(passkey_str, passkey);
- management_send_pairing_request_event(passkey_str, 6);
+ ble_management_send_pairing_request_event(passkey_str, 6);
- management_send_status_event();
+ ble_management_send_status_event();
}
void pairing_auth_cancel(struct bt_conn *conn) {
@@ -66,8 +66,8 @@ void pairing_auth_cancel(struct bt_conn *conn) {
connection_disconnect();
- management_send_pairing_cancelled_event();
- management_send_status_event();
+ ble_management_send_pairing_cancelled_event();
+ ble_management_send_status_event();
LOG_INF("Pairing cancelled: %s", addr);
}
diff --git a/nordic/trezor/trezor-ble/src/main.c b/nordic/trezor/trezor-ble/src/main.c
index 10ee4e1412..b260901456 100644
--- a/nordic/trezor/trezor-ble/src/main.c
+++ b/nordic/trezor/trezor-ble/src/main.c
@@ -39,7 +39,8 @@
#include
#include
-#include
+#include
+#include
#include
#include
@@ -55,9 +56,11 @@ int main(void) {
ble_init();
- power_management_init();
+ management_init();
- signals_fw_running(true);
+ prodtest_init();
+
+ signals_nrf_ready(true);
for (;;) {
k_sleep(K_FOREVER);
diff --git a/nordic/trezor/trezor-ble/src/power_management/inc/power_management/power_management.h b/nordic/trezor/trezor-ble/src/management/inc/management/management.h
similarity index 90%
rename from nordic/trezor/trezor-ble/src/power_management/inc/power_management/power_management.h
rename to nordic/trezor/trezor-ble/src/management/inc/management/management.h
index 492b4ad478..f64d52b9d4 100644
--- a/nordic/trezor/trezor-ble/src/power_management/inc/power_management/power_management.h
+++ b/nordic/trezor/trezor-ble/src/management/inc/management/management.h
@@ -19,5 +19,5 @@
#pragma once
-// Initialize the power management module
-void power_management_init(void);
+// Initialize the management module
+void management_init(void);
diff --git a/nordic/trezor/trezor-ble/src/power_management/power_management.c b/nordic/trezor/trezor-ble/src/management/management.c
similarity index 54%
rename from nordic/trezor/trezor-ble/src/power_management/power_management.c
rename to nordic/trezor/trezor-ble/src/management/management.c
index a779eb2bba..7656a5a747 100644
--- a/nordic/trezor/trezor-ble/src/power_management/power_management.c
+++ b/nordic/trezor/trezor-ble/src/management/management.c
@@ -23,45 +23,72 @@
#include
#include
+#include
#include
#include
#include
+#include
#include
-#define LOG_MODULE_NAME power_manangement
+#define LOG_MODULE_NAME manangement
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
-static K_SEM_DEFINE(power_management_ok, 0, 1);
+static K_SEM_DEFINE(management_ok, 0, 1);
typedef enum {
- PWR_CMD_SYSTEM_OFF = 0x00,
-} power_management_cmd_t;
+ MGMT_CMD_SYSTEM_OFF = 0x00,
+ MGMT_CMD_INFO = 0x01,
+} management_cmd_t;
-void power_management_init(void) { k_sem_give(&power_management_ok); }
+typedef enum {
+ MGMT_RESP_INFO = 0,
+} management_resp_t;
+
+void management_init(void) { k_sem_give(&management_ok); }
+
+static void send_info(void) {
+ uint8_t data[9] = {0};
+
+ data[0] = MGMT_RESP_INFO;
+ data[1] = APP_VERSION_MAJOR;
+ data[2] = APP_VERSION_MINOR;
+ data[3] = APP_PATCHLEVEL;
+ data[4] = APP_TWEAK;
+ data[5] = signals_is_trz_ready();
+ data[6] = signals_is_stay_in_bootloader();
+ data[7] = signals_out_get_nrf_ready();
+ data[8] = signals_out_get_reserved();
+
+ trz_comm_send_msg(NRF_SERVICE_MANAGEMENT, data, sizeof(data));
+}
static void process_command(uint8_t *data, uint16_t len) {
uint8_t cmd = data[0];
switch (cmd) {
- case PWR_CMD_SYSTEM_OFF:
+ case MGMT_CMD_SYSTEM_OFF:
LOG_INF("System off");
sys_poweroff();
break;
+ case MGMT_CMD_INFO:
+ LOG_INF("Info command");
+ send_info();
+ break;
default:
break;
}
}
-void power_management_thread(void) {
+void management_thread(void) {
/* Don't go any further until BLE is initialized */
- k_sem_take(&power_management_ok, K_FOREVER);
+ k_sem_take(&management_ok, K_FOREVER);
for (;;) {
- trz_packet_t *buf = trz_comm_poll_data(NRF_SERVICE_POWER_MANAGEMENT);
+ trz_packet_t *buf = trz_comm_poll_data(NRF_SERVICE_MANAGEMENT);
process_command(buf->data, buf->len);
k_free(buf);
}
}
-K_THREAD_DEFINE(power_management_thread_id, CONFIG_DEFAULT_THREAD_STACK_SIZE,
- power_management_thread, NULL, NULL, NULL, 7, 0, 0);
+K_THREAD_DEFINE(management_thread_id, CONFIG_DEFAULT_THREAD_STACK_SIZE,
+ management_thread, NULL, NULL, NULL, 7, 0, 0);
diff --git a/nordic/trezor/trezor-ble/src/prodtest/inc/prodtest/prodtest.h b/nordic/trezor/trezor-ble/src/prodtest/inc/prodtest/prodtest.h
new file mode 100644
index 0000000000..3d7de7c387
--- /dev/null
+++ b/nordic/trezor/trezor-ble/src/prodtest/inc/prodtest/prodtest.h
@@ -0,0 +1,23 @@
+/*
+ * 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
+
+// Initialize the prodtest module
+void prodtest_init(void);
diff --git a/nordic/trezor/trezor-ble/src/prodtest/prodtest.c b/nordic/trezor/trezor-ble/src/prodtest/prodtest.c
new file mode 100644
index 0000000000..26f8666da8
--- /dev/null
+++ b/nordic/trezor/trezor-ble/src/prodtest/prodtest.c
@@ -0,0 +1,81 @@
+/*
+ * 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 .
+ */
+
+#include
+#include
+
+#include
+#include
+
+#include
+
+#include
+#include
+
+#define LOG_MODULE_NAME prodtest
+LOG_MODULE_REGISTER(LOG_MODULE_NAME);
+
+static K_SEM_DEFINE(prodtest_ok, 0, 1);
+
+typedef enum {
+ PRODTEST_CMD_SPI_DATA = 0x00,
+ PRODTEST_CMD_UART_DATA = 0x01,
+ PRODTEST_CMD_SET_OUTPUT = 0x02,
+} prodtest_cmd_t;
+
+typedef enum {
+ PRODTEST_RESP_SPI = 0x00,
+ PRODTEST_RESP_UART = 0x01,
+} prodtest_resp_t;
+
+void prodtest_init(void) { k_sem_give(&prodtest_ok); }
+
+static void process_command(uint8_t *data, uint16_t len) {
+ uint8_t resp_data[244] = {0};
+ uint8_t cmd = data[0];
+ switch (cmd) {
+ case PRODTEST_CMD_SPI_DATA:
+ resp_data[0] = PRODTEST_RESP_SPI;
+ trz_comm_send_msg(NRF_SERVICE_PRODTEST, resp_data, 244);
+ break;
+ case PRODTEST_CMD_UART_DATA:
+ resp_data[0] = PRODTEST_RESP_UART;
+ trz_comm_send_msg(NRF_SERVICE_PRODTEST, resp_data, 64);
+ break;
+ case PRODTEST_CMD_SET_OUTPUT:
+ signals_reserved(data[1]);
+ break;
+ default:
+ break;
+ }
+}
+
+void prodtest_thread(void) {
+ /* Don't go any further until module is initialized */
+ k_sem_take(&prodtest_ok, K_FOREVER);
+
+ for (;;) {
+ trz_packet_t *buf = trz_comm_poll_data(NRF_SERVICE_PRODTEST);
+ process_command(buf->data, buf->len);
+ k_free(buf);
+ }
+}
+
+K_THREAD_DEFINE(prodtest_thread_id, CONFIG_DEFAULT_THREAD_STACK_SIZE,
+ prodtest_thread, NULL, NULL, NULL, 7, 0, 0);
diff --git a/nordic/trezor/trezor-ble/src/signals/inc/signals/signals.h b/nordic/trezor/trezor-ble/src/signals/inc/signals/signals.h
index 1766d38b4f..22cff327b3 100644
--- a/nordic/trezor/trezor-ble/src/signals/inc/signals/signals.h
+++ b/nordic/trezor/trezor-ble/src/signals/inc/signals/signals.h
@@ -24,8 +24,24 @@
// Initializes the Signals module
bool signals_init(void);
+// INPUTS
+
// Checks if the TRZ is ready to communicate
bool signals_is_trz_ready(void);
+// Checks if the device should stay in the bootloader
+bool signals_is_stay_in_bootloader(void);
+
+// OUTPUTS
+
// Signals that NRF firmware is running and initialized
-void signals_fw_running(bool set);
+void signals_nrf_ready(bool set);
+
+// Sets the reserved output
+void signals_reserved(bool set);
+
+// Reads the current output setting
+bool signals_out_get_nrf_ready(void);
+
+// Reads the current output setting
+bool signals_out_get_reserved(void);
diff --git a/nordic/trezor/trezor-ble/src/signals/signals.c b/nordic/trezor/trezor-ble/src/signals/signals.c
index 141359a2ec..49ded9bb11 100644
--- a/nordic/trezor/trezor-ble/src/signals/signals.c
+++ b/nordic/trezor/trezor-ble/src/signals/signals.c
@@ -28,12 +28,16 @@
#define LOG_MODULE_NAME signals
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
-#define RUN_STATUS_LED DK_LED1
-#define RUN_LED_BLINK_INTERVAL 1000
+#define OUT_RESERVED DK_LED1
+#define OUT_NRF_READY DK_LED2
-#define FW_RUNNING_SIG DK_LED2
+#define IN_STAY_IN_BOOTLOADER DK_BTN1_MSK
+#define IN_TRZ_READY DK_BTN2_MSK
-static K_SEM_DEFINE(led_init_ok, 0, 1);
+static K_SEM_DEFINE(signals_ok, 0, 1);
+
+static bool out_nrf_ready = false;
+static bool out_reserved = false;
void button_changed(uint32_t button_state, uint32_t has_changed) {}
@@ -52,44 +56,31 @@ static void configure_gpio(void) {
}
bool signals_is_trz_ready(void) {
- return (dk_get_buttons() & DK_BTN2_MSK) != 0;
+ return (dk_get_buttons() & IN_TRZ_READY) != 0;
+}
+
+bool signals_is_stay_in_bootloader(void) {
+ return (dk_get_buttons() & IN_STAY_IN_BOOTLOADER) != 0;
}
bool signals_init(void) {
configure_gpio();
- k_sem_give(&led_init_ok);
+ k_sem_give(&signals_ok);
return true;
}
-void signals_fw_running(bool set) { dk_set_led(FW_RUNNING_SIG, set); }
-
-void led_thread(void) {
- // bool connected = false;
- int blink_status = 0;
- /* Don't go any further until BLE is initialized */
- k_sem_take(&led_init_ok, K_FOREVER);
-
- for (;;) {
- blink_status++;
- dk_set_led(RUN_STATUS_LED, (blink_status) % 2);
-
- // connected = is_connected();
- //
- // if (connected) {
- // dk_set_led_on(CON_STATUS_LED);
- // } else {
- // if (is_advertising() && !is_advertising_whitelist()) {
- // dk_set_led(CON_STATUS_LED, (blink_status) % 2);
- // } else {
- // dk_set_led_off(CON_STATUS_LED);
- // }
- // }
-
- k_sleep(K_MSEC(RUN_LED_BLINK_INTERVAL));
- }
+void signals_nrf_ready(bool set) {
+ out_nrf_ready = set;
+ dk_set_led(OUT_NRF_READY, set);
}
-K_THREAD_DEFINE(led_thread_id, CONFIG_DEFAULT_THREAD_STACK_SIZE, led_thread,
- NULL, NULL, NULL, 7, 0, 0);
+bool signals_out_get_nrf_ready(void) { return out_nrf_ready; }
+
+void signals_reserved(bool set) {
+ out_reserved = set;
+ dk_set_led(OUT_RESERVED, set);
+}
+
+bool signals_out_get_reserved(void) { return out_reserved; }
diff --git a/nordic/trezor/trezor-ble/src/trz_comm/inc/trz_comm/trz_comm.h b/nordic/trezor/trezor-ble/src/trz_comm/inc/trz_comm/trz_comm.h
index d2c9037ce7..2f26f6a9a8 100644
--- a/nordic/trezor/trezor-ble/src/trz_comm/inc/trz_comm/trz_comm.h
+++ b/nordic/trezor/trezor-ble/src/trz_comm/inc/trz_comm/trz_comm.h
@@ -27,7 +27,8 @@
typedef enum {
NRF_SERVICE_BLE = 0,
NRF_SERVICE_BLE_MANAGER = 1,
- NRF_SERVICE_POWER_MANAGEMENT = 2,
+ NRF_SERVICE_MANAGEMENT = 2,
+ NRF_SERVICE_PRODTEST = 3,
NRF_SERVICE_CNT // Number of services
} nrf_service_id_t;
diff --git a/nordic/trezor/trezor-ble/src/trz_comm/trz_comm.c b/nordic/trezor/trezor-ble/src/trz_comm/trz_comm.c
index 77837c89d3..412d8da342 100644
--- a/nordic/trezor/trezor-ble/src/trz_comm/trz_comm.c
+++ b/nordic/trezor/trezor-ble/src/trz_comm/trz_comm.c
@@ -34,7 +34,8 @@ LOG_MODULE_REGISTER(LOG_MODULE_NAME);
static K_FIFO_DEFINE(fifo_uart_rx_ble);
static K_FIFO_DEFINE(fifo_uart_rx_ble_manager);
-static K_FIFO_DEFINE(fifo_uart_rx_power_management);
+static K_FIFO_DEFINE(fifo_uart_rx_management);
+static K_FIFO_DEFINE(fifo_uart_rx_prodtest);
void trz_comm_init(void) {
spi_init();
@@ -62,15 +63,23 @@ void process_rx_msg(uint8_t service_id, uint8_t *data, uint32_t len) {
buf->len = len;
memcpy(buf->data, data, len);
- if (service_id == NRF_SERVICE_BLE) {
- k_fifo_put(&fifo_uart_rx_ble, buf);
- } else if (service_id == NRF_SERVICE_BLE_MANAGER) {
- k_fifo_put(&fifo_uart_rx_ble_manager, buf);
- } else if (service_id == NRF_SERVICE_POWER_MANAGEMENT) {
- k_fifo_put(&fifo_uart_rx_power_management, buf);
- } else {
- LOG_WRN("UART_RX unknown service");
- k_free(buf);
+ switch (service_id) {
+ case NRF_SERVICE_BLE:
+ k_fifo_put(&fifo_uart_rx_ble, buf);
+ break;
+ case NRF_SERVICE_BLE_MANAGER:
+ k_fifo_put(&fifo_uart_rx_ble_manager, buf);
+ break;
+ case NRF_SERVICE_MANAGEMENT:
+ k_fifo_put(&fifo_uart_rx_management, buf);
+ break;
+ case NRF_SERVICE_PRODTEST:
+ k_fifo_put(&fifo_uart_rx_prodtest, buf);
+ break;
+ default:
+ LOG_WRN("UART_RX unknown service");
+ k_free(buf);
+ break;
}
}
@@ -80,8 +89,10 @@ trz_packet_t *trz_comm_poll_data(nrf_service_id_t service) {
return k_fifo_get(&fifo_uart_rx_ble, K_FOREVER);
case NRF_SERVICE_BLE_MANAGER:
return k_fifo_get(&fifo_uart_rx_ble_manager, K_FOREVER);
- case NRF_SERVICE_POWER_MANAGEMENT:
- return k_fifo_get(&fifo_uart_rx_power_management, K_FOREVER);
+ case NRF_SERVICE_MANAGEMENT:
+ return k_fifo_get(&fifo_uart_rx_management, K_FOREVER);
+ case NRF_SERVICE_PRODTEST:
+ return k_fifo_get(&fifo_uart_rx_prodtest, K_FOREVER);
default:
LOG_WRN("UART_RX unknown service");
return NULL;