diff --git a/configs/stm32f4discovery/README.txt b/configs/stm32f4discovery/README.txt index b70acbe379..e0224bad48 100644 --- a/configs/stm32f4discovery/README.txt +++ b/configs/stm32f4discovery/README.txt @@ -1223,6 +1223,37 @@ Configuration Sub-directories configure a new U[S]ART and/or modify the pin selections in 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: ---- This is another version of the NuttShell configuration for the diff --git a/configs/stm32f4discovery/hciuart/defconfig b/configs/stm32f4discovery/hciuart/defconfig index 5f1a82f7e5..033acfb114 100644 --- a/configs/stm32f4discovery/hciuart/defconfig +++ b/configs/stm32f4discovery/hciuart/defconfig @@ -74,7 +74,6 @@ CONFIG_START_MONTH=9 CONFIG_START_YEAR=2014 CONFIG_STM32_DMA2=y CONFIG_STM32_DMACAPABLE=y -CONFIG_STM32_HCIUART3_BAUD=9600 CONFIG_STM32_JTAG_SW_ENABLE=y CONFIG_STM32_PWR=y CONFIG_STM32_SDIO=y diff --git a/drivers/wireless/bluetooth/Kconfig b/drivers/wireless/bluetooth/Kconfig index 04794b1b47..95def2b1d7 100644 --- a/drivers/wireless/bluetooth/Kconfig +++ b/drivers/wireless/bluetooth/Kconfig @@ -44,6 +44,7 @@ if DRIVERS_BLUETOOTH config BLUETOOTH_UART bool "Bluetooth UART driver" default n + select SCHED_HPWORK ---help--- Enable Bluetooth UART driver. diff --git a/drivers/wireless/bluetooth/bt_uart.c b/drivers/wireless/bluetooth/bt_uart.c index 986a92865d..b6f37a51ca 100644 --- a/drivers/wireless/bluetooth/bt_uart.c +++ b/drivers/wireless/bluetooth/bt_uart.c @@ -50,6 +50,7 @@ #include #include +#include #include #include #include @@ -81,6 +82,11 @@ struct btuart_upperhalf_s /* The cached lower half interface */ 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 ntotal = 0; + wlinfo("buflen %lu minread %lu\n", + (unsigned long)buflen, (unsigned long)minread); + DEBUGASSERT(upper != NULL && upper->lower != NULL); lower = upper->lower; 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, - FAR int *remaining) + FAR unsigned int *hdrlen) { FAR struct bt_buf_s *buf; 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)); - if (nread < 0) + if (nread != sizeof(struct bt_hci_evt_hdr_s)) { + wlerr("ERROR: btuart_read returned %ld\n", (long)nread); return NULL; } - *remaining = hdr.len; - buf = bt_buf_alloc(BT_EVT, NULL, 0); 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"); } - wlinfo("len %u\n", hdr.len); + *hdrlen = (int)hdr.len; + + wlinfo("hdrlen %u\n", hdr.len); return buf; } 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; 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)); - if (nread < 0) + if (nread != sizeof(struct bt_hci_acl_hdr_s)) { + wlerr("ERROR: btuart_read returned %ld\n", (long)nread); return NULL; } 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, 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"); } - *remaining = BT_LE162HOST(hdr.len); + *hdrlen = BT_LE162HOST(hdr.len); - wlinfo("len %u\n", *remaining); + wlinfo("hdrlen %u\n", *hdrlen); 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, FAR void *arg) { 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; - /* Beginning of a new packet */ - - while (remaining > 0) + if (!upper->busy) { - uint8_t type; - - /* Get packet type */ - - nread = btuart_read(upper, &type, 1, 0); - if (nread != sizeof(type)) + int ret = work_queue(HPWORK, &upper->work, btuart_rxwork, arg, 0); + if (ret < 0) { - wlwarn("WARNING: Unable to read H4 packet type\n"); - continue; + wlerr("ERROR: work_queue failed: %d\n", ret); } - - switch (type) + else { - case H4_EVT: - 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; + upper->busy = true; } - - 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,