Initial commit for hci_uart
This commit is contained in:
6
.gitignore
vendored
Normal file
6
.gitignore
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
# editors
|
||||
*.swp
|
||||
*~
|
||||
|
||||
# build
|
||||
/build*/
|
||||
8
CMakeLists.txt
Normal file
8
CMakeLists.txt
Normal file
@@ -0,0 +1,8 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
cmake_minimum_required(VERSION 3.20.0)
|
||||
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
project(hci_uart)
|
||||
|
||||
target_sources(app PRIVATE src/main.c)
|
||||
202
README.rst
Normal file
202
README.rst
Normal file
@@ -0,0 +1,202 @@
|
||||
.. zephyr:code-sample:: bluetooth_hci_uart
|
||||
:name: HCI UART
|
||||
:relevant-api: hci_raw bluetooth uart_interface
|
||||
|
||||
Expose a Bluetooth controller to another device or CPU over UART.
|
||||
|
||||
Overview
|
||||
*********
|
||||
|
||||
Expose Bluetooth controller support over UART to another device/CPU
|
||||
using the H:4 HCI transport protocol (requires HW flow control from the UART).
|
||||
|
||||
Requirements
|
||||
************
|
||||
|
||||
* A board with Bluetooth LE support
|
||||
|
||||
Default UART settings
|
||||
*********************
|
||||
|
||||
By default the controller builds use the following settings:
|
||||
|
||||
* Baudrate: 1Mbit/s
|
||||
* 8 bits, no parity, 1 stop bit
|
||||
* Hardware Flow Control (RTS/CTS) enabled
|
||||
|
||||
Building and Running
|
||||
********************
|
||||
|
||||
This sample can be found under :zephyr_file:`samples/bluetooth/hci_uart` in the
|
||||
Zephyr tree, and it is built as a standard Zephyr application.
|
||||
|
||||
Using the controller with emulators and BlueZ
|
||||
*********************************************
|
||||
|
||||
The instructions below show how to use a Nordic nRF5x device as a Zephyr BLE
|
||||
controller and expose it to Linux's BlueZ. This can be very useful for testing
|
||||
the Zephyr Link Layer with the BlueZ Host. The Zephyr Bluetooth LE controller can also
|
||||
provide a modern Bluetooth LE 5.0 controller to a Linux-based machine for native
|
||||
BLE support or QEMU-based development.
|
||||
|
||||
First, make sure you have a recent BlueZ version installed by following the
|
||||
instructions in the :ref:`bluetooth_bluez` section.
|
||||
|
||||
Now build and flash the sample for the Nordic nRF5x board of your choice.
|
||||
All of the Nordic Development Kits come with a Segger IC that provides a
|
||||
debugger interface and a CDC ACM serial port bridge. More information can be
|
||||
found in :ref:`nordic_segger`.
|
||||
|
||||
For example, to build for the nRF52832 Development Kit:
|
||||
|
||||
.. zephyr-app-commands::
|
||||
:zephyr-app: samples/bluetooth/hci_uart
|
||||
:board: nrf52dk/nrf52832
|
||||
:goals: build flash
|
||||
|
||||
.. _bluetooth-hci-uart-qemu-posix:
|
||||
|
||||
Using the controller with QEMU or native_sim
|
||||
============================================
|
||||
|
||||
In order to use the HCI UART controller with QEMU or :ref:`native_sim <native_sim>` you will need
|
||||
to attach it to the Linux Host first. To do so simply build the sample and
|
||||
connect the UART to the Linux machine, and then attach it with this command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
sudo btattach -B /dev/ttyACM0 -S 1000000 -R
|
||||
|
||||
.. note::
|
||||
Depending on the serial port you are using you will need to modify the
|
||||
``/dev/ttyACM0`` string to point to the serial device your controller is
|
||||
connected to.
|
||||
|
||||
.. note::
|
||||
If using the BBC micro:bit you will need to modify the baudrate argument
|
||||
from ``1000000`` to ``115200``.
|
||||
|
||||
.. note::
|
||||
The ``-R`` flag passed to ``btattach`` instructs the kernel to avoid
|
||||
interacting with the controller and instead just be aware of it in order
|
||||
to proxy it to QEMU later.
|
||||
|
||||
If you are running :file:`btmon` you should see a brief log showing how the
|
||||
Linux kernel identifies the attached controller.
|
||||
|
||||
Once the controller is attached follow the instructions in the
|
||||
:ref:`bluetooth_qemu_native` section to use QEMU with it.
|
||||
|
||||
.. _bluetooth-hci-uart-bluez:
|
||||
|
||||
Using the controller with BlueZ
|
||||
===============================
|
||||
|
||||
In order to use the HCI UART controller with BlueZ you will need to attach it
|
||||
to the Linux Host first. To do so simply build the sample and connect the
|
||||
UART to the Linux machine, and then attach it with this command:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
sudo btattach -B /dev/ttyACM0 -S 1000000
|
||||
|
||||
.. note::
|
||||
Depending on the serial port you are using you will need to modify the
|
||||
``/dev/ttyACM0`` string to point to the serial device your controller is
|
||||
connected to.
|
||||
|
||||
.. note::
|
||||
If using the BBC micro:bit you will need to modify the baudrate argument
|
||||
from ``1000000`` to ``115200``.
|
||||
|
||||
If you are running :file:`btmon` you should see a comprehensive log showing how
|
||||
BlueZ loads and initializes the attached controller.
|
||||
|
||||
Once the controller is attached follow the instructions in the
|
||||
:ref:`bluetooth_ctlr_bluez` section to use BlueZ with it.
|
||||
|
||||
Debugging the controller
|
||||
========================
|
||||
|
||||
The sample can be debugged using RTT since the UART is otherwise used by this
|
||||
application. To enable debug over RTT the debug configuration file can be used.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
west build samples/bluetooth/hci_uart -- -DEXTRA_CONF_FILE='debug.conf'
|
||||
|
||||
Then attach RTT as described here: :ref:`Using Segger J-Link <Using Segger J-Link>`
|
||||
|
||||
Support for the Direction Finding
|
||||
=================================
|
||||
|
||||
The sample can be built with the support for the Bluetooth LE Direction Finding.
|
||||
To enable this feature build this sample for specific board variants that provide
|
||||
required hardware configuration for the Radio.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
west build samples/bluetooth/hci_uart -b nrf52833dk/nrf52833@df -- -DCONFIG_BT_CTLR_DF=y
|
||||
|
||||
You can use following targets:
|
||||
|
||||
* ``nrf5340dk/nrf5340/cpunet@df``
|
||||
* ``nrf52833dk/nrf52833@df``
|
||||
|
||||
Check the :zephyr:code-sample:`ble_direction_finding_connectionless_rx` and the
|
||||
:zephyr:code-sample:`ble_direction_finding_connectionless_tx` for more details.
|
||||
|
||||
Using a USB CDC ACM UART
|
||||
========================
|
||||
|
||||
The sample can be configured to use a USB UART instead. See :zephyr_file:`samples/bluetooth/hci_uart/boards/nrf52840dongle_nrf52840.conf` and :zephyr_file:`samples/bluetooth/hci_uart/boards/nrf52840dongle_nrf52840.overlay`.
|
||||
|
||||
Using the controller with the Zephyr host
|
||||
=========================================
|
||||
|
||||
This describes how to hook up a board running this sample to a board running
|
||||
an application that uses the Zephyr host.
|
||||
|
||||
On the controller side, the ``zephyr,bt-c2h-uart`` DTS property (in the ``chosen``
|
||||
block) is used to select which uart device to use. For example if we want to
|
||||
keep the console logs, we can keep console on uart0 and the HCI on uart1 like
|
||||
so:
|
||||
|
||||
.. code-block:: dts
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,console = &uart0;
|
||||
zephyr,shell-uart = &uart0;
|
||||
zephyr,bt-c2h-uart = &uart1;
|
||||
};
|
||||
};
|
||||
|
||||
On the host application, some config options need to be used to select the H4
|
||||
driver instead of the built-in controller:
|
||||
|
||||
.. code-block:: cfg
|
||||
|
||||
CONFIG_BT_HCI=y
|
||||
CONFIG_BT_CTLR=n
|
||||
|
||||
Similarly, the ``zephyr,bt-hci`` DTS property selects which HCI instance to use.
|
||||
The UART needs to have as its child node a HCI UART node:
|
||||
|
||||
.. code-block:: dts
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,console = &uart0;
|
||||
zephyr,shell-uart = &uart0;
|
||||
zephyr,bt-hci = &bt_hci_uart;
|
||||
};
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
bt_hci_uart: bt_hci_uart {
|
||||
compatible = "zephyr,bt-hci-uart";
|
||||
status = "okay";
|
||||
};
|
||||
};
|
||||
8
boards/96b_nitrogen.overlay
Normal file
8
boards/96b_nitrogen.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uart";
|
||||
current-speed = <1000000>;
|
||||
hw-flow-control;
|
||||
status = "okay";
|
||||
};
|
||||
8
boards/bbc_microbit.conf
Normal file
8
boards/bbc_microbit.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
CONFIG_MAIN_STACK_SIZE=512
|
||||
CONFIG_IDLE_STACK_SIZE=256
|
||||
CONFIG_ISR_STACK_SIZE=512
|
||||
CONFIG_BT_MAX_CONN=10
|
||||
# Revert values set in prj.conf, set them to their Kconfig default value
|
||||
CONFIG_BT_BUF_CMD_TX_SIZE=65
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=69
|
||||
CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=43
|
||||
4
boards/esp32_devkitc_wroom_procpu.conf
Normal file
4
boards/esp32_devkitc_wroom_procpu.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
CONFIG_BT_MAX_CONN=9
|
||||
34
boards/esp32_devkitc_wroom_procpu.overlay
Normal file
34
boards/esp32_devkitc_wroom_procpu.overlay
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,bt-c2h-uart = &uart1;
|
||||
};
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
|
||||
uart1_default: uart1_default {
|
||||
group1 {
|
||||
pinmux = <UART1_TX_GPIO5>,
|
||||
<UART1_RX_GPIO18>,
|
||||
<UART1_RTS_GPIO19>;
|
||||
};
|
||||
group2 {
|
||||
pinmux = <UART1_CTS_GPIO23>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
current-speed = <921600>;
|
||||
pinctrl-0 = <&uart1_default>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
8
boards/nrf51_blenano.conf
Normal file
8
boards/nrf51_blenano.conf
Normal file
@@ -0,0 +1,8 @@
|
||||
CONFIG_MAIN_STACK_SIZE=512
|
||||
CONFIG_BT_MAX_CONN=10
|
||||
CONFIG_IDLE_STACK_SIZE=256
|
||||
CONFIG_ISR_STACK_SIZE=512
|
||||
# Revert values set in prj.conf, set them to their Kconfig default value
|
||||
CONFIG_BT_BUF_CMD_TX_SIZE=65
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=69
|
||||
CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=43
|
||||
8
boards/nrf51_blenano.overlay
Normal file
8
boards/nrf51_blenano.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uart";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
1
boards/nrf51dk_nrf51822.conf
Normal file
1
boards/nrf51dk_nrf51822.conf
Normal file
@@ -0,0 +1 @@
|
||||
CONFIG_MAIN_STACK_SIZE=512
|
||||
8
boards/nrf51dk_nrf51822.overlay
Normal file
8
boards/nrf51dk_nrf51822.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uart";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
1
boards/nrf51dongle_nrf51822.conf
Normal file
1
boards/nrf51dongle_nrf51822.conf
Normal file
@@ -0,0 +1 @@
|
||||
CONFIG_MAIN_STACK_SIZE=512
|
||||
8
boards/nrf51dongle_nrf51822.overlay
Normal file
8
boards/nrf51dongle_nrf51822.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uart";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
12
boards/nrf52833dk_nrf52833.overlay
Normal file
12
boards/nrf52833dk_nrf52833.overlay
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
33
boards/nrf52833dk_nrf52833_df.overlay
Normal file
33
boards/nrf52833dk_nrf52833_df.overlay
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
|
||||
&radio {
|
||||
status = "okay";
|
||||
/* This is an example number of antennas that may be available
|
||||
* on antenna matrix board.
|
||||
*/
|
||||
dfe-antenna-num = <10>;
|
||||
/* This is an example switch pattern that will be used to set an
|
||||
* antenna for Tx PDU (period before start of Tx CTE).
|
||||
*/
|
||||
dfe-pdu-antenna = <0x0>;
|
||||
|
||||
/* These are example GPIO pin numbers that are provided to
|
||||
* Radio peripheral. The pins will be acquired by Radio to
|
||||
* drive antenna switching when AoD is enabled.
|
||||
*/
|
||||
dfegpio0-gpios = <&gpio0 3 0>;
|
||||
dfegpio1-gpios = <&gpio0 4 0>;
|
||||
dfegpio2-gpios = <&gpio0 28 0>;
|
||||
dfegpio3-gpios = <&gpio0 29 0>;
|
||||
};
|
||||
8
boards/nrf52840dk_nrf52840.overlay
Normal file
8
boards/nrf52840dk_nrf52840.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uart";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
4
boards/nrf52840dongle_nrf52840.conf
Normal file
4
boards/nrf52840dongle_nrf52840.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
CONFIG_USB_DEVICE_STACK=y
|
||||
CONFIG_USB_DEVICE_PRODUCT="Zephyr HCI UART sample"
|
||||
CONFIG_USB_CDC_ACM=y
|
||||
CONFIG_USB_DEVICE_INITIALIZE_AT_BOOT=n
|
||||
8
boards/nrf52_blenano2.overlay
Normal file
8
boards/nrf52_blenano2.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uart";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
8
boards/nrf52dk_nrf52832.overlay
Normal file
8
boards/nrf52dk_nrf52832.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uart";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
8
boards/nrf5340dk_nrf5340_cpuapp.overlay
Normal file
8
boards/nrf5340dk_nrf5340_cpuapp.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
8
boards/nrf5340dk_nrf5340_cpunet.overlay
Normal file
8
boards/nrf5340dk_nrf5340_cpunet.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
33
boards/nrf5340dk_nrf5340_cpunet_df.overlay
Normal file
33
boards/nrf5340dk_nrf5340_cpunet_df.overlay
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
|
||||
&radio {
|
||||
status = "okay";
|
||||
/* This is an example number of antennas that may be available
|
||||
* on antenna matrix board.
|
||||
*/
|
||||
dfe-antenna-num = <10>;
|
||||
/* This is an example switch pattern that will be used to set an
|
||||
* antenna for Tx PDU (period before start of Tx CTE).
|
||||
*/
|
||||
dfe-pdu-antenna = <0x0>;
|
||||
|
||||
/* These are example GPIO pin numbers that are provided to
|
||||
* Radio peripheral. The pins will be acquired by Radio to
|
||||
* drive antenna switching when AoD is enabled.
|
||||
*/
|
||||
dfegpio0-gpios = <&gpio0 4 0>;
|
||||
dfegpio1-gpios = <&gpio0 5 0>;
|
||||
dfegpio2-gpios = <&gpio0 6 0>;
|
||||
dfegpio3-gpios = <&gpio0 7 0>;
|
||||
};
|
||||
8
boards/nrf5340pdk_nrf5340_cpuapp.overlay
Normal file
8
boards/nrf5340pdk_nrf5340_cpuapp.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
&uart0 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
12
boards/nrf54l15dk_nrf54l15_cpuapp.overlay
Normal file
12
boards/nrf54l15dk_nrf54l15_cpuapp.overlay
Normal file
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&uart20 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
33
boards/nrf54l15dk_nrf54l15_cpuapp_df.overlay
Normal file
33
boards/nrf54l15dk_nrf54l15_cpuapp_df.overlay
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2024 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&uart20 {
|
||||
compatible = "nordic,nrf-uarte";
|
||||
current-speed = <1000000>;
|
||||
status = "okay";
|
||||
hw-flow-control;
|
||||
};
|
||||
|
||||
&radio {
|
||||
status = "okay";
|
||||
/* This is an example number of antennas that may be available
|
||||
* on antenna matrix board.
|
||||
*/
|
||||
dfe-antenna-num = <10>;
|
||||
/* This is an example switch pattern that will be used to set an
|
||||
* antenna for Tx PDU (period before start of Tx CTE).
|
||||
*/
|
||||
dfe-pdu-antenna = <0x0>;
|
||||
|
||||
/* These are example GPIO pin numbers that are provided to
|
||||
* Radio peripheral. The pins will be acquired by Radio to
|
||||
* drive antenna switching when AoD is enabled.
|
||||
*/
|
||||
dfegpio0-gpios = <&gpio1 4 0>;
|
||||
dfegpio1-gpios = <&gpio1 5 0>;
|
||||
dfegpio2-gpios = <&gpio1 6 0>;
|
||||
dfegpio3-gpios = <&gpio1 7 0>;
|
||||
};
|
||||
4
boards/nrf9160dk_nrf52840.conf
Normal file
4
boards/nrf9160dk_nrf52840.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
# Override prj.conf defaults
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
20
boards/nrf9160dk_nrf52840.overlay
Normal file
20
boards/nrf9160dk_nrf52840.overlay
Normal file
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <nrf52840/nrf9160dk_nrf52840_reset_on_if5.dtsi>
|
||||
|
||||
#include <nrf52840/nrf9160dk_uart1_on_if0_3.dtsi>
|
||||
|
||||
&uart1 {
|
||||
current-speed = <1000000>;
|
||||
hw-flow-control;
|
||||
};
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,bt-c2h-uart=&uart1;
|
||||
};
|
||||
};
|
||||
8
boards/nrf9160dk_nrf52840_0_14_0.overlay
Normal file
8
boards/nrf9160dk_nrf52840_0_14_0.overlay
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Nordic Semiconductor ASA
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* Use the reset line that is available starting from v0.14.0 of the DK. */
|
||||
#include <nrf52840/nrf9160dk_nrf52840_reset_on_if9.dtsi>
|
||||
7
boards/rv32m1_vega_openisa_rv32m1_ri5cy.conf
Normal file
7
boards/rv32m1_vega_openisa_rv32m1_ri5cy.conf
Normal file
@@ -0,0 +1,7 @@
|
||||
#
|
||||
# Copyright 2020, NXP
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
|
||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
28
boards/rv32m1_vega_openisa_rv32m1_ri5cy.overlay
Normal file
28
boards/rv32m1_vega_openisa_rv32m1_ri5cy.overlay
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2019 NXP
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,bt-c2h-uart = &lpuart0;
|
||||
};
|
||||
};
|
||||
|
||||
&lptmr1 {
|
||||
interrupt-parent = <&intmux0_ch2>;
|
||||
};
|
||||
|
||||
&intmux0_ch2 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&intmux0_ch3 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&generic_fsk {
|
||||
interrupt-parent = <&intmux0_ch3>;
|
||||
status = "okay";
|
||||
};
|
||||
4
boards/yd_esp32_procpu.conf
Normal file
4
boards/yd_esp32_procpu.conf
Normal file
@@ -0,0 +1,4 @@
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_STDOUT_CONSOLE=y
|
||||
CONFIG_UART_CONSOLE=y
|
||||
CONFIG_BT_MAX_CONN=9
|
||||
34
boards/yd_esp32_procpu.overlay
Normal file
34
boards/yd_esp32_procpu.overlay
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2021 Espressif Systems (Shanghai) Co., Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/ {
|
||||
chosen {
|
||||
zephyr,bt-c2h-uart = &uart1;
|
||||
};
|
||||
};
|
||||
|
||||
&pinctrl {
|
||||
|
||||
uart1_default: uart1_default {
|
||||
group1 {
|
||||
pinmux = <UART1_TX_GPIO5>,
|
||||
<UART1_RX_GPIO18>,
|
||||
<UART1_RTS_GPIO19>;
|
||||
};
|
||||
group2 {
|
||||
pinmux = <UART1_CTS_GPIO23>;
|
||||
bias-pull-up;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
&uart1 {
|
||||
status = "okay";
|
||||
current-speed = <921600>;
|
||||
pinctrl-0 = <&uart1_default>;
|
||||
pinctrl-names = "default";
|
||||
};
|
||||
21
debug.conf
Normal file
21
debug.conf
Normal file
@@ -0,0 +1,21 @@
|
||||
CONFIG_ASSERT=y
|
||||
|
||||
CONFIG_THREAD_NAME=y
|
||||
CONFIG_THREAD_ANALYZER=y
|
||||
CONFIG_THREAD_ANALYZER_AUTO=y
|
||||
CONFIG_THREAD_ANALYZER_RUN_UNLOCKED=y
|
||||
|
||||
CONFIG_HW_STACK_PROTECTION=y
|
||||
|
||||
CONFIG_CONSOLE=y
|
||||
CONFIG_LOG=y
|
||||
CONFIG_LOG_BUFFER_SIZE=4096
|
||||
CONFIG_RTT_CONSOLE=y
|
||||
CONFIG_LOG_BACKEND_RTT=y
|
||||
CONFIG_LOG_BACKEND_RTT_MODE_DROP=n
|
||||
CONFIG_USE_SEGGER_RTT=y
|
||||
CONFIG_SEGGER_RTT_BUFFER_SIZE_UP=4096
|
||||
CONFIG_LOG_BACKEND_SHOW_COLOR=n
|
||||
CONFIG_LOG_PROCESS_THREAD_STACK_SIZE=1024
|
||||
|
||||
CONFIG_LOG_DEFAULT_LEVEL=3
|
||||
7
dts/arm/nordic/override.dtsi
Normal file
7
dts/arm/nordic/override.dtsi
Normal file
@@ -0,0 +1,7 @@
|
||||
/* Keep default IRQ priority low for peripherals to reduce Radio ISR latency.
|
||||
* ARM Cortex-M4 lowest priority value of 5, i.e. considering Zephyr reserved 2
|
||||
* levels for Exceptions and ZLI (if enabled).
|
||||
* ARM Cortex-M0 lowest priority value of 3, i.e. we use it as Zephyr has no
|
||||
* support for ZLI on Cortex-M0.
|
||||
*/
|
||||
#define NRF_DEFAULT_IRQ_PRIORITY 3
|
||||
109
overlay-all-bt_ll_sw_split.conf
Normal file
109
overlay-all-bt_ll_sw_split.conf
Normal file
@@ -0,0 +1,109 @@
|
||||
CONFIG_BT_BUF_EVT_RX_COUNT=16
|
||||
|
||||
CONFIG_BT_BUF_EVT_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_TX_SIZE=251
|
||||
CONFIG_BT_BUF_CMD_TX_SIZE=255
|
||||
|
||||
# Host and Controller common dependencies
|
||||
CONFIG_BT_EXT_ADV=y
|
||||
CONFIG_BT_PER_ADV=y
|
||||
CONFIG_BT_PER_ADV_SYNC=y
|
||||
CONFIG_BT_PER_ADV_SYNC_MAX=2
|
||||
|
||||
# Broadcast and Connected ISO
|
||||
CONFIG_BT_ISO_BROADCASTER=y
|
||||
CONFIG_BT_ISO_SYNC_RECEIVER=y
|
||||
CONFIG_BT_ISO_CENTRAL=y
|
||||
CONFIG_BT_ISO_PERIPHERAL=y
|
||||
|
||||
# ISO Streams
|
||||
CONFIG_BT_ISO_MAX_CHAN=2
|
||||
|
||||
# Controller
|
||||
CONFIG_BT_LL_SW_SPLIT=y
|
||||
CONFIG_BT_CTLR_ASSERT_HANDLER=y
|
||||
CONFIG_BT_CTLR_DTM_HCI=y
|
||||
|
||||
# Rx ACL and Adv Reports
|
||||
CONFIG_BT_CTLR_RX_BUFFERS=9
|
||||
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251
|
||||
|
||||
# Coded PHY support
|
||||
CONFIG_BT_CTLR_PHY_CODED=y
|
||||
|
||||
# Advertising Sets and Extended Scanning
|
||||
CONFIG_BT_CTLR_ADV_EXT=y
|
||||
CONFIG_BT_CTLR_ADV_SET=3
|
||||
CONFIG_BT_CTLR_ADV_DATA_LEN_MAX=191
|
||||
CONFIG_BT_CTLR_SCAN_DATA_LEN_MAX=1650
|
||||
|
||||
CONFIG_BT_CTLR_ADVANCED_FEATURES=y
|
||||
CONFIG_BT_CTLR_ADV_AUX_SET=3
|
||||
CONFIG_BT_CTLR_ADV_AUX_PDU_BACK2BACK=y
|
||||
CONFIG_BT_CTLR_ADV_SYNC_SET=3
|
||||
CONFIG_BT_CTLR_ADV_SYNC_PDU_BACK2BACK=y
|
||||
CONFIG_BT_CTLR_ADV_DATA_BUF_MAX=6
|
||||
|
||||
# Increase the below to receive interleaved advertising chains
|
||||
CONFIG_BT_CTLR_SCAN_AUX_SET=1
|
||||
|
||||
CONFIG_BT_CTLR_ADV_RESERVE_MAX=n
|
||||
CONFIG_BT_CTLR_CENTRAL_RESERVE_MAX=n
|
||||
CONFIG_BT_CTLR_SLOT_RESERVATION_UPDATE=n
|
||||
CONFIG_BT_CTLR_SCAN_UNRESERVED=y
|
||||
CONFIG_BT_TICKER_NEXT_SLOT_GET_MATCH=y
|
||||
CONFIG_BT_TICKER_EXT=y
|
||||
CONFIG_BT_TICKER_EXT_SLOT_WINDOW_YIELD=y
|
||||
|
||||
# Control Procedure
|
||||
CONFIG_BT_CTLR_LLCP_LOCAL_PROC_CTX_BUF_NUM=6
|
||||
|
||||
# Direction Finding
|
||||
CONFIG_BT_CTLR_DF=y
|
||||
CONFIG_BT_CTLR_DF_PER_ADV_CTE_NUM_MAX=3
|
||||
CONFIG_BT_CTLR_DF_PER_SCAN_CTE_NUM_MAX=3
|
||||
|
||||
# Direction Finding Tx
|
||||
CONFIG_BT_CTLR_DF_CTE_TX=y
|
||||
CONFIG_BT_CTLR_DF_CONN_CTE_TX=y
|
||||
CONFIG_BT_CTLR_DF_ANT_SWITCH_TX=y
|
||||
CONFIG_BT_CTLR_DF_CONN_CTE_RSP=y
|
||||
|
||||
# Direction Finding Rx
|
||||
CONFIG_BT_CTLR_DF_CTE_RX=y
|
||||
CONFIG_BT_CTLR_DF_CONN_CTE_RX=y
|
||||
CONFIG_BT_CTLR_DF_ANT_SWITCH_RX=y
|
||||
CONFIG_BT_CTLR_DF_CONN_CTE_REQ=y
|
||||
|
||||
# ISO Broadcaster Controller
|
||||
CONFIG_BT_CTLR_ADV_EXT=y
|
||||
CONFIG_BT_CTLR_ADV_PERIODIC=y
|
||||
CONFIG_BT_CTLR_ADV_ISO=y
|
||||
CONFIG_BT_CTLR_ADV_ISO_PDU_LEN_MAX=247
|
||||
CONFIG_BT_CTLR_ADV_ISO_STREAM_MAX=2
|
||||
|
||||
# ISO Receive Controller
|
||||
CONFIG_BT_CTLR_ADV_EXT=y
|
||||
CONFIG_BT_CTLR_SYNC_PERIODIC=y
|
||||
CONFIG_BT_CTLR_SYNC_ISO=y
|
||||
CONFIG_BT_CTLR_SYNC_ISO_PDU_LEN_MAX=251
|
||||
CONFIG_BT_CTLR_SYNC_ISO_STREAM_MAX=2
|
||||
|
||||
# ISO Connection Oriented
|
||||
CONFIG_BT_CTLR_CENTRAL_ISO=y
|
||||
CONFIG_BT_CTLR_PERIPHERAL_ISO=y
|
||||
CONFIG_BT_CTLR_CONN_ISO_SDU_LEN_MAX=247
|
||||
CONFIG_BT_CTLR_CONN_ISO_PDU_LEN_MAX=251
|
||||
|
||||
# ISO Transmissions
|
||||
CONFIG_BT_CTLR_ISO_TX_BUFFERS=8
|
||||
CONFIG_BT_CTLR_ISO_TX_BUFFER_SIZE=255
|
||||
CONFIG_BT_CTLR_ISOAL_SOURCES=2
|
||||
|
||||
# ISO Receptions
|
||||
CONFIG_BT_CTLR_ISO_RX_BUFFERS=8
|
||||
CONFIG_BT_CTLR_ISOAL_SINKS=2
|
||||
|
||||
# Tx Power Dynamic Control
|
||||
CONFIG_BT_CTLR_TX_PWR_DYNAMIC_CONTROL=y
|
||||
23
prj.conf
Normal file
23
prj.conf
Normal file
@@ -0,0 +1,23 @@
|
||||
CONFIG_CONSOLE=n
|
||||
CONFIG_STDOUT_CONSOLE=n
|
||||
CONFIG_UART_CONSOLE=n
|
||||
CONFIG_GPIO=y
|
||||
CONFIG_SERIAL=y
|
||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
CONFIG_BT=y
|
||||
CONFIG_BT_HCI_RAW=y
|
||||
CONFIG_BT_HCI_RAW_H4=y
|
||||
CONFIG_BT_HCI_RAW_H4_ENABLE=y
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=255
|
||||
CONFIG_BT_BUF_CMD_TX_SIZE=255
|
||||
CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255
|
||||
CONFIG_BT_CTLR_ASSERT_HANDLER=y
|
||||
CONFIG_BT_MAX_CONN=16
|
||||
CONFIG_BT_TINYCRYPT_ECC=n
|
||||
CONFIG_BT_CTLR_DTM_HCI=y
|
||||
|
||||
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512
|
||||
|
||||
# Workaround: Unable to allocate command buffer when using K_NO_WAIT since
|
||||
# Host number of completed commands does not follow normal flow control.
|
||||
CONFIG_BT_BUF_CMD_TX_COUNT=10
|
||||
81
sample.yaml
Normal file
81
sample.yaml
Normal file
@@ -0,0 +1,81 @@
|
||||
sample:
|
||||
name: Bluetooth HCI UART
|
||||
description: Allows Zephyr to provide Bluetooth connectivity via UART
|
||||
tests:
|
||||
sample.bluetooth.hci_uart.nrf5:
|
||||
harness: bluetooth
|
||||
platform_allow:
|
||||
- nrf52dk/nrf52832
|
||||
tags:
|
||||
- uart
|
||||
- bluetooth
|
||||
sample.bluetooth.hci_uart.nrf52833.df:
|
||||
harness: bluetooth
|
||||
platform_allow: nrf52833dk/nrf52833
|
||||
extra_args:
|
||||
- DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay
|
||||
- SNIPPET="bt-ll-sw-split"
|
||||
extra_configs:
|
||||
- CONFIG_BT_CTLR_DF=y
|
||||
tags:
|
||||
- uart
|
||||
- bluetooth
|
||||
sample.bluetooth.hci_uart.nrf5340_netcore.df:
|
||||
harness: bluetooth
|
||||
platform_allow: nrf5340dk/nrf5340/cpunet
|
||||
extra_args:
|
||||
- DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay
|
||||
- SNIPPET="bt-ll-sw-split"
|
||||
extra_configs:
|
||||
- CONFIG_BT_CTLR_DF=y
|
||||
tags:
|
||||
- uart
|
||||
- bluetooth
|
||||
sample.bluetooth.hci_uart.nrf52833.df.iq_report:
|
||||
harness: bluetooth
|
||||
platform_allow: nrf52833dk/nrf52833
|
||||
extra_args:
|
||||
- DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay
|
||||
- SNIPPET="bt-ll-sw-split"
|
||||
extra_configs:
|
||||
- CONFIG_BT_CTLR_DF=y
|
||||
- CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT=y
|
||||
tags:
|
||||
- uart
|
||||
- bluetooth
|
||||
sample.bluetooth.hci_uart.nrf5340_netcore.df.iq_report:
|
||||
harness: bluetooth
|
||||
platform_allow: nrf5340dk/nrf5340/cpunet
|
||||
extra_args:
|
||||
- DTC_OVERLAY_FILE=./boards/nrf5340dk_nrf5340_cpunet_df.overlay
|
||||
- SNIPPET="bt-ll-sw-split"
|
||||
extra_configs:
|
||||
- CONFIG_BT_CTLR_DF=y
|
||||
- CONFIG_BT_CTLR_DTM_HCI_DF_IQ_REPORT=y
|
||||
tags:
|
||||
- uart
|
||||
- bluetooth
|
||||
sample.bluetooth.hci_uart.nrf52833.all:
|
||||
harness: bluetooth
|
||||
platform_allow: nrf52833dk/nrf52833
|
||||
integration_platforms:
|
||||
- nrf52833dk/nrf52833
|
||||
extra_args:
|
||||
- OVERLAY_CONFIG=overlay-all-bt_ll_sw_split.conf
|
||||
- DTC_OVERLAY_FILE=./boards/nrf52833dk_nrf52833_df.overlay
|
||||
- SNIPPET="bt-ll-sw-split"
|
||||
tags:
|
||||
- uart
|
||||
- bluetooth
|
||||
sample.bluetooth.hci_uart.nrf54l15.all:
|
||||
harness: bluetooth
|
||||
platform_allow: nrf54l15dk/nrf54l15/cpuapp
|
||||
integration_platforms:
|
||||
- nrf54l15dk/nrf54l15/cpuapp
|
||||
extra_args:
|
||||
- OVERLAY_CONFIG=overlay-all-bt_ll_sw_split.conf
|
||||
- DTC_OVERLAY_FILE=./boards/nrf54l15dk_nrf54l15_cpuapp_df.overlay
|
||||
- SNIPPET="bt-ll-sw-split"
|
||||
tags:
|
||||
- uart
|
||||
- bluetooth
|
||||
413
src/main.c
Normal file
413
src/main.c
Normal file
@@ -0,0 +1,413 @@
|
||||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* Copyright (c) 2015-2016 Intel Corporation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/arch/cpu.h>
|
||||
#include <zephyr/sys/byteorder.h>
|
||||
#include <zephyr/logging/log.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
|
||||
#include <zephyr/usb/usb_device.h>
|
||||
|
||||
#include <zephyr/net_buf.h>
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/l2cap.h>
|
||||
#include <zephyr/bluetooth/hci.h>
|
||||
#include <zephyr/bluetooth/buf.h>
|
||||
#include <zephyr/bluetooth/hci_raw.h>
|
||||
|
||||
#define LOG_MODULE_NAME hci_uart
|
||||
LOG_MODULE_REGISTER(LOG_MODULE_NAME);
|
||||
|
||||
static const struct device *const hci_uart_dev =
|
||||
DEVICE_DT_GET(DT_CHOSEN(zephyr_bt_c2h_uart));
|
||||
static K_THREAD_STACK_DEFINE(tx_thread_stack, CONFIG_BT_HCI_TX_STACK_SIZE);
|
||||
static struct k_thread tx_thread_data;
|
||||
static K_FIFO_DEFINE(tx_queue);
|
||||
|
||||
/* RX in terms of bluetooth communication */
|
||||
static K_FIFO_DEFINE(uart_tx_queue);
|
||||
|
||||
#define H4_CMD 0x01
|
||||
#define H4_ACL 0x02
|
||||
#define H4_SCO 0x03
|
||||
#define H4_EVT 0x04
|
||||
#define H4_ISO 0x05
|
||||
|
||||
/* Receiver states. */
|
||||
#define ST_IDLE 0 /* Waiting for packet type. */
|
||||
#define ST_HDR 1 /* Receiving packet header. */
|
||||
#define ST_PAYLOAD 2 /* Receiving packet payload. */
|
||||
#define ST_DISCARD 3 /* Dropping packet. */
|
||||
|
||||
/* Length of a discard/flush buffer.
|
||||
* This is sized to align with a BLE HCI packet:
|
||||
* 1 byte H:4 header + 32 bytes ACL/event data
|
||||
* Bigger values might overflow the stack since this is declared as a local
|
||||
* variable, smaller ones will force the caller to call into discard more
|
||||
* often.
|
||||
*/
|
||||
#define H4_DISCARD_LEN 33
|
||||
|
||||
static int h4_read(const struct device *uart, uint8_t *buf, size_t len)
|
||||
{
|
||||
int rx = uart_fifo_read(uart, buf, len);
|
||||
|
||||
LOG_DBG("read %d req %d", rx, len);
|
||||
|
||||
return rx;
|
||||
}
|
||||
|
||||
static bool valid_type(uint8_t type)
|
||||
{
|
||||
return (type == H4_CMD) | (type == H4_ACL) | (type == H4_ISO);
|
||||
}
|
||||
|
||||
/* Function expects that type is validated and only CMD, ISO or ACL will be used. */
|
||||
static uint32_t get_len(const uint8_t *hdr_buf, uint8_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case H4_CMD:
|
||||
return ((const struct bt_hci_cmd_hdr *)hdr_buf)->param_len;
|
||||
case H4_ISO:
|
||||
return bt_iso_hdr_len(
|
||||
sys_le16_to_cpu(((const struct bt_hci_iso_hdr *)hdr_buf)->len));
|
||||
case H4_ACL:
|
||||
return sys_le16_to_cpu(((const struct bt_hci_acl_hdr *)hdr_buf)->len);
|
||||
default:
|
||||
LOG_ERR("Invalid type: %u", type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Function expects that type is validated and only CMD, ISO or ACL will be used. */
|
||||
static int hdr_len(uint8_t type)
|
||||
{
|
||||
switch (type) {
|
||||
case H4_CMD:
|
||||
return sizeof(struct bt_hci_cmd_hdr);
|
||||
case H4_ISO:
|
||||
return sizeof(struct bt_hci_iso_hdr);
|
||||
case H4_ACL:
|
||||
return sizeof(struct bt_hci_acl_hdr);
|
||||
default:
|
||||
LOG_ERR("Invalid type: %u", type);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static void rx_isr(void)
|
||||
{
|
||||
static struct net_buf *buf;
|
||||
static int remaining;
|
||||
static uint8_t state;
|
||||
static uint8_t type;
|
||||
static uint8_t hdr_buf[MAX(sizeof(struct bt_hci_cmd_hdr),
|
||||
sizeof(struct bt_hci_acl_hdr))];
|
||||
int read;
|
||||
|
||||
do {
|
||||
switch (state) {
|
||||
case ST_IDLE:
|
||||
/* Get packet type */
|
||||
read = h4_read(hci_uart_dev, &type, sizeof(type));
|
||||
/* since we read in loop until no data is in the fifo,
|
||||
* it is possible that read = 0.
|
||||
*/
|
||||
if (read) {
|
||||
if (valid_type(type)) {
|
||||
/* Get expected header size and switch
|
||||
* to receiving header.
|
||||
*/
|
||||
remaining = hdr_len(type);
|
||||
state = ST_HDR;
|
||||
} else {
|
||||
LOG_WRN("Unknown header %d", type);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case ST_HDR:
|
||||
read = h4_read(hci_uart_dev,
|
||||
&hdr_buf[hdr_len(type) - remaining],
|
||||
remaining);
|
||||
remaining -= read;
|
||||
if (remaining == 0) {
|
||||
/* Header received. Allocate buffer and get
|
||||
* payload length. If allocation fails leave
|
||||
* interrupt. On failed allocation state machine
|
||||
* is reset.
|
||||
*/
|
||||
buf = bt_buf_get_tx(BT_BUF_H4, K_NO_WAIT,
|
||||
&type, sizeof(type));
|
||||
if (!buf) {
|
||||
LOG_ERR("No available command buffers!");
|
||||
state = ST_IDLE;
|
||||
return;
|
||||
}
|
||||
|
||||
remaining = get_len(hdr_buf, type);
|
||||
|
||||
net_buf_add_mem(buf, hdr_buf, hdr_len(type));
|
||||
if (remaining > net_buf_tailroom(buf)) {
|
||||
LOG_ERR("Not enough space in buffer");
|
||||
net_buf_unref(buf);
|
||||
state = ST_DISCARD;
|
||||
} else {
|
||||
state = ST_PAYLOAD;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case ST_PAYLOAD:
|
||||
read = h4_read(hci_uart_dev, net_buf_tail(buf),
|
||||
remaining);
|
||||
buf->len += read;
|
||||
remaining -= read;
|
||||
if (remaining == 0) {
|
||||
/* Packet received */
|
||||
LOG_DBG("putting RX packet in queue.");
|
||||
k_fifo_put(&tx_queue, buf);
|
||||
state = ST_IDLE;
|
||||
}
|
||||
break;
|
||||
case ST_DISCARD:
|
||||
{
|
||||
uint8_t discard[H4_DISCARD_LEN];
|
||||
size_t to_read = MIN(remaining, sizeof(discard));
|
||||
|
||||
read = h4_read(hci_uart_dev, discard, to_read);
|
||||
remaining -= read;
|
||||
if (remaining == 0) {
|
||||
state = ST_IDLE;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
}
|
||||
default:
|
||||
read = 0;
|
||||
__ASSERT_NO_MSG(0);
|
||||
break;
|
||||
|
||||
}
|
||||
} while (read);
|
||||
}
|
||||
|
||||
static void tx_isr(void)
|
||||
{
|
||||
static struct net_buf *buf;
|
||||
int len;
|
||||
|
||||
if (!buf) {
|
||||
buf = k_fifo_get(&uart_tx_queue, K_NO_WAIT);
|
||||
if (!buf) {
|
||||
uart_irq_tx_disable(hci_uart_dev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
len = uart_fifo_fill(hci_uart_dev, buf->data, buf->len);
|
||||
net_buf_pull(buf, len);
|
||||
if (!buf->len) {
|
||||
net_buf_unref(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void bt_uart_isr(const struct device *unused, void *user_data)
|
||||
{
|
||||
ARG_UNUSED(unused);
|
||||
ARG_UNUSED(user_data);
|
||||
|
||||
if (!(uart_irq_rx_ready(hci_uart_dev) ||
|
||||
uart_irq_tx_ready(hci_uart_dev))) {
|
||||
LOG_DBG("spurious interrupt");
|
||||
}
|
||||
|
||||
if (uart_irq_tx_ready(hci_uart_dev)) {
|
||||
tx_isr();
|
||||
}
|
||||
|
||||
if (uart_irq_rx_ready(hci_uart_dev)) {
|
||||
rx_isr();
|
||||
}
|
||||
}
|
||||
|
||||
static void tx_thread(void *p1, void *p2, void *p3)
|
||||
{
|
||||
while (1) {
|
||||
struct net_buf *buf;
|
||||
int err;
|
||||
|
||||
/* Wait until a buffer is available */
|
||||
buf = k_fifo_get(&tx_queue, K_FOREVER);
|
||||
/* Pass buffer to the stack */
|
||||
err = bt_send(buf);
|
||||
if (err) {
|
||||
LOG_ERR("Unable to send (err %d)", err);
|
||||
net_buf_unref(buf);
|
||||
}
|
||||
|
||||
/* Give other threads a chance to run if tx_queue keeps getting
|
||||
* new data all the time.
|
||||
*/
|
||||
k_yield();
|
||||
}
|
||||
}
|
||||
|
||||
static int h4_send(struct net_buf *buf)
|
||||
{
|
||||
LOG_DBG("buf %p type %u len %u", buf, bt_buf_get_type(buf),
|
||||
buf->len);
|
||||
|
||||
k_fifo_put(&uart_tx_queue, buf);
|
||||
uart_irq_tx_enable(hci_uart_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_BT_CTLR_ASSERT_HANDLER)
|
||||
void bt_ctlr_assert_handle(char *file, uint32_t line)
|
||||
{
|
||||
uint32_t len = 0U, pos = 0U;
|
||||
|
||||
/* Disable interrupts, this is unrecoverable */
|
||||
(void)irq_lock();
|
||||
|
||||
uart_irq_rx_disable(hci_uart_dev);
|
||||
uart_irq_tx_disable(hci_uart_dev);
|
||||
|
||||
if (file) {
|
||||
while (file[len] != '\0') {
|
||||
if (file[len] == '/') {
|
||||
pos = len + 1;
|
||||
}
|
||||
len++;
|
||||
}
|
||||
file += pos;
|
||||
len -= pos;
|
||||
}
|
||||
|
||||
uart_poll_out(hci_uart_dev, H4_EVT);
|
||||
/* Vendor-Specific debug event */
|
||||
uart_poll_out(hci_uart_dev, 0xff);
|
||||
/* 0xAA + strlen + \0 + 32-bit line number */
|
||||
uart_poll_out(hci_uart_dev, 1 + len + 1 + 4);
|
||||
uart_poll_out(hci_uart_dev, 0xAA);
|
||||
|
||||
if (len) {
|
||||
while (*file != '\0') {
|
||||
uart_poll_out(hci_uart_dev, *file);
|
||||
file++;
|
||||
}
|
||||
uart_poll_out(hci_uart_dev, 0x00);
|
||||
}
|
||||
|
||||
uart_poll_out(hci_uart_dev, line >> 0 & 0xff);
|
||||
uart_poll_out(hci_uart_dev, line >> 8 & 0xff);
|
||||
uart_poll_out(hci_uart_dev, line >> 16 & 0xff);
|
||||
uart_poll_out(hci_uart_dev, line >> 24 & 0xff);
|
||||
|
||||
while (1) {
|
||||
}
|
||||
}
|
||||
#endif /* CONFIG_BT_CTLR_ASSERT_HANDLER */
|
||||
|
||||
static int hci_uart_init(void)
|
||||
{
|
||||
LOG_DBG("");
|
||||
|
||||
if (IS_ENABLED(CONFIG_USB_CDC_ACM)) {
|
||||
if (usb_enable(NULL)) {
|
||||
LOG_ERR("Failed to enable USB");
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!device_is_ready(hci_uart_dev)) {
|
||||
LOG_ERR("HCI UART %s is not ready", hci_uart_dev->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
uart_irq_rx_disable(hci_uart_dev);
|
||||
uart_irq_tx_disable(hci_uart_dev);
|
||||
|
||||
uart_irq_callback_set(hci_uart_dev, bt_uart_isr);
|
||||
|
||||
uart_irq_rx_enable(hci_uart_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SYS_INIT(hci_uart_init, APPLICATION, CONFIG_KERNEL_INIT_PRIORITY_DEVICE);
|
||||
|
||||
int main(void)
|
||||
{
|
||||
/* incoming events and data from the controller */
|
||||
static K_FIFO_DEFINE(rx_queue);
|
||||
int err;
|
||||
|
||||
LOG_DBG("Start");
|
||||
__ASSERT(hci_uart_dev, "UART device is NULL");
|
||||
|
||||
/* Enable the raw interface, this will in turn open the HCI driver */
|
||||
bt_enable_raw(&rx_queue);
|
||||
|
||||
if (IS_ENABLED(CONFIG_BT_WAIT_NOP)) {
|
||||
/* Issue a Command Complete with NOP */
|
||||
int i;
|
||||
|
||||
const struct {
|
||||
const uint8_t h4;
|
||||
const struct bt_hci_evt_hdr hdr;
|
||||
const struct bt_hci_evt_cmd_complete cc;
|
||||
} __packed cc_evt = {
|
||||
.h4 = H4_EVT,
|
||||
.hdr = {
|
||||
.evt = BT_HCI_EVT_CMD_COMPLETE,
|
||||
.len = sizeof(struct bt_hci_evt_cmd_complete),
|
||||
},
|
||||
.cc = {
|
||||
.ncmd = 1,
|
||||
.opcode = sys_cpu_to_le16(BT_OP_NOP),
|
||||
},
|
||||
};
|
||||
|
||||
for (i = 0; i < sizeof(cc_evt); i++) {
|
||||
uart_poll_out(hci_uart_dev,
|
||||
*(((const uint8_t *)&cc_evt)+i));
|
||||
}
|
||||
}
|
||||
|
||||
/* Spawn the TX thread and start feeding commands and data to the
|
||||
* controller
|
||||
*/
|
||||
k_thread_create(&tx_thread_data, tx_thread_stack,
|
||||
K_THREAD_STACK_SIZEOF(tx_thread_stack), tx_thread,
|
||||
NULL, NULL, NULL, K_PRIO_COOP(7), 0, K_NO_WAIT);
|
||||
k_thread_name_set(&tx_thread_data, "HCI uart TX");
|
||||
|
||||
while (1) {
|
||||
struct net_buf *buf;
|
||||
|
||||
buf = k_fifo_get(&rx_queue, K_FOREVER);
|
||||
err = h4_send(buf);
|
||||
if (err) {
|
||||
LOG_ERR("Failed to send");
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user