From 702b151e47ccea62ac17a1afceb30d38baecef8a Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Thu, 21 Jan 2016 15:36:47 +0200 Subject: [PATCH] Bluetooth: nble: Move receive logic to fiber Move receiving logic to fiber rx_fiber(). rx_queue is registered with uart driver and all data is sent there for processing. Clean up old ipc_channel interface since there will be only one interface to uart driver. Change-Id: I292863b1f38e5adb8ca4e6ac63aed09c83de56bf Signed-off-by: Andrei Emeltchenko --- drivers/nble/gap.c | 40 +---------- drivers/nble/uart.c | 163 +++++++------------------------------------- drivers/nble/uart.h | 2 - 3 files changed, 28 insertions(+), 177 deletions(-) diff --git a/drivers/nble/gap.c b/drivers/nble/gap.c index af45f5db195..7d0f04a4ecf 100644 --- a/drivers/nble/gap.c +++ b/drivers/nble/gap.c @@ -24,6 +24,8 @@ #include #include +#include + #include "gap_internal.h" #include "uart.h" #include "rpc.h" @@ -32,40 +34,6 @@ #define NBLE_RESET_PIN NBLE_SWDIO_PIN #define NBLE_BTWAKE_PIN 5 -#define NBLE_CHANNEL 0 - -static void *channel; - -/** - * Function handling the events from the UART IPC (irq). - * - * @param channel Channel on which the event applies - * @param request IPC_MSG_TYPE_MESSAGE when a new message was received, - * IPC_MSG_TYPE_FREE when the previous message was sent and can be freed. - * @param len Length of the data - * @param p_data Pointer to the data - * @return 0 - */ -static int recv_cb(int channel, int request, int len, void *p_data) -{ - BT_DBG("channel %d request %d len %d", channel, request, len); - - switch (request) { - case IPC_MSG_TYPE_MESSAGE: - rpc_deserialize(p_data, len); - break; - case IPC_MSG_TYPE_FREE: - /* TODO: Try to send another message immediately */ - break; - default: - /* Free the message */ - BT_ERR("Unsupported RPC request"); - break; - } - - return 0; -} - static bt_ready_cb_t bt_ready_cb; void on_nble_up(void) @@ -142,10 +110,6 @@ int bt_enable(bt_ready_cb_t cb) return -EINVAL; } - /* Open the UART channel for RPC while Nordic is in reset */ - channel = ipc_uart_channel_open(NBLE_CHANNEL, recv_cb); - BT_DBG("channel %p", channel); - ret = nble_open(); if (ret) { return ret; diff --git a/drivers/nble/uart.c b/drivers/nble/uart.c index c4a19721fce..95b429b376d 100644 --- a/drivers/nble/uart.c +++ b/drivers/nble/uart.c @@ -28,6 +28,7 @@ #include #include "uart.h" +#include "rpc.h" /* TODO: check size */ #define NBLE_IPC_COUNT 1 @@ -39,54 +40,28 @@ static NET_BUF_POOL(rx_pool, NBLE_IPC_COUNT, NBLE_BUF_SIZE, &rx, NULL, 0); static struct nano_fifo tx; static NET_BUF_POOL(tx_pool, NBLE_IPC_COUNT, NBLE_BUF_SIZE, &tx, NULL, 0); -enum { - STATUS_TX_IDLE = 0, - STATUS_TX_BUSY, - STATUS_TX_DONE, -}; - -enum { - STATUS_RX_IDLE = 0, - STATUS_RX_HDR, - STATUS_RX_DATA -}; - -/** - * Describes the uart IPC to handle - */ -struct ipc_uart_info { - int uart_num; /* UART device to use */ - uint32_t irq_vector; /* IRQ number */ - uint32_t irq_mask; /* IRQ mask */ - - /* callback to be called to set wake state when TX is starting - * or ending - */ - void (*tx_cb)(bool wake_state, void*); - void *tx_cb_param; /* tx_cb function parameter */ -}; - -struct ipc_uart { - uint8_t *tx_data; - uint8_t *rx_ptr; - struct ipc_uart_channels channels[IPC_UART_MAX_CHANNEL]; - struct ipc_uart_header tx_hdr; - struct ipc_uart_header rx_hdr; - uint16_t send_counter; - uint16_t rx_size; - uint8_t tx_state; - uint8_t rx_state; - uint8_t uart_enabled; - /* protect against multiple wakelock and wake assert calls */ - uint8_t tx_wakelock_acquired; - /* TODO: remove once IRQ will take a parameter */ - struct device *device; -}; - -static struct ipc_uart ipc; +static BT_STACK_NOINIT(rx_fiber_stack, 256); static struct device *nble_dev; +static struct nano_fifo rx_queue; + +static void rx_fiber(void) +{ + BT_DBG("Started"); + + while (true) { + struct net_buf *buf; + + buf = nano_fifo_get(&rx_queue, TICKS_UNLIMITED); + BT_DBG("Got buf %p", buf); + + rpc_deserialize(buf->data, buf->len); + + net_buf_unref(buf); + } +} + uint8_t *rpc_alloc_cb(uint16_t length) { struct net_buf *buf; @@ -137,22 +112,6 @@ void rpc_transmit_cb(uint8_t *p_buf, uint16_t length) net_buf_unref(buf); } -static void uart_frame_recv(uint16_t len, uint8_t *p_data) -{ - BT_DBG("rcv: len: %d data len %d src %d channel %d", - ipc.rx_hdr.len, len, ipc.rx_hdr.src_cpu_id, ipc.rx_hdr.channel); - - if ((ipc.rx_hdr.channel < IPC_UART_MAX_CHANNEL) && - (ipc.channels[ipc.rx_hdr.channel].cb != NULL)) { - ipc.channels[ipc.rx_hdr.channel].cb(ipc.rx_hdr.channel, - IPC_MSG_TYPE_MESSAGE, - len, - p_data); - } else { - BT_ERR("uart_ipc: bad channel %d", ipc.rx_hdr.channel); - } -} - static int nble_read(struct device *uart, uint8_t *buf, size_t len, size_t min) { @@ -265,84 +224,20 @@ void bt_uart_isr(void *unused) BT_DBG("full packet received"); /* Pass buffer to the stack */ - uart_frame_recv(buf->len, buf->data); - net_buf_unref(buf); - buf = NULL; + nano_fifo_put(&rx_queue, buf); } } } -void *ipc_uart_channel_open(int channel_id, - int (*cb)(int, int, int, void *)) -{ - struct ipc_uart_channels *chan; - - if (channel_id > (IPC_UART_MAX_CHANNEL - 1)) - return NULL; - - chan = &ipc.channels[channel_id]; - - if (chan->state != IPC_CHANNEL_STATE_CLOSED) - return NULL; - - chan->state = IPC_CHANNEL_STATE_OPEN; - chan->cb = cb; - - ipc.uart_enabled = 1; - - return chan; -} - -void ipc_uart_close_channel(int channel_id) -{ - ipc.channels[channel_id].state = IPC_CHANNEL_STATE_CLOSED; - ipc.channels[channel_id].cb = NULL; - ipc.channels[channel_id].index = channel_id; - - ipc.uart_enabled = 0; -} - -void ipc_uart_ns16550_set_tx_cb(struct device *dev, void (*cb)(bool, void*), - void *param) -{ - struct ipc_uart_info *info = dev->driver_data; - - info->tx_cb = cb; - info->tx_cb_param = param; -} - -static int ipc_uart_ns16550_init(struct device *dev) -{ - struct ipc_uart_info *info = dev->driver_data; - int i; - - /* Fail init if no info defined */ - if (!info) { - BT_ERR("No driver data found"); - return -1; - } - - for (i = 0; i < IPC_UART_MAX_CHANNEL; i++) { - ipc_uart_close_channel(i); - } - - /* Set dev used in irq handler */ - ipc.device = dev; - - ipc.uart_enabled = 0; - - /* Initialize the reception pointer */ - ipc.rx_size = sizeof(ipc.rx_hdr); - ipc.rx_ptr = (uint8_t *)&ipc.rx_hdr; - ipc.rx_state = STATUS_RX_IDLE; - - return 0; -} - int nble_open(void) { BT_DBG(""); + /* Initialize receive queue and start rx_fiber */ + nano_fifo_init(&rx_queue); + fiber_start(rx_fiber_stack, sizeof(rx_fiber_stack), + (nano_fiber_entry_t)rx_fiber, 0, 0, 7, 0); + uart_irq_rx_disable(nble_dev); uart_irq_tx_disable(nble_dev); @@ -362,8 +257,6 @@ int nble_open(void) return 0; } -struct ipc_uart_info info; - static int _bt_nble_init(struct device *unused) { ARG_UNUSED(unused); @@ -376,10 +269,6 @@ static int _bt_nble_init(struct device *unused) net_buf_pool_init(rx_pool); net_buf_pool_init(tx_pool); - nble_dev->driver_data = &info; - ipc_uart_ns16550_init(nble_dev); - /* TODO: Register nble driver */ - return DEV_OK; } diff --git a/drivers/nble/uart.h b/drivers/nble/uart.h index 1389d42aa43..346072bafbb 100644 --- a/drivers/nble/uart.h +++ b/drivers/nble/uart.h @@ -52,8 +52,6 @@ struct ipc_uart_channels { int (*cb)(int chan, int request, int len, void *data); }; -void ipc_uart_isr(void); -void ipc_uart_ns16550_disable(struct device *dev); int nble_open(void); /**