1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2025-01-08 14:31:06 +00:00

fixup! feat(core:): introduce BLE driver

This commit is contained in:
tychovrahe 2025-01-02 16:07:40 +01:00
parent 1e422dd8bb
commit bec19dae87
4 changed files with 122 additions and 117 deletions

View File

@ -44,7 +44,7 @@ typedef enum {
INTERNAL_EVENT_STATUS = 0x01, INTERNAL_EVENT_STATUS = 0x01,
INTERNAL_EVENT_PAIRING_REQUEST = 0x04, INTERNAL_EVENT_PAIRING_REQUEST = 0x04,
INTERNAL_EVENT_PAIRING_CANCELLED = 0x05, INTERNAL_EVENT_PAIRING_CANCELLED = 0x05,
} InternalEvent_t; } internal_event_t;
typedef enum { typedef enum {
INTERNAL_CMD_PING = 0x00, INTERNAL_CMD_PING = 0x00,
@ -55,5 +55,5 @@ typedef enum {
INTERNAL_CMD_ACK = 0x05, INTERNAL_CMD_ACK = 0x05,
INTERNAL_CMD_ALLOW_PAIRING = 0x06, INTERNAL_CMD_ALLOW_PAIRING = 0x06,
INTERNAL_CMD_REJECT_PAIRING = 0x07, INTERNAL_CMD_REJECT_PAIRING = 0x07,
} InternalCmd_t; } internal_cmd_t;
#endif #endif

View File

@ -39,11 +39,8 @@ typedef enum {
NRF_STATUS_ABORTED = 3, // Packet was aborted NRF_STATUS_ABORTED = 3, // Packet was aborted
} nrf_status_t; } nrf_status_t;
typedef struct { typedef void (*nrf_rx_callback_t)(const uint8_t *data, uint32_t len);
const uint8_t *data; typedef void (*nrf_tx_callback_t)(nrf_status_t status, void *context);
uint32_t len;
} nrf_packet_t;
// Initialize the NRF driver // Initialize the NRF driver
void nrf_init(void); void nrf_init(void);
@ -57,8 +54,9 @@ bool nrf_is_running(void);
// Register listener for a service // Register listener for a service
// The listener will be called when a message is received for the service // The listener will be called when a message is received for the service
// The listener will be called from an interrupt context // The listener will be called from an interrupt context
void nrf_register_listener(nrf_service_id_t service, // Returns false if a listener for the service is already registered
void (*listener)(const uint8_t *data, uint32_t len)); bool nrf_register_listener(nrf_service_id_t service,
nrf_rx_callback_t callback);
// Unregister listener for a service // Unregister listener for a service
void nrf_unregister_listener(nrf_service_id_t service); void nrf_unregister_listener(nrf_service_id_t service);
@ -68,9 +66,7 @@ void nrf_unregister_listener(nrf_service_id_t service);
// If the queue is full, the message will be dropped // If the queue is full, the message will be dropped
// returns ID of the message if it was successfully queued, otherwise -1 // returns ID of the message if it was successfully queued, otherwise -1
int32_t nrf_send_msg(nrf_service_id_t service, const uint8_t *data, int32_t nrf_send_msg(nrf_service_id_t service, const uint8_t *data,
uint32_t len, uint32_t len, nrf_tx_callback_t callback, void *context);
void (*callback)(nrf_status_t status, void *context),
void *context);
// Abort a message by ID // Abort a message by ID
// If the message is already sent or the id is not found, it does nothing and // If the message is already sent or the id is not found, it does nothing and

View File

@ -66,7 +66,7 @@ typedef struct {
typedef struct { typedef struct {
uint8_t data[UART_PACKET_SIZE]; uint8_t data[UART_PACKET_SIZE];
uint8_t len; uint8_t len;
void (*callback)(nrf_status_t status, void *context); nrf_tx_callback_t callback;
void *context; void *context;
} nrf_uart_tx_data_t; } nrf_uart_tx_data_t;
@ -74,28 +74,25 @@ typedef struct {
UART_HandleTypeDef urt; UART_HandleTypeDef urt;
DMA_HandleTypeDef urt_tx_dma; DMA_HandleTypeDef urt_tx_dma;
uint8_t urt_tx_buffers[UART_QUEUE_SIZE][sizeof(nrf_uart_tx_data_t)]; uint8_t tx_buffers[UART_QUEUE_SIZE][sizeof(nrf_uart_tx_data_t)];
tsqueue_entry_t urt_tx_queue_entries[UART_QUEUE_SIZE]; tsqueue_entry_t tx_queue_entries[UART_QUEUE_SIZE];
tsqueue_t urt_tx_queue; tsqueue_t tx_queue;
nrf_uart_tx_data_t urt_sending; nrf_uart_tx_data_t tx_data;
int32_t tx_msg_id;
uint8_t urt_rx_buf[UART_PACKET_SIZE]; uint8_t rx_buffer[UART_PACKET_SIZE];
uint8_t urt_rx_len; uint8_t rx_len;
uint8_t urt_rx_byte; uint8_t rx_byte;
uint16_t urt_rx_idx; uint16_t rx_idx;
SPI_HandleTypeDef spi; SPI_HandleTypeDef spi;
DMA_HandleTypeDef spi_dma; DMA_HandleTypeDef spi_dma;
uint8_t spi_buffer[SPI_PACKET_SIZE]; uint8_t long_rx_buffer[SPI_PACKET_SIZE];
int32_t urt_tx_msg_id;
bool urt_tx_running;
bool spi_rx_running;
bool comm_running; bool comm_running;
bool initialized; bool initialized;
void (*service_listeners[NRF_SERVICE_CNT])(const uint8_t *data, uint32_t len); nrf_rx_callback_t service_listeners[NRF_SERVICE_CNT];
} nrf_driver_t; } nrf_driver_t;
@ -107,12 +104,11 @@ static void nrf_start(void) {
return; return;
} }
HAL_SPI_Receive_DMA(&drv->spi, drv->spi_buffer, SPI_PACKET_SIZE); HAL_SPI_Receive_DMA(&drv->spi, drv->long_rx_buffer, SPI_PACKET_SIZE);
tsqueue_reset(&drv->urt_tx_queue); tsqueue_reset(&drv->tx_queue);
HAL_UART_Receive_IT(&drv->urt, &drv->urt_rx_byte, 1); HAL_UART_Receive_IT(&drv->urt, &drv->rx_byte, 1);
drv->spi_rx_running = true;
drv->comm_running = true; drv->comm_running = true;
nrf_signal_running(); nrf_signal_running();
@ -122,24 +118,24 @@ static void nrf_abort_urt_comm(nrf_driver_t *drv) {
HAL_UART_AbortReceive(&drv->urt); HAL_UART_AbortReceive(&drv->urt);
HAL_UART_AbortTransmit(&drv->urt); HAL_UART_AbortTransmit(&drv->urt);
if (drv->urt_sending.callback != NULL) { if (drv->tx_data.callback != NULL) {
drv->urt_sending.callback(NRF_STATUS_ERROR, drv->urt_sending.context); drv->tx_data.callback(NRF_STATUS_ERROR, drv->tx_data.context);
} }
drv->urt_rx_idx = 0; drv->rx_idx = 0;
drv->urt_rx_len = 0; drv->rx_len = 0;
drv->urt_tx_msg_id = -1; drv->tx_msg_id = -1;
drv->urt_tx_running = false;
while (tsqueue_dequeue(&drv->urt_tx_queue, (uint8_t *)&drv->urt_sending, while (tsqueue_dequeue(&drv->tx_queue, (uint8_t *)&drv->tx_data,
sizeof(nrf_uart_tx_data_t), NULL, sizeof(nrf_uart_tx_data_t), NULL, &drv->tx_msg_id)) {
&drv->urt_tx_msg_id)) { if (drv->tx_data.callback != NULL) {
drv->urt_sending.callback(NRF_STATUS_ERROR, drv->urt_sending.context); drv->tx_data.callback(NRF_STATUS_ERROR, drv->tx_data.context);
}
} }
memset(&drv->urt_sending, 0, sizeof(nrf_uart_tx_data_t)); memset(&drv->tx_data, 0, sizeof(nrf_uart_tx_data_t));
tsqueue_reset(&drv->urt_tx_queue); tsqueue_reset(&drv->tx_queue);
} }
static void nrf_stop(void) { static void nrf_stop(void) {
@ -171,8 +167,8 @@ void nrf_init(void) {
__HAL_RCC_GPIOD_CLK_ENABLE(); __HAL_RCC_GPIOD_CLK_ENABLE();
memset(drv, 0, sizeof(*drv)); memset(drv, 0, sizeof(*drv));
tsqueue_init(&drv->urt_tx_queue, drv->urt_tx_queue_entries, tsqueue_init(&drv->tx_queue, drv->tx_queue_entries,
(uint8_t *)drv->urt_tx_buffers, sizeof(nrf_uart_tx_data_t), (uint8_t *)drv->tx_buffers, sizeof(nrf_uart_tx_data_t),
UART_QUEUE_SIZE); UART_QUEUE_SIZE);
GPIO_InitTypeDef GPIO_InitStructure = {0}; GPIO_InitTypeDef GPIO_InitStructure = {0};
@ -331,20 +327,38 @@ void nrf_deinit(void) {
nrf_stop(); nrf_stop();
NVIC_DisableIRQ(GPDMA1_Channel2_IRQn);
NVIC_DisableIRQ(SPI1_IRQn);
__HAL_RCC_SPI1_FORCE_RESET();
__HAL_RCC_SPI1_RELEASE_RESET();
__HAL_RCC_USART1_FORCE_RESET();
__HAL_RCC_USART1_RELEASE_RESET();
drv->initialized = false; drv->initialized = false;
} }
void nrf_register_listener(nrf_service_id_t service, bool nrf_register_listener(nrf_service_id_t service,
void (*listener)(const uint8_t *data, nrf_rx_callback_t callback) {
uint32_t len)) {
nrf_driver_t *drv = &g_nrf_driver; nrf_driver_t *drv = &g_nrf_driver;
if (!drv->initialized) { if (!drv->initialized) {
return; return false;
} }
if (service < NRF_SERVICE_CNT) { if (service >= NRF_SERVICE_CNT) {
drv->service_listeners[service] = listener; return false;
} }
if (drv->service_listeners[service] != NULL) {
return false;
}
irq_key_t key = irq_lock();
drv->service_listeners[service] = callback;
irq_unlock(key);
return true;
} }
void nrf_unregister_listener(nrf_service_id_t service) { void nrf_unregister_listener(nrf_service_id_t service) {
@ -353,9 +367,13 @@ void nrf_unregister_listener(nrf_service_id_t service) {
return; return;
} }
if (service < NRF_SERVICE_CNT) { if (service >= NRF_SERVICE_CNT) {
drv->service_listeners[service] = NULL; return;
} }
irq_key_t key = irq_lock();
drv->service_listeners[service] = NULL;
irq_unlock(key);
} }
static void nrf_process_msg(nrf_driver_t *drv, const uint8_t *data, static void nrf_process_msg(nrf_driver_t *drv, const uint8_t *data,
@ -407,9 +425,7 @@ uint32_t nrf_dfu_comm_receive(uint8_t *data, uint32_t len) {
/// --------------------------------------------------------- /// ---------------------------------------------------------
int32_t nrf_send_msg(nrf_service_id_t service, const uint8_t *data, int32_t nrf_send_msg(nrf_service_id_t service, const uint8_t *data,
uint32_t len, uint32_t len, nrf_tx_callback_t callback, void *context) {
void (*callback)(nrf_status_t status, void *context),
void *context) {
nrf_driver_t *drv = &g_nrf_driver; nrf_driver_t *drv = &g_nrf_driver;
if (!drv->initialized) { if (!drv->initialized) {
return -1; return -1;
@ -444,20 +460,18 @@ int32_t nrf_send_msg(nrf_service_id_t service, const uint8_t *data,
}; };
memcpy(&buffer.data[UART_HEADER_SIZE + len], &footer, UART_FOOTER_SIZE); memcpy(&buffer.data[UART_HEADER_SIZE + len], &footer, UART_FOOTER_SIZE);
if (!tsqueue_enqueue(&drv->urt_tx_queue, (uint8_t *)&buffer, if (!tsqueue_enqueue(&drv->tx_queue, (uint8_t *)&buffer,
sizeof(nrf_uart_tx_data_t), &id)) { sizeof(nrf_uart_tx_data_t), &id)) {
return -1; return -1;
} }
irq_key_t key = irq_lock(); irq_key_t key = irq_lock();
if (!drv->urt_tx_running) { if (drv->tx_msg_id < 0) {
int32_t tx_id = 0; int32_t tx_id = 0;
if (tsqueue_dequeue(&drv->urt_tx_queue, (uint8_t *)&drv->urt_sending, if (tsqueue_dequeue(&drv->tx_queue, (uint8_t *)&drv->tx_data,
sizeof(nrf_uart_tx_data_t), NULL, &tx_id)) { sizeof(nrf_uart_tx_data_t), NULL, &tx_id)) {
HAL_UART_Transmit_DMA(&drv->urt, drv->urt_sending.data, HAL_UART_Transmit_DMA(&drv->urt, drv->tx_data.data, drv->tx_data.len);
drv->urt_sending.len); drv->tx_msg_id = tx_id;
drv->urt_tx_msg_id = tx_id;
drv->urt_tx_running = true;
} }
} }
irq_unlock(key); irq_unlock(key);
@ -471,14 +485,14 @@ bool nrf_abort_msg(int32_t id) {
return false; return false;
} }
bool aborted = tsqueue_abort(&drv->urt_tx_queue, id, NULL, 0, NULL); bool aborted = tsqueue_abort(&drv->tx_queue, id, NULL, 0, NULL);
if (aborted) { if (aborted) {
return true; return true;
} }
if (drv->urt_tx_msg_id == id) { if (drv->tx_msg_id == id) {
drv->urt_tx_msg_id = -1; drv->tx_msg_id = -1;
return true; return true;
} }
@ -500,64 +514,63 @@ static bool nrf_is_valid_startbyte(uint8_t val) {
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *urt) { void HAL_UART_RxCpltCallback(UART_HandleTypeDef *urt) {
nrf_driver_t *drv = &g_nrf_driver; nrf_driver_t *drv = &g_nrf_driver;
if (drv->initialized && urt == &drv->urt) { if (drv->initialized && urt == &drv->urt) {
if (drv->urt_rx_idx == 0) { if (drv->rx_idx == 0) {
// received first byte: START BYTE // received first byte: START BYTE
if (nrf_is_valid_startbyte(drv->urt_rx_byte)) { if (nrf_is_valid_startbyte(drv->rx_byte)) {
drv->urt_rx_buf[0] = drv->urt_rx_byte; drv->rx_buffer[0] = drv->rx_byte;
drv->urt_rx_idx++; drv->rx_idx++;
} else { } else {
// bad message, flush the line // bad message, flush the line
drv->urt_rx_idx = 0; drv->rx_idx = 0;
} }
} else if (drv->urt_rx_idx == 1) { } else if (drv->rx_idx == 1) {
// received second byte: LEN // received second byte: LEN
drv->urt_rx_buf[1] = drv->urt_rx_byte; drv->rx_buffer[1] = drv->rx_byte;
drv->urt_rx_len = drv->urt_rx_byte; drv->rx_len = drv->rx_byte;
if (drv->urt_rx_len > UART_PACKET_SIZE) { if (drv->rx_len > UART_PACKET_SIZE) {
drv->urt_rx_len = 0; drv->rx_len = 0;
} else { } else {
drv->urt_rx_idx++; drv->rx_idx++;
} }
} else if (drv->urt_rx_idx >= UART_HEADER_SIZE && } else if (drv->rx_idx >= UART_HEADER_SIZE &&
drv->urt_rx_idx < (drv->urt_rx_len - 1)) { drv->rx_idx < (drv->rx_len - 1)) {
// receive the rest of the message // receive the rest of the message
drv->urt_rx_buf[drv->urt_rx_idx] = drv->urt_rx_byte; drv->rx_buffer[drv->rx_idx] = drv->rx_byte;
drv->urt_rx_idx++; drv->rx_idx++;
if (drv->urt_rx_idx >= NRF_MAX_TX_DATA_SIZE) { if (drv->rx_idx >= NRF_MAX_TX_DATA_SIZE) {
// message is too long, flush the line // message is too long, flush the line
drv->urt_rx_idx = 0; drv->rx_idx = 0;
drv->urt_rx_len = 0; drv->rx_len = 0;
} }
} else if (drv->urt_rx_idx == (drv->urt_rx_len - 1)) { } else if (drv->rx_idx == (drv->rx_len - 1)) {
// received last byte: CRC // received last byte: CRC
uint8_t crc = uint8_t crc = crc8(drv->rx_buffer, drv->rx_len - 1, 0x07, 0x00, false);
crc8(drv->urt_rx_buf, drv->urt_rx_len - 1, 0x07, 0x00, false);
if (drv->urt_rx_byte == crc) { if (drv->rx_byte == crc) {
uart_header_t *header = (uart_header_t *)drv->urt_rx_buf; uart_header_t *header = (uart_header_t *)drv->rx_buffer;
nrf_process_msg(drv, drv->urt_rx_buf, drv->urt_rx_len, nrf_process_msg(drv, drv->rx_buffer, drv->rx_len,
header->service_id & 0x0F, UART_HEADER_SIZE, header->service_id & 0x0F, UART_HEADER_SIZE,
UART_OVERHEAD_SIZE); UART_OVERHEAD_SIZE);
} }
drv->urt_rx_idx = 0; drv->rx_idx = 0;
drv->urt_rx_len = 0; drv->rx_len = 0;
} else { } else {
// bad message, flush the line // bad message, flush the line
drv->urt_rx_idx = 0; drv->rx_idx = 0;
drv->urt_rx_len = 0; drv->rx_len = 0;
} }
} }
// receive the rest of the message, or new message in any case. // receive the rest of the message, or new message in any case.
HAL_UART_Receive_IT(&drv->urt, &drv->urt_rx_byte, 1); HAL_UART_Receive_IT(&drv->urt, &drv->rx_byte, 1);
} }
void HAL_UART_ErrorCallback(UART_HandleTypeDef *urt) { void HAL_UART_ErrorCallback(UART_HandleTypeDef *urt) {
@ -565,28 +578,24 @@ void HAL_UART_ErrorCallback(UART_HandleTypeDef *urt) {
if (drv->initialized && urt == &drv->urt) { if (drv->initialized && urt == &drv->urt) {
nrf_abort_urt_comm(drv); nrf_abort_urt_comm(drv);
HAL_UART_Receive_IT(&drv->urt, &drv->urt_rx_byte, 1); HAL_UART_Receive_IT(&drv->urt, &drv->rx_byte, 1);
} }
} }
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *urt) { void HAL_UART_TxCpltCallback(UART_HandleTypeDef *urt) {
nrf_driver_t *drv = &g_nrf_driver; nrf_driver_t *drv = &g_nrf_driver;
if (drv->initialized && urt == &drv->urt) { if (drv->initialized && urt == &drv->urt) {
if (drv->urt_tx_msg_id >= 0 && (drv->urt_sending.callback != NULL)) { if (drv->tx_msg_id >= 0 && (drv->tx_data.callback != NULL)) {
drv->urt_sending.callback(NRF_STATUS_OK, drv->urt_sending.context); drv->tx_data.callback(NRF_STATUS_OK, drv->tx_data.context);
drv->urt_tx_msg_id = -1; drv->tx_msg_id = -1;
memset(&drv->urt_sending, 0, sizeof(nrf_uart_tx_data_t)); memset(&drv->tx_data, 0, sizeof(nrf_uart_tx_data_t));
} }
bool msg = bool msg =
tsqueue_dequeue(&drv->urt_tx_queue, (uint8_t *)&drv->urt_sending, tsqueue_dequeue(&drv->tx_queue, (uint8_t *)&drv->tx_data,
sizeof(nrf_uart_tx_data_t), NULL, &drv->urt_tx_msg_id); sizeof(nrf_uart_tx_data_t), NULL, &drv->tx_msg_id);
if (msg) { if (msg) {
HAL_UART_Transmit_DMA(&drv->urt, drv->urt_sending.data, HAL_UART_Transmit_DMA(&drv->urt, drv->tx_data.data, drv->tx_data.len);
drv->urt_sending.len);
drv->urt_tx_running = true;
} else {
drv->urt_tx_running = false;
} }
} }
} }
@ -629,8 +638,7 @@ static bool start_spi_dma(nrf_driver_t *drv) {
return false; return false;
} }
HAL_SPI_Receive_DMA(&drv->spi, drv->spi_buffer, SPI_PACKET_SIZE); HAL_SPI_Receive_DMA(&drv->spi, drv->long_rx_buffer, SPI_PACKET_SIZE);
drv->spi_rx_running = true;
return true; return true;
} }
@ -676,23 +684,22 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {
return; return;
} }
spi_header_t *header = (spi_header_t *)drv->spi_buffer; spi_header_t *header = (spi_header_t *)drv->long_rx_buffer;
spi_footer_t *footer = spi_footer_t *footer =
(spi_footer_t *)(drv->spi_buffer + SPI_PACKET_SIZE - SPI_FOOTER_SIZE); (spi_footer_t *)(drv->long_rx_buffer + SPI_PACKET_SIZE - SPI_FOOTER_SIZE);
uint8_t crc = crc8(drv->spi_buffer, SPI_PACKET_SIZE - SPI_FOOTER_SIZE, 0x07, uint8_t crc = crc8(drv->long_rx_buffer, SPI_PACKET_SIZE - SPI_FOOTER_SIZE,
0x00, false); 0x07, 0x00, false);
if ((header->service_id & 0xF0) != START_BYTE || footer->crc != crc) { if ((header->service_id & 0xF0) != START_BYTE || footer->crc != crc) {
HAL_SPI_Abort(&drv->spi); HAL_SPI_Abort(&drv->spi);
HAL_SPI_Receive_DMA(&drv->spi, drv->spi_buffer, SPI_PACKET_SIZE); HAL_SPI_Receive_DMA(&drv->spi, drv->long_rx_buffer, SPI_PACKET_SIZE);
return; return;
} }
nrf_process_msg(drv, drv->spi_buffer, SPI_PACKET_SIZE, nrf_process_msg(drv, drv->long_rx_buffer, SPI_PACKET_SIZE,
header->service_id & 0x0F, SPI_HEADER_SIZE, header->service_id & 0x0F, SPI_HEADER_SIZE,
SPI_OVERHEAD_SIZE); SPI_OVERHEAD_SIZE);
drv->spi_rx_running = false;
start_spi_dma(drv); start_spi_dma(drv);
} }

View File

@ -723,7 +723,9 @@ void ble_get_state__verified(ble_state_t *state) {
goto access_violation; goto access_violation;
} }
ble_get_state(state); ble_state_t state_copy = {0};
ble_get_state(&state_copy);
*state = state_copy;
return; return;
access_violation: access_violation: