drivers/wireless/bluetooth: Default BAUD must be 115200, Fix logic in Rx callback, Rx callback must execute on work queue. Now sends and receives one command and response. But hangs on the next.

This commit is contained in:
Gregory Nutt 2018-04-17 13:07:28 -06:00
parent 021b4954d7
commit 27f624d881
4 changed files with 142 additions and 79 deletions

View File

@ -1223,6 +1223,37 @@ Configuration Sub-directories
configure a new U[S]ART and/or modify the pin selections in configure a new U[S]ART and/or modify the pin selections in
include/board.h. include/board.h.
4. Stack sizes are large and non-optimal. Don't judge memory usage
without tuning.
5. I tested using the Laird DVK_BT860. The BT860 defaults to 115200
BAUD but is capable of transfers up to 4M. The documentation says
that the part supports auto baudrate detection, but I have found no
documentation on how to use that.
Currently only a fixed, configurable BAUD is used and this must
be set to the BT860 default.
Baud rate can be set with vendor-specific command. Ideally, the
sequence would be: (1) start at default baud rate, (2) get local
version info, (3) send the vendor-specific baud rate change command,
(4) wait for response, and (5) set local UART to higher baud rate.
The custom, vendor-specific command is
{0x18, 0xfc, 0x06, 0x00, 0x00, NN, NN, NN, NN}
where {NN, NN, NN, NN} is the requested baud in little endian byte order.
If an initialization script is used then (5) then send initialization
scripts script. After sending the last command from the
initialization script, (6) reset the local UART. Finally, (7) send
vendor-specific baud rate change command, (8) wait for response, and
(9) set local UART to high baud rate.
The command to write the initialization script into NVRAM is another
story for another time and another place.
ipv6: ipv6:
---- ----
This is another version of the NuttShell configuration for the This is another version of the NuttShell configuration for the

View File

@ -74,7 +74,6 @@ CONFIG_START_MONTH=9
CONFIG_START_YEAR=2014 CONFIG_START_YEAR=2014
CONFIG_STM32_DMA2=y CONFIG_STM32_DMA2=y
CONFIG_STM32_DMACAPABLE=y CONFIG_STM32_DMACAPABLE=y
CONFIG_STM32_HCIUART3_BAUD=9600
CONFIG_STM32_JTAG_SW_ENABLE=y CONFIG_STM32_JTAG_SW_ENABLE=y
CONFIG_STM32_PWR=y CONFIG_STM32_PWR=y
CONFIG_STM32_SDIO=y CONFIG_STM32_SDIO=y

View File

@ -44,6 +44,7 @@ if DRIVERS_BLUETOOTH
config BLUETOOTH_UART config BLUETOOTH_UART
bool "Bluetooth UART driver" bool "Bluetooth UART driver"
default n default n
select SCHED_HPWORK
---help--- ---help---
Enable Bluetooth UART driver. Enable Bluetooth UART driver.

View File

@ -50,6 +50,7 @@
#include <errno.h> #include <errno.h>
#include <nuttx/kmalloc.h> #include <nuttx/kmalloc.h>
#include <nuttx/wqueue.h>
#include <nuttx/wireless/bt_core.h> #include <nuttx/wireless/bt_core.h>
#include <nuttx/wireless/bt_hci.h> #include <nuttx/wireless/bt_hci.h>
#include <nuttx/wireless/bt_driver.h> #include <nuttx/wireless/bt_driver.h>
@ -81,6 +82,11 @@ struct btuart_upperhalf_s
/* The cached lower half interface */ /* The cached lower half interface */
FAR const struct btuart_lowerhalf_s *lower; FAR const struct btuart_lowerhalf_s *lower;
/* Work queue support */
struct work_s work;
volatile bool busy;
}; };
/**************************************************************************** /****************************************************************************
@ -95,6 +101,9 @@ static ssize_t btuart_read(FAR struct btuart_upperhalf_s *upper,
ssize_t nread; ssize_t nread;
ssize_t ntotal = 0; ssize_t ntotal = 0;
wlinfo("buflen %lu minread %lu\n",
(unsigned long)buflen, (unsigned long)minread);
DEBUGASSERT(upper != NULL && upper->lower != NULL); DEBUGASSERT(upper != NULL && upper->lower != NULL);
lower = upper->lower; lower = upper->lower;
DEBUGASSERT(lower->read != NULL); DEBUGASSERT(lower->read != NULL);
@ -129,7 +138,7 @@ static ssize_t btuart_read(FAR struct btuart_upperhalf_s *upper,
} }
static FAR struct bt_buf_s *btuart_evt_recv(FAR struct btuart_upperhalf_s *upper, static FAR struct bt_buf_s *btuart_evt_recv(FAR struct btuart_upperhalf_s *upper,
FAR int *remaining) FAR unsigned int *hdrlen)
{ {
FAR struct bt_buf_s *buf; FAR struct bt_buf_s *buf;
struct bt_hci_evt_hdr_s hdr; struct bt_hci_evt_hdr_s hdr;
@ -141,13 +150,12 @@ static FAR struct bt_buf_s *btuart_evt_recv(FAR struct btuart_upperhalf_s *upper
sizeof(struct bt_hci_evt_hdr_s), sizeof(struct bt_hci_evt_hdr_s),
sizeof(struct bt_hci_evt_hdr_s)); sizeof(struct bt_hci_evt_hdr_s));
if (nread < 0) if (nread != sizeof(struct bt_hci_evt_hdr_s))
{ {
wlerr("ERROR: btuart_read returned %ld\n", (long)nread);
return NULL; return NULL;
} }
*remaining = hdr.len;
buf = bt_buf_alloc(BT_EVT, NULL, 0); buf = bt_buf_alloc(BT_EVT, NULL, 0);
if (buf != NULL) if (buf != NULL)
{ {
@ -159,12 +167,14 @@ static FAR struct bt_buf_s *btuart_evt_recv(FAR struct btuart_upperhalf_s *upper
wlerr("ERROR: No available event buffers!\n"); wlerr("ERROR: No available event buffers!\n");
} }
wlinfo("len %u\n", hdr.len); *hdrlen = (int)hdr.len;
wlinfo("hdrlen %u\n", hdr.len);
return buf; return buf;
} }
static FAR struct bt_buf_s *btuart_acl_recv(FAR struct btuart_upperhalf_s *upper, static FAR struct bt_buf_s *btuart_acl_recv(FAR struct btuart_upperhalf_s *upper,
FAR int *remaining) FAR unsigned int *hdrlen)
{ {
FAR struct bt_buf_s *buf; FAR struct bt_buf_s *buf;
struct bt_hci_acl_hdr_s hdr; struct bt_hci_acl_hdr_s hdr;
@ -176,13 +186,14 @@ static FAR struct bt_buf_s *btuart_acl_recv(FAR struct btuart_upperhalf_s *upper
sizeof(struct bt_hci_acl_hdr_s), sizeof(struct bt_hci_acl_hdr_s),
sizeof(struct bt_hci_acl_hdr_s)); sizeof(struct bt_hci_acl_hdr_s));
if (nread < 0) if (nread != sizeof(struct bt_hci_acl_hdr_s))
{ {
wlerr("ERROR: btuart_read returned %ld\n", (long)nread);
return NULL; return NULL;
} }
buf = bt_buf_alloc(BT_ACL_IN, NULL, 0); buf = bt_buf_alloc(BT_ACL_IN, NULL, 0);
if (buf) if (buf != NULL)
{ {
memcpy(bt_buf_extend(buf, sizeof(struct bt_hci_acl_hdr_s)), &hdr, memcpy(bt_buf_extend(buf, sizeof(struct bt_hci_acl_hdr_s)), &hdr,
sizeof(struct bt_hci_acl_hdr_s)); sizeof(struct bt_hci_acl_hdr_s));
@ -192,93 +203,114 @@ static FAR struct bt_buf_s *btuart_acl_recv(FAR struct btuart_upperhalf_s *upper
wlerr("ERROR: No available ACL buffers!\n"); wlerr("ERROR: No available ACL buffers!\n");
} }
*remaining = BT_LE162HOST(hdr.len); *hdrlen = BT_LE162HOST(hdr.len);
wlinfo("len %u\n", *remaining); wlinfo("hdrlen %u\n", *hdrlen);
return buf; return buf;
} }
static void btuart_rxwork(FAR void *arg)
{
FAR struct btuart_upperhalf_s *upper;
static FAR struct bt_buf_s *buf;
static unsigned int hdrlen;
static int remaining;
ssize_t nread;
uint8_t type;
upper = (FAR struct btuart_upperhalf_s *)arg;
DEBUGASSERT(upper != NULL);
/* Beginning of a new packet. Read the first byte to get the packet type. */
buf = NULL;
hdrlen = 0;
nread = btuart_read(upper, &type, 1, 0);
if (nread != 1)
{
wlwarn("WARNING: Unable to read H4 packet type: %ld\n",
(long)nread);
goto errout_with_busy;
}
switch (type)
{
case H4_EVT:
buf = btuart_evt_recv(upper, &hdrlen);
break;
case H4_ACL:
buf = btuart_acl_recv(upper, &hdrlen);
break;
default:
wlerr("ERROR: Unknown H4 type %u\n", type);
goto errout_with_busy;
}
if (buf == NULL)
{
FAR const struct btuart_lowerhalf_s *lower = upper->lower;
DEBUGASSERT(lower != NULL);
nread = lower->rxdrain(lower);
wlwarn("WARNING: Discarded %ld bytes\n", (long)nread);
goto errout_with_busy;
}
else if ((hdrlen - 1) > bt_buf_tailroom(buf))
{
wlerr("ERROR: Not enough space in buffer\n");
goto errout_with_buf;
}
remaining = hdrlen - 1;
wlinfo("Need to get %u of %u bytes\n", remaining, hdrlen);
while (remaining > 0)
{
nread = btuart_read(upper, bt_buf_tail(buf), remaining, 0);
wlinfo("Received %ld bytes\n", (long)nread);
buf->len += nread;
remaining -= nread;
}
/* Pass buffer to the stack */
wlinfo("Full packet received\n");
upper->busy = false;
bt_hci_receive(buf);
return;
errout_with_buf:
bt_buf_release(buf);
errout_with_busy:
upper->busy = false;
return;
}
static void btuart_rxcallback(FAR const struct btuart_lowerhalf_s *lower, static void btuart_rxcallback(FAR const struct btuart_lowerhalf_s *lower,
FAR void *arg) FAR void *arg)
{ {
FAR struct btuart_upperhalf_s *upper; FAR struct btuart_upperhalf_s *upper;
static FAR struct bt_buf_s *buf;
static int remaining;
ssize_t nread;
DEBUGASSERT(lower != NULL && lower->rxdrain != NULL && arg != NULL); DEBUGASSERT(lower != NULL && arg != NULL);
upper = (FAR struct btuart_upperhalf_s *)arg; upper = (FAR struct btuart_upperhalf_s *)arg;
/* Beginning of a new packet */ if (!upper->busy)
while (remaining > 0)
{ {
uint8_t type; int ret = work_queue(HPWORK, &upper->work, btuart_rxwork, arg, 0);
if (ret < 0)
/* Get packet type */
nread = btuart_read(upper, &type, 1, 0);
if (nread != sizeof(type))
{ {
wlwarn("WARNING: Unable to read H4 packet type\n"); wlerr("ERROR: work_queue failed: %d\n", ret);
continue;
} }
else
switch (type)
{ {
case H4_EVT: upper->busy = true;
buf = btuart_evt_recv(upper, &remaining);
break;
case H4_ACL:
buf = btuart_acl_recv(upper, &remaining);
break;
default:
wlerr("ERROR: Unknown H4 type %u\n", type);
return;
} }
if (buf != NULL && remaining > bt_buf_tailroom(buf))
{
wlerr("ERROR: Not enough space in buffer\n");
goto failed;
}
wlinfo("Need to get %u bytes\n", remaining);
} }
if (buf == NULL)
{
nread = lower->rxdrain(lower);
wlwarn("WARNING: Discarded %ld bytes\n", (long)nread);
remaining -= nread;
}
nread = btuart_read(upper, bt_buf_tail(buf), remaining, 0);
buf->len += nread;
remaining -= nread;
wlinfo("Received %ld bytes\n", (long)nread);
if (remaining == 0)
{
wlinfo("Full packet received\n");
/* Pass buffer to the stack */
bt_hci_receive(buf);
buf = NULL;
}
return;
failed:
bt_buf_release(buf);
remaining = 0;
buf = NULL;
return;
} }
static int btuart_send(FAR const struct bt_driver_s *dev, static int btuart_send(FAR const struct bt_driver_s *dev,