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 <andrei.emeltchenko@intel.com>
This commit is contained in:
Andrei Emeltchenko 2016-01-21 15:36:47 +02:00 committed by Anas Nashif
commit 702b151e47
3 changed files with 28 additions and 177 deletions

View file

@ -24,6 +24,8 @@
#include <bluetooth/conn.h> #include <bluetooth/conn.h>
#include <bluetooth/log.h> #include <bluetooth/log.h>
#include <net/buf.h>
#include "gap_internal.h" #include "gap_internal.h"
#include "uart.h" #include "uart.h"
#include "rpc.h" #include "rpc.h"
@ -32,40 +34,6 @@
#define NBLE_RESET_PIN NBLE_SWDIO_PIN #define NBLE_RESET_PIN NBLE_SWDIO_PIN
#define NBLE_BTWAKE_PIN 5 #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; static bt_ready_cb_t bt_ready_cb;
void on_nble_up(void) void on_nble_up(void)
@ -142,10 +110,6 @@ int bt_enable(bt_ready_cb_t cb)
return -EINVAL; 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(); ret = nble_open();
if (ret) { if (ret) {
return ret; return ret;

View file

@ -28,6 +28,7 @@
#include <bluetooth/log.h> #include <bluetooth/log.h>
#include "uart.h" #include "uart.h"
#include "rpc.h"
/* TODO: check size */ /* TODO: check size */
#define NBLE_IPC_COUNT 1 #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 struct nano_fifo tx;
static NET_BUF_POOL(tx_pool, NBLE_IPC_COUNT, NBLE_BUF_SIZE, &tx, NULL, 0); static NET_BUF_POOL(tx_pool, NBLE_IPC_COUNT, NBLE_BUF_SIZE, &tx, NULL, 0);
enum { static BT_STACK_NOINIT(rx_fiber_stack, 256);
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 struct device *nble_dev; 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) uint8_t *rpc_alloc_cb(uint16_t length)
{ {
struct net_buf *buf; struct net_buf *buf;
@ -137,22 +112,6 @@ void rpc_transmit_cb(uint8_t *p_buf, uint16_t length)
net_buf_unref(buf); 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, static int nble_read(struct device *uart, uint8_t *buf,
size_t len, size_t min) size_t len, size_t min)
{ {
@ -265,84 +224,20 @@ void bt_uart_isr(void *unused)
BT_DBG("full packet received"); BT_DBG("full packet received");
/* Pass buffer to the stack */ /* Pass buffer to the stack */
uart_frame_recv(buf->len, buf->data); nano_fifo_put(&rx_queue, buf);
net_buf_unref(buf);
buf = NULL;
} }
} }
} }
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) int nble_open(void)
{ {
BT_DBG(""); 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_rx_disable(nble_dev);
uart_irq_tx_disable(nble_dev); uart_irq_tx_disable(nble_dev);
@ -362,8 +257,6 @@ int nble_open(void)
return 0; return 0;
} }
struct ipc_uart_info info;
static int _bt_nble_init(struct device *unused) static int _bt_nble_init(struct device *unused)
{ {
ARG_UNUSED(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(rx_pool);
net_buf_pool_init(tx_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; return DEV_OK;
} }

View file

@ -52,8 +52,6 @@ struct ipc_uart_channels {
int (*cb)(int chan, int request, int len, void *data); 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); int nble_open(void);
/** /**