1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-07-30 18:38:27 +00:00

feat(core): suspend NRF&BLE driver, with or without connection

[no changelog]
This commit is contained in:
tychovrahe 2025-04-28 14:35:41 +02:00 committed by TychoVrahe
parent 3f6a82ab67
commit 755cb359bd
6 changed files with 161 additions and 34 deletions

View File

@ -42,6 +42,13 @@ typedef enum {
BLE_UNPAIR = 7, // Erase bond for currently connected device
} ble_command_type_t;
typedef enum {
BLE_MODE_OFF,
BLE_MODE_CONNECTABLE,
BLE_MODE_PAIRING,
BLE_MODE_DFU,
} ble_mode_t;
typedef struct {
uint8_t name[BLE_ADV_NAME_LEN];
bool static_mac;
@ -59,6 +66,12 @@ typedef struct {
ble_command_data_t data;
} ble_command_t;
typedef struct {
bool accept_msgs;
bool reboot_on_resume;
ble_mode_t mode_requested;
} ble_wakeup_params_t;
typedef enum {
BLE_NONE = 0, // No event
BLE_CONNECTED = 1, // Connected to a device
@ -97,6 +110,12 @@ bool ble_init(void);
// and shuts down the BLE module.
void ble_deinit(void);
// Suspends the BLE module
void ble_suspend(ble_wakeup_params_t *wakeup_params);
// Resumes the BLE module
bool ble_resume(const ble_wakeup_params_t *wakeup_params);
// Starts BLE operations
//
// Enables reception of messages over BLE

View File

@ -32,13 +32,6 @@
#include "ble_comm_defs.h"
typedef enum {
BLE_MODE_OFF,
BLE_MODE_CONNECTABLE,
BLE_MODE_PAIRING,
BLE_MODE_DFU,
} ble_mode_t;
// changing value of TX_QUEUE_LEN is not allowed
// as it might result in order of messages being changed
#define TX_QUEUE_LEN 1
@ -55,6 +48,7 @@ typedef struct {
bool initialized;
bool status_valid;
bool accept_msgs;
bool reboot_on_resume;
uint8_t busy_flag;
bool pairing_requested;
ble_event_t event_queue_buffers[EVENT_QUEUE_LEN];
@ -319,6 +313,10 @@ static void ble_process_data(const uint8_t *data, uint32_t len) {
return;
}
if (!drv->accept_msgs) {
return;
}
if (len != BLE_RX_PACKET_SIZE) {
return;
}
@ -445,9 +443,7 @@ cleanup:
return false;
}
void ble_deinit(void) {
ble_driver_t *drv = &g_ble_driver;
static void ble_deinit_common(ble_driver_t *drv) {
if (!drv->initialized) {
return;
}
@ -463,10 +459,62 @@ void ble_deinit(void) {
tsqueue_reset(&drv->event_queue);
tsqueue_reset(&drv->rx_queue);
tsqueue_reset(&drv->tx_queue);
}
nrf_deinit();
void ble_deinit(void) {
ble_driver_t *drv = &g_ble_driver;
drv->initialized = false;
if (drv->initialized) {
ble_deinit_common(drv);
nrf_deinit();
drv->initialized = false;
}
}
void ble_suspend(ble_wakeup_params_t *wakeup_params) {
ble_driver_t *drv = &g_ble_driver;
if (drv->initialized) {
bool connected = drv->connected;
wakeup_params->accept_msgs = connected;
wakeup_params->mode_requested = drv->mode_requested;
ble_deinit_common(drv);
if (!connected) {
wakeup_params->reboot_on_resume = true;
// if not connected, we can turn off the radio
nrf_system_off();
nrf_deinit();
} else {
nrf_suspend();
}
drv->initialized = false;
}
}
bool ble_resume(const ble_wakeup_params_t *wakeup_params) {
ble_driver_t *drv = &g_ble_driver;
if (!ble_init()) {
return false;
}
if (wakeup_params->reboot_on_resume) {
nrf_reboot();
}
if (wakeup_params->mode_requested) {
ble_start();
}
irq_key_t key = irq_lock();
drv->mode_requested = wakeup_params->mode_requested;
irq_unlock(key);
return true;
}
bool ble_connected(void) {

View File

@ -62,6 +62,9 @@ void nrf_init(void);
// Deinitialize the NRF driver
void nrf_deinit(void);
// Suspend NRF driver
void nrf_suspend(void);
// Check that NRF is running
bool nrf_is_running(void);
@ -109,3 +112,7 @@ bool nrf_test_gpio_stay_in_bld(void);
// Test GPIO reserved
bool nrf_test_gpio_reserved(void);
bool nrf_system_off(void);
void nrf_reboot(void);

View File

@ -41,7 +41,6 @@ uint32_t nrf_dfu_comm_receive(uint8_t *data, uint32_t len);
void nrf_int_send(const uint8_t *data, uint32_t len);
uint32_t nrf_int_receive(uint8_t *data, uint32_t len);
bool nrf_reboot(void);
bool nrf_reboot_to_bootloader(void);
void nrf_signal_data_ready(void);

View File

@ -77,10 +77,11 @@ typedef struct {
DMA_HandleTypeDef spi_tx_dma;
spi_packet_t long_rx_buffer;
EXTI_HandleTypeDef exti;
bool comm_running;
bool initialized;
bool wakeup;
bool pending_request;
nrf_rx_callback_t service_listeners[NRF_SERVICE_CNT];
@ -189,8 +190,6 @@ void nrf_init(void) {
__HAL_RCC_GPIOB_CLK_ENABLE();
__HAL_RCC_GPIOD_CLK_ENABLE();
bool tmp_pending_request = drv->pending_request;
memset(drv, 0, sizeof(*drv));
tsqueue_init(&drv->tx_queue, drv->tx_queue_entries,
(uint8_t *)drv->tx_buffers, sizeof(nrf_tx_request_t),
@ -235,14 +234,12 @@ void nrf_init(void) {
GPIO_InitStructure.Pin = NRF_IN_SPI_REQUEST_PIN;
HAL_GPIO_Init(NRF_IN_SPI_REQUEST_PORT, &GPIO_InitStructure);
EXTI_HandleTypeDef EXTI_Handle = {0};
EXTI_ConfigTypeDef EXTI_Config = {0};
EXTI_Config.GPIOSel = NRF_EXTI_INTERRUPT_GPIOSEL;
EXTI_Config.Line = NRF_EXTI_INTERRUPT_LINE;
EXTI_Config.Mode = EXTI_MODE_INTERRUPT;
EXTI_Config.Trigger = EXTI_TRIGGER_RISING;
HAL_EXTI_SetConfigLine(&EXTI_Handle, &EXTI_Config);
NVIC_SetPriority(NRF_EXTI_INTERRUPT_NUM, IRQ_PRI_NORMAL);
HAL_EXTI_SetConfigLine(&drv->exti, &EXTI_Config);
__HAL_GPIO_EXTI_CLEAR_FLAG(NRF_EXTI_INTERRUPT_PIN);
// UART PINS
@ -338,7 +335,13 @@ void nrf_init(void) {
HAL_SPI_Init(&drv->spi);
drv->tx_request_id = -1;
nrf_register_listener(NRF_SERVICE_MANAGEMENT, nrf_management_rx_cb);
drv->initialized = true;
drv->timer = systimer_create(nrf_timer_callback, drv);
nrf_start();
NVIC_SetPriority(USART3_IRQn, IRQ_PRI_NORMAL);
NVIC_EnableIRQ(USART3_IRQn);
@ -348,21 +351,16 @@ void nrf_init(void) {
NVIC_EnableIRQ(GPDMA1_Channel2_IRQn);
NVIC_SetPriority(SPI1_IRQn, IRQ_PRI_NORMAL);
NVIC_EnableIRQ(SPI1_IRQn);
NVIC_SetPriority(NRF_EXTI_INTERRUPT_NUM, IRQ_PRI_NORMAL);
NVIC_EnableIRQ(NRF_EXTI_INTERRUPT_NUM);
drv->tx_request_id = -1;
drv->initialized = true;
nrf_register_listener(NRF_SERVICE_MANAGEMENT, nrf_management_rx_cb);
nrf_start();
if (tmp_pending_request) {
if (HAL_GPIO_ReadPin(NRF_IN_SPI_REQUEST_PORT, NRF_IN_SPI_REQUEST_PIN) ==
GPIO_PIN_SET) {
nrf_prepare_spi_data(drv);
}
}
void nrf_deinit(void) {
void nrf_suspend(void) {
nrf_driver_t *drv = &g_nrf_driver;
nrf_stop();
@ -373,7 +371,6 @@ void nrf_deinit(void) {
NVIC_DisableIRQ(GPDMA1_Channel2_IRQn);
NVIC_DisableIRQ(SPI1_IRQn);
NVIC_DisableIRQ(USART3_IRQn);
NVIC_DisableIRQ(NRF_EXTI_INTERRUPT_NUM);
__HAL_RCC_SPI1_FORCE_RESET();
__HAL_RCC_SPI1_RELEASE_RESET();
@ -381,10 +378,43 @@ void nrf_deinit(void) {
__HAL_RCC_USART3_FORCE_RESET();
__HAL_RCC_USART3_RELEASE_RESET();
HAL_GPIO_DeInit(NRF_OUT_RESET_PORT, NRF_OUT_RESET_PIN);
HAL_GPIO_DeInit(NRF_OUT_SPI_READY_PORT, NRF_OUT_SPI_READY_PIN);
HAL_GPIO_DeInit(NRF_OUT_STAY_IN_BLD_PORT, NRF_OUT_STAY_IN_BLD_PIN);
HAL_GPIO_DeInit(NRF_IN_RESERVED_PORT, NRF_IN_RESERVED_PIN);
// UART Pins
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_1);
HAL_GPIO_DeInit(GPIOD, GPIO_PIN_11);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_5);
// SPI Pins
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_1);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_4);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_6);
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_7);
drv->initialized = false;
drv->pending_spi_transaction = false;
drv->wakeup = true;
}
void nrf_deinit(void) {
nrf_driver_t *drv = &g_nrf_driver;
if (drv->initialized) {
NVIC_DisableIRQ(NRF_EXTI_INTERRUPT_NUM);
HAL_GPIO_DeInit(NRF_IN_SPI_REQUEST_PORT, NRF_IN_SPI_REQUEST_PIN);
HAL_EXTI_ClearConfigLine(&drv->exti);
nrf_suspend();
}
}
bool nrf_register_listener(nrf_service_id_t service,
nrf_rx_callback_t callback) {
nrf_driver_t *drv = &g_nrf_driver;
@ -769,7 +799,6 @@ void NRF_EXTI_INTERRUPT_HANDLER(void) {
// Inform the powerctl module about nrf/ble wakeup
wakeup_flags_set(WAKEUP_FLAG_BLE);
drv->wakeup = false;
drv->pending_request = true;
}
#endif
@ -821,13 +850,12 @@ bool nrf_in_reserved(void) {
return HAL_GPIO_ReadPin(NRF_IN_RESERVED_PORT, NRF_IN_RESERVED_PIN) != 0;
}
bool nrf_reboot(void) {
void 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,
GPIO_PIN_RESET);
systick_delay_ms(50);
HAL_GPIO_WritePin(NRF_OUT_RESET_PORT, NRF_OUT_RESET_PIN, GPIO_PIN_SET);
return true;
}
void nrf_signal_data_ready(void) {
@ -876,6 +904,31 @@ bool nrf_get_info(nrf_info_t *info) {
return false;
}
bool nrf_system_off(void) {
nrf_driver_t *drv = &g_nrf_driver;
if (!drv->initialized) {
return false;
}
uint8_t data[1] = {MGMT_CMD_SYSTEM_OFF};
if (!nrf_send_msg(NRF_SERVICE_MANAGEMENT, data, 1, NULL, NULL)) {
return false;
}
uint32_t timeout = ticks_timeout(100);
bool finished = false;
while (!ticks_expired(timeout) && !finished) {
irq_key_t key = irq_lock();
finished = tsqueue_empty(&drv->tx_queue) && !drv->pending_spi_transaction;
irq_unlock(key);
__WFI();
}
return true;
}
void nrf_set_dfu_mode(void) {
nrf_driver_t *drv = &g_nrf_driver;

View File

@ -97,7 +97,8 @@ void powerctl_suspend(void) {
touch_deinit();
#endif
#ifdef USE_BLE
ble_deinit();
ble_wakeup_params_t ble_wakeup_params = {0};
ble_suspend(&ble_wakeup_params);
#endif
int backlight_level = display_get_backlight();
@ -180,7 +181,7 @@ void powerctl_suspend(void) {
tropic_init();
#endif
#ifdef USE_BLE
ble_init();
ble_resume(&ble_wakeup_params);
#endif
}