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>
This commit is contained in:
parent
d324f357ee
commit
24730069ab
1 changed files with 22 additions and 52 deletions
|
@ -118,32 +118,6 @@ void rpc_transmit_cb(struct net_buf *buf)
|
||||||
net_buf_unref(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)
|
static size_t nble_discard(struct device *uart, size_t len)
|
||||||
{
|
{
|
||||||
/* FIXME: correct size for nble */
|
/* 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)
|
void bt_uart_isr(void *unused)
|
||||||
{
|
{
|
||||||
static struct net_buf *buf;
|
static struct net_buf *buf;
|
||||||
static int remaining;
|
|
||||||
|
|
||||||
ARG_UNUSED(unused);
|
ARG_UNUSED(unused);
|
||||||
|
|
||||||
while (uart_irq_update(nble_dev) && uart_irq_is_pending(nble_dev)) {
|
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;
|
int read;
|
||||||
|
|
||||||
if (!uart_irq_rx_ready(nble_dev)) {
|
if (!uart_irq_rx_ready(nble_dev)) {
|
||||||
|
@ -178,47 +153,42 @@ void bt_uart_isr(void *unused)
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Beginning of a new packet */
|
if (hdr_bytes < sizeof(hdr)) {
|
||||||
if (!remaining) {
|
|
||||||
struct ipc_uart_header hdr;
|
|
||||||
|
|
||||||
/* Get packet type */
|
/* Get packet type */
|
||||||
read = nble_read(nble_dev, (uint8_t *)&hdr,
|
hdr_bytes += uart_fifo_read(nble_dev,
|
||||||
sizeof(hdr), sizeof(hdr));
|
(uint8_t *)&hdr + hdr_bytes,
|
||||||
if (read != sizeof(hdr)) {
|
sizeof(hdr) - hdr_bytes);
|
||||||
BT_WARN("Unable to read NBLE header");
|
if (hdr_bytes < sizeof(hdr)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
remaining = hdr.len;
|
if (hdr.len > NBLE_BUF_SIZE) {
|
||||||
|
BT_ERR("Too much data to fit buffer");
|
||||||
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);
|
|
||||||
buf = NULL;
|
buf = NULL;
|
||||||
|
} else {
|
||||||
|
buf = net_buf_get(&rx, 0);
|
||||||
|
if (!buf) {
|
||||||
|
BT_ERR("No available IPC buffers");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
read = nble_discard(nble_dev, remaining);
|
hdr.len -= nble_discard(nble_dev, hdr.len);
|
||||||
BT_WARN("Discarded %d bytes", read);
|
if (!hdr.len) {
|
||||||
remaining -= read;
|
hdr_bytes = 0;
|
||||||
|
}
|
||||||
continue;
|
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;
|
buf->len += read;
|
||||||
remaining -= read;
|
hdr.len -= read;
|
||||||
|
|
||||||
if (!remaining) {
|
if (!hdr.len) {
|
||||||
BT_DBG("full packet received");
|
BT_DBG("full packet received");
|
||||||
|
hdr_bytes = 0;
|
||||||
/* Pass buffer to the stack */
|
/* Pass buffer to the stack */
|
||||||
nano_fifo_put(&rx_queue, buf);
|
nano_fifo_put(&rx_queue, buf);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue