1
0
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:
tychovrahe 2025-02-20 09:16:09 +01:00 committed by TychoVrahe
parent 06223b78fe
commit 4221b8514b
21 changed files with 705 additions and 84 deletions

View File

@ -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',

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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;

View 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

View File

@ -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.
```

View 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

View File

@ -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 += [

View File

@ -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 {

View File

@ -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

View File

@ -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);
}

View File

@ -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);

View File

@ -19,5 +19,5 @@
#pragma once
// Initialize the power management module
void power_management_init(void);
// Initialize the management module
void management_init(void);

View File

@ -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);

View File

@ -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);

View 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);

View File

@ -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);

View File

@ -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; }

View File

@ -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;

View File

@ -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;