feat(core): faster BLE communication - larger packets and write without response

tychovrahe/bluetooth/cleaner_disc2
tychovrahe 1 year ago
parent e8083af961
commit 52c520a8da

@ -22,9 +22,9 @@ BLE_NUS_DEF(m_nus,
NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */ NRF_SDH_BLE_TOTAL_LINK_COUNT); /**< BLE NUS service instance. */
static const nrf_drv_spi_t spi = static const nrf_drv_spi_t spi =
NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */ NRF_DRV_SPI_INSTANCE(SPI_INSTANCE); /**< SPI instance. */
static volatile bool spi_xfer_done; /**< Flag used to indicate that SPI instance static volatile bool spi_xfer_done = true; /**< Flag used to indicate that SPI
completed the transfer. */ instance completed the transfer. */
/** /**
* @brief SPI user event handler. * @brief SPI user event handler.
@ -200,10 +200,14 @@ void nus_data_handler(ble_nus_evt_t *p_evt) {
NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data,
p_evt->params.rx_data.length); p_evt->params.rx_data.length);
if (p_evt->params.rx_data.length != 64) { if (p_evt->params.rx_data.length != BLE_PACKET_SIZE) {
return; return;
} }
while (!spi_xfer_done)
;
spi_xfer_done = false;
nrf_drv_spi_transfer(&spi, p_evt->params.rx_data.p_data, nrf_drv_spi_transfer(&spi, p_evt->params.rx_data.p_data,
p_evt->params.rx_data.length, NULL, 0); p_evt->params.rx_data.length, NULL, 0);
} }

@ -110,15 +110,15 @@
18000 /**< The advertising duration (180 seconds) in units of 10 \ 18000 /**< The advertising duration (180 seconds) in units of 10 \
milliseconds. */ milliseconds. */
#define MIN_CONN_INTERVAL \ #define MIN_CONN_INTERVAL \
MSEC_TO_UNITS( \ MSEC_TO_UNITS( \
20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), \ 7.5, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), \
Connection interval uses 1.25 ms units. */ Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL \ #define MAX_CONN_INTERVAL \
MSEC_TO_UNITS( \ MSEC_TO_UNITS( \
75, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), \ 7.5, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), \
Connection interval uses 1.25 ms units. */ Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY 0 /**< Slave latency. */ #define SLAVE_LATENCY 0 /**< Slave latency. */
#define CONN_SUP_TIMEOUT \ #define CONN_SUP_TIMEOUT \
MSEC_TO_UNITS(4000, \ MSEC_TO_UNITS(4000, \
UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), \ UNIT_10_MS) /**< Connection supervisory timeout (4 seconds), \

@ -206,7 +206,7 @@ STATIC mp_obj_t mod_trezorio_poll(mp_obj_t ifaces, mp_obj_t list_ref,
} }
} else if (iface == BLE_IFACE_EXT) { } else if (iface == BLE_IFACE_EXT) {
if (mode == POLL_READ) { if (mode == POLL_READ) {
uint8_t buf[64] = {0}; uint8_t buf[BLE_PACKET_SIZE] = {0};
int len = ble_ext_comm_receive(buf, sizeof(buf)); int len = ble_ext_comm_receive(buf, sizeof(buf));
if (len > 0) { if (len > 0) {
ret->items[0] = MP_OBJ_NEW_SMALL_INT(i); ret->items[0] = MP_OBJ_NEW_SMALL_INT(i);

@ -26,8 +26,7 @@
#include "int_comm_defs.h" #include "int_comm_defs.h"
#include "state.h" #include "state.h"
#define SPI_PACKET_SIZE 64 #define SPI_QUEUE_SIZE 10
#define SPI_QUEUE_SIZE 4
static UART_HandleTypeDef urt; static UART_HandleTypeDef urt;
static uint8_t last_init_byte = 0; static uint8_t last_init_byte = 0;
@ -36,14 +35,17 @@ static SPI_HandleTypeDef spi = {0};
static DMA_HandleTypeDef spi_dma = {0}; static DMA_HandleTypeDef spi_dma = {0};
typedef struct { typedef struct {
uint8_t buffer[SPI_PACKET_SIZE]; uint8_t buffer[BLE_PACKET_SIZE];
bool used; bool used;
bool ready; bool ready;
} spi_buffer_t; } spi_buffer_t;
spi_buffer_t spi_queue[SPI_QUEUE_SIZE]; spi_buffer_t spi_queue[SPI_QUEUE_SIZE];
static int head = 0, tail = 0; static int head = 0, tail = 0;
static bool overrun = 1; static bool overrun = false;
volatile uint16_t overrun_count = 0;
volatile uint16_t msg_cntr = 0;
volatile uint16_t first_overrun_at = 0;
void ble_comm_init(void) { void ble_comm_init(void) {
GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitTypeDef GPIO_InitStructure;
@ -101,7 +103,10 @@ void ble_comm_init(void) {
set_initialized(false); set_initialized(false);
HAL_SPI_Receive_DMA(&spi, spi_queue[0].buffer, 64); HAL_SPI_Receive_DMA(&spi, spi_queue[0].buffer, BLE_PACKET_SIZE);
spi_queue[0].used = true;
tail = 0;
} }
void ble_comm_send(uint8_t *data, uint32_t len) { void ble_comm_send(uint8_t *data, uint32_t len) {
@ -291,25 +296,35 @@ uint32_t ble_int_comm_receive(uint8_t *data, uint32_t len) {
} }
bool start_spi_dma(void) { bool start_spi_dma(void) {
if (spi_queue[tail].used || spi_queue[tail].ready) { int tmp_tail = (tail + 1) % SPI_QUEUE_SIZE;
if (spi_queue[tmp_tail].used || spi_queue[tmp_tail].ready) {
overrun = true; overrun = true;
overrun_count++;
if (first_overrun_at == 0) {
first_overrun_at = msg_cntr;
}
return false; return false;
} }
spi_queue[tail].used = true; spi_queue[tmp_tail].used = true;
HAL_SPI_Receive_DMA(&spi, spi_queue[tail].buffer, SPI_PACKET_SIZE); HAL_SPI_Receive_DMA(&spi, spi_queue[tmp_tail].buffer, BLE_PACKET_SIZE);
tail = tmp_tail;
return true; return true;
} }
void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) { void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi) {
spi_queue[tail].ready = true; spi_queue[tail].ready = true;
tail = (tail + 1) % SPI_QUEUE_SIZE; msg_cntr++;
start_spi_dma(); start_spi_dma();
} }
#include "supervise.h"
uint32_t ble_ext_comm_receive(uint8_t *data, uint32_t len) { uint32_t ble_ext_comm_receive(uint8_t *data, uint32_t len) {
svc_disableIRQ(DMA2_Stream0_IRQn);
if (spi_queue[head].ready) { if (spi_queue[head].ready) {
uint8_t *buffer = (uint8_t *)spi_queue[head].buffer; uint8_t *buffer = (uint8_t *)spi_queue[head].buffer;
memcpy(data, buffer, len > SPI_PACKET_SIZE ? SPI_PACKET_SIZE : len); memcpy(data, buffer, len > BLE_PACKET_SIZE ? BLE_PACKET_SIZE : len);
spi_queue[head].used = false; spi_queue[head].used = false;
spi_queue[head].ready = false; spi_queue[head].ready = false;
@ -320,8 +335,26 @@ uint32_t ble_ext_comm_receive(uint8_t *data, uint32_t len) {
overrun = false; overrun = false;
} }
return len > SPI_PACKET_SIZE ? SPI_PACKET_SIZE : len; if (data[0] != '?') {
// bad packet, restart the DMA
HAL_SPI_Abort(&spi);
memset(spi_queue, 0, sizeof(spi_queue));
head = 0;
tail = 0;
overrun = false;
HAL_SPI_Receive_DMA(&spi, spi_queue[0].buffer, BLE_PACKET_SIZE);
spi_queue[0].used = true;
// todo return error?
svc_enableIRQ(DMA2_Stream0_IRQn);
return 0;
}
svc_enableIRQ(DMA2_Stream0_IRQn);
return len > BLE_PACKET_SIZE ? BLE_PACKET_SIZE : len;
} }
svc_enableIRQ(DMA2_Stream0_IRQn);
return 0; return 0;
} }

@ -2,6 +2,8 @@
#ifndef __INT_COMM_DEFS__ #ifndef __INT_COMM_DEFS__
#define __INT_COMM_DEFS__ #define __INT_COMM_DEFS__
#define BLE_PACKET_SIZE (244)
#define COMM_HEADER_SIZE (3) #define COMM_HEADER_SIZE (3)
#define COMM_FOOTER_SIZE (1) #define COMM_FOOTER_SIZE (1)
#define OVERHEAD_SIZE (COMM_HEADER_SIZE + COMM_FOOTER_SIZE) #define OVERHEAD_SIZE (COMM_HEADER_SIZE + COMM_FOOTER_SIZE)

@ -322,10 +322,14 @@ class Characteristic:
def read(self): def read(self):
return bytes(self._char.ReadValue({})) return bytes(self._char.ReadValue({}))
def write(self, value): def write(self, value, command=True):
start = time.time() start = time.time()
try: try:
self._char.WriteValue(value, {}) if command:
self._char.WriteValue(value, {"type": "command"})
else:
self._char.WriteValue(value, {"type": "request"})
except dbus.DBusException as e: except dbus.DBusException as e:
if ( if (
e.get_dbus_name() == "org.bluez.Error.Failed" e.get_dbus_name() == "org.bluez.Error.Failed"

@ -68,7 +68,7 @@ class BleTransport(ProtocolBasedTransport):
self.ble_device = d self.ble_device = d
break break
super().__init__(protocol=ProtocolV1(self)) super().__init__(protocol=ProtocolV1(self, replen=244))
def get_path(self) -> str: def get_path(self) -> str:
return "{}:{}".format(self.PATH_PREFIX, self.device) return "{}:{}".format(self.PATH_PREFIX, self.device)

@ -75,8 +75,9 @@ class Protocol:
its messages. its messages.
""" """
def __init__(self, handle: Handle) -> None: def __init__(self, handle: Handle, replen=REPLEN) -> None:
self.handle = handle self.handle = handle
self.replen = replen
self.session_counter = 0 self.session_counter = 0
# XXX we might be able to remove this now that TrezorClient does session handling # XXX we might be able to remove this now that TrezorClient does session handling
@ -133,10 +134,10 @@ class ProtocolV1(Protocol):
while buffer: while buffer:
# Report ID, data padded to 63 bytes # Report ID, data padded to 63 bytes
chunk = b"?" + buffer[: REPLEN - 1] chunk = b"?" + buffer[: self.replen - 1]
chunk = chunk.ljust(REPLEN, b"\x00") chunk = chunk.ljust(self.replen, b"\x00")
self.handle.write_chunk(chunk) self.handle.write_chunk(chunk)
buffer = buffer[63:] buffer = buffer[self.replen - 1 :]
def read(self) -> MessagePayload: def read(self) -> MessagePayload:
buffer = bytearray() buffer = bytearray()

Loading…
Cancel
Save