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:
parent
3f6a82ab67
commit
755cb359bd
@ -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
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user