mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-02-27 06:42:02 +00:00
feat(core/prodtest): implement NRF test functions
[no changelog]
This commit is contained in:
parent
06223b78fe
commit
4221b8514b
@ -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',
|
||||
|
@ -17,12 +17,9 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_NRF_CRC8_H
|
||||
#define TREZORHAL_NRF_CRC8_H
|
||||
#pragma once
|
||||
|
||||
#include <trezor_types.h>
|
||||
|
||||
uint8_t crc8(const uint8_t *src, size_t len, uint8_t polynomial,
|
||||
uint8_t initial_value, bool reversed);
|
||||
|
||||
#endif
|
||||
|
@ -17,8 +17,7 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_NRF_H
|
||||
#define TREZORHAL_NRF_H
|
||||
#pragma once
|
||||
|
||||
#include <trezor_types.h>
|
||||
|
||||
@ -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);
|
||||
|
@ -17,11 +17,19 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef TREZORHAL_NRF_INTERNAL_H
|
||||
#define TREZORHAL_NRF_INTERNAL_H
|
||||
#pragma once
|
||||
|
||||
#include <trezor_types.h>
|
||||
|
||||
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);
|
||||
|
@ -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;
|
||||
|
||||
|
249
core/embed/io/nrf/stm32u5/nrf_test.c
Normal file
249
core/embed/io/nrf/stm32u5/nrf_test.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <sys/systick.h>
|
||||
#ifdef KERNEL_MODE
|
||||
|
||||
#include <trezor_model.h>
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include <io/nrf.h>
|
||||
|
||||
#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
|
@ -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 `<major>.<minor>.<patch>.<tweak>`.
|
||||
|
||||
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.
|
||||
```
|
||||
|
94
core/embed/projects/prodtest/cmd/prodtest_nrf.c
Normal file
94
core/embed/projects/prodtest/cmd/prodtest_nrf.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifdef USE_BLE
|
||||
|
||||
#include <trezor_rtl.h>
|
||||
|
||||
#include <io/nrf.h>
|
||||
#include <rtl/cli.h>
|
||||
|
||||
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
|
@ -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 += [
|
||||
|
@ -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 = <INPUT_KEY_0>;
|
||||
};
|
||||
trezor_ready: trezor_ready {
|
||||
|
@ -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
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -39,7 +39,8 @@
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <ble/ble.h>
|
||||
#include <power_management/power_management.h>
|
||||
#include <management/management.h>
|
||||
#include <prodtest/prodtest.h>
|
||||
#include <signals/signals.h>
|
||||
#include <trz_comm/trz_comm.h>
|
||||
|
||||
@ -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);
|
||||
|
@ -19,5 +19,5 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// Initialize the power management module
|
||||
void power_management_init(void);
|
||||
// Initialize the management module
|
||||
void management_init(void);
|
@ -23,45 +23,72 @@
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#include <app_version.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/sys/crc.h>
|
||||
#include <zephyr/sys/poweroff.h>
|
||||
|
||||
#include <signals/signals.h>
|
||||
#include <trz_comm/trz_comm.h>
|
||||
|
||||
#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);
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
// Initialize the prodtest module
|
||||
void prodtest_init(void);
|
81
nordic/trezor/trezor-ble/src/prodtest/prodtest.c
Normal file
81
nordic/trezor/trezor-ble/src/prodtest/prodtest.c
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#include <zephyr/logging/log.h>
|
||||
|
||||
#include <signals/signals.h>
|
||||
#include <trz_comm/trz_comm.h>
|
||||
|
||||
#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);
|
@ -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);
|
||||
|
@ -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; }
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user