summaryrefslogtreecommitdiff
path: root/drivers/nble
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2016-02-12 12:06:08 +0200
committerGerrit Code Review <gerrit@zephyrproject.org>2016-02-12 11:01:04 +0000
commit24730069aba6daf509c0558a9ca0d5827c7c5695 (patch)
treeb0396e8997a968ef638d028fe8f4ad6c372bc96d /drivers/nble
parentd324f357ee59aced1fff2d73a6ccef9ebfd730a4 (diff)
drivers/nble: Make UART reading more robust
Don't require being able to read the full header in a single ISR call. Instead track the number of received header bytes. Also check for IPC length before allocating buffer to avoid unnecessary buffer allocations. Change-Id: I1678c3ac3aaf35a1b9bbe930cc2e942fce3f458a Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Diffstat (limited to 'drivers/nble')
-rw-r--r--drivers/nble/uart.c74
1 files changed, 22 insertions, 52 deletions
diff --git a/drivers/nble/uart.c b/drivers/nble/uart.c
index 2ad95c194..7c288465c 100644
--- a/drivers/nble/uart.c
+++ b/drivers/nble/uart.c
@@ -118,32 +118,6 @@ void rpc_transmit_cb(struct net_buf *buf)
net_buf_unref(buf);
}
-static int nble_read(struct device *uart, uint8_t *buf,
- size_t len, size_t min)
-{
- int total = 0;
- int tries = 10;
-
- while (len) {
- int rx;
-
- rx = uart_fifo_read(uart, buf, len);
- if (rx == 0) {
- BT_DBG("Got zero bytes from UART");
- if (total < min && tries--) {
- continue;
- }
- break;
- }
-
- len -= rx;
- total += rx;
- buf += rx;
- }
-
- return total;
-}
-
static size_t nble_discard(struct device *uart, size_t len)
{
/* FIXME: correct size for nble */
@@ -155,11 +129,12 @@ static size_t nble_discard(struct device *uart, size_t len)
void bt_uart_isr(void *unused)
{
static struct net_buf *buf;
- static int remaining;
ARG_UNUSED(unused);
while (uart_irq_update(nble_dev) && uart_irq_is_pending(nble_dev)) {
+ static struct ipc_uart_header hdr;
+ static uint8_t hdr_bytes;
int read;
if (!uart_irq_rx_ready(nble_dev)) {
@@ -178,47 +153,42 @@ void bt_uart_isr(void *unused)
continue;
}
- /* Beginning of a new packet */
- if (!remaining) {
- struct ipc_uart_header hdr;
-
+ if (hdr_bytes < sizeof(hdr)) {
/* Get packet type */
- read = nble_read(nble_dev, (uint8_t *)&hdr,
- sizeof(hdr), sizeof(hdr));
- if (read != sizeof(hdr)) {
- BT_WARN("Unable to read NBLE header");
+ hdr_bytes += uart_fifo_read(nble_dev,
+ (uint8_t *)&hdr + hdr_bytes,
+ sizeof(hdr) - hdr_bytes);
+ if (hdr_bytes < sizeof(hdr)) {
continue;
}
- remaining = hdr.len;
-
- buf = net_buf_get(&rx, 0);
- if (!buf) {
- BT_ERR("No available IPC buffers");
- }
-
- if (buf && remaining > net_buf_tailroom(buf)) {
- BT_ERR("Not enough space in buffer");
- net_buf_unref(buf);
+ if (hdr.len > NBLE_BUF_SIZE) {
+ BT_ERR("Too much data to fit buffer");
buf = NULL;
+ } else {
+ buf = net_buf_get(&rx, 0);
+ if (!buf) {
+ BT_ERR("No available IPC buffers");
+ }
}
}
if (!buf) {
- read = nble_discard(nble_dev, remaining);
- BT_WARN("Discarded %d bytes", read);
- remaining -= read;
+ hdr.len -= nble_discard(nble_dev, hdr.len);
+ if (!hdr.len) {
+ hdr_bytes = 0;
+ }
continue;
}
- read = nble_read(nble_dev, net_buf_tail(buf), remaining, 0);
+ read = uart_fifo_read(nble_dev, net_buf_tail(buf), hdr.len);
buf->len += read;
- remaining -= read;
+ hdr.len -= read;
- if (!remaining) {
+ if (!hdr.len) {
BT_DBG("full packet received");
-
+ hdr_bytes = 0;
/* Pass buffer to the stack */
nano_fifo_put(&rx_queue, buf);
}