Bluetooth HCI lpuart issue - nRF9160 + nRF52840

Hello,

I'm using nRF9160 as a HCI host and nRF52840 as HCI controller (nRF52840 config is based on HCI lpuart example). My application receives data over Bluetooth using notifications. To handle the notifications data I use a message queue and a workqueue (to avoid handling it from a notification callback which is executed from a bt_rx_thread). It has to be able to receive ~50kB of data. Sometimes it works without any problem but sometimes I get the following information in logs:

bt_hci_core: opcode 0x0002 pool id 3 pool 0x20020958 != &hci_cmd_pool 0x200209b0
lpuart: Tx timeout

or

lpuart: req pin low when expected high
lpuart: Empty receiver state:4
bt_hci_core: opcode 0x0000 pool id 3 pool 0x20020958 != &hci_cmd_pool 0x200209b0
bt_hci_core: Unexpected HOST_NUM_COMPLETED_PACKETS (status 0x0c)
bt_hci_core: Unexpected HOST_NUM_COMPLETED_PACKETS (status 0x0c)

or

lpuart: req pin low when expected high
lpuart: Empty receiver state:4
bt_driver: Not enough space in buffer 1275/255

After each of above logs the bluetooth becomes unresponsive. Using sniffer I found out that the connection is alive and it sends Empty PDU packets. Only reseting the device helps in such situation.

The higher baudrate of HCI, the issue occurs more frequently. When I try to use baud rate of 1000000, it fails almost everytime.

Setup:
Custom board with nRF9160 and nRF52840
NCS v2.6.1

nRF9160 BT configuration:
CONFIG_BT=y
CONFIG_BT_H4=y
CONFIG_BT_WAIT_NOP=y
CONFIG_BT_HCI=y
CONFIG_BT_CTLR=n
CONFIG_BT_CENTRAL=y
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_DM=y
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_MANUFACTURER_DATA_CNT=1
CONFIG_BT_L2CAP_TX_MTU=247
CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_HCI_TX_STACK_SIZE_WITH_PROMPT=y
CONFIG_BT_HCI_TX_STACK_SIZE=2048
CONFIG_BT_RX_STACK_SIZE=4096
CONFIG_MAIN_STACK_SIZE=2048
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_HEAP_MEM_POOL_SIZE=8192

nRF52840 BT configuration:
CONFIG_BT=y
CONFIG_BT_CTLR=y
CONFIG_BT_WAIT_NOP=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=251
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255

Also, I would like to mention another issue I encountered.
If I detect some error (I don't mean the error with HCI mentioned above but some kind of error in my functions that has to be handled) while downloading ~50kB of data using notifications,
I would like to drop connection. To do it, I execute bt_conn_disconnect in a workqueue that handles notification data. Using sniffer, I can see that the disconnect command goes to the peripheral device and the connection ends. The problem is that I do not receive a disconnected callback. 
When I disconnect after receiving all the data, the disconnected callback is executed.
Any help would be greatly appreciated.
  • Hello,

    I will try to see if I can replicate the HCI communication issues on my end, but did not get time to get started on that today. Will update the ticket when I have had a chance to try this.

    To do it, I execute bt_conn_disconnect in a workqueue that handles notification data. Using sniffer, I can see that the disconnect command goes to the peripheral device and the connection ends. The problem is that I do not receive a disconnected callback. When I disconnect after receiving all the data, the disconnected callback is executed.
    Any help would be greatly appreciated.

    Is the application allowed to returned to the idle thread after you've sent the disconnect, or is it busy with other tasks? It unepexted if the disconnect callback never comes through. Are you observing any HCI errors when this happens?

    Best regards,

    Vidar

  • Is the application allowed to returned to the idle thread after you've sent the disconnect, or is it busy with other tasks? It unepexted if the disconnect callback never comes through. Are you observing any HCI errors when this happens?

    I put a log in an idle thread every second and I can see that after executing bt_conn_disconnect, idle thread still works. My other threads also work. No HCI errors observed in logs. The bt_conn_disconnect also doesn't return any error.

  • Hello,

    Could you try to enable the LP UART driver in the HCI UART based on ASYNC UART sample instead? The ASYNC implementation should enable more reliable communcation at higher data rates than the interrupt-driven API. 

  • Hello,

    So, based on hci_uart_async I copied files main.c and hci_uart_async.c to my nRF52840 project and changed configuration to the following:

    dts:

    / {
        chosen {
            zephyr,bt-c2h-uart=&bt_c2h_uart;
        };
    };
    
    &pinctrl {
    	uart1_default_alt: uart1_default_alt {
    		group1 {
    			psels = <NRF_PSEL(UART_TX, 0, 20)>,
    					<NRF_PSEL(UART_RX, 0, 13)>,
    					<NRF_PSEL(UART_RTS, 0, 14)>,
    					<NRF_PSEL(UART_CTS, 0, 15)>;
    		};
    	};
    
    	uart1_sleep_alt: uart1_sleep_alt {
    		group1 {
    			psels = <NRF_PSEL(UART_TX, 0, 20)>,
    					<NRF_PSEL(UART_RX, 0, 13)>,
    					<NRF_PSEL(UART_RTS, 0, 14)>,
    					<NRF_PSEL(UART_CTS, 0, 15)>;
    			low-power-enable;
    		};
    	};
    };
    
    bt_c2h_uart: &uart1 {
    	status = "okay";
    	current-speed = <1000000>;
    	hw-flow-control;
    
    	pinctrl-0 = <&uart1_default_alt>;
    	pinctrl-1 = <&uart1_sleep_alt>;
    	pinctrl-names = "default", "sleep";
    };

    prj.conf:

    CONFIG_SERIAL=y
    CONFIG_UART_ASYNC_API=y
    
    CONFIG_BT=y
    CONFIG_BT_HCI_RAW=y
    CONFIG_BT_HCI_RAW_H4=y
    CONFIG_BT_HCI_RAW_H4_ENABLE=y
    
    CONFIG_BT_WAIT_NOP=y
    
    CONFIG_BT_BUF_ACL_RX_SIZE=255
    CONFIG_BT_BUF_ACL_TX_SIZE=255
    CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255
    
    CONFIG_UART_CONSOLE=n


    board_defconfig:
    CONFIG_SOC_SERIES_NRF52X=y
    CONFIG_SOC_NRF52840_QIAA=y
    CONFIG_BOARD_xyz=y
    
    CONFIG_ARM_MPU=y
    CONFIG_HW_STACK_PROTECTION=y
    
    CONFIG_GPIO=y
    CONFIG_PINCTRL=y
    CONFIG_MAIN_STACK_SIZE=1024
    CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=512
    
    CONFIG_BT_TINYCRYPT_ECC=n
    CONFIG_BT_CTLR_ASSERT_HANDLER=n
    
    CONFIG_UART_1_ASYNC=y
    CONFIG_UART_1_INTERRUPT_DRIVEN=n
    CONFIG_UART_1_NRF_HW_ASYNC=y
    CONFIG_UART_1_NRF_HW_ASYNC_TIMER=2

    Now nRF9160 logs the following on system start and resets:

    00> *** Booting nRF Connect SDK v3.5.99-ncs1-1 ***
    00> [1970-01-01 00:00:03.039000]<wrn> bt_hci_core: opcode 0x0400 pool id 3 pool 0x20020974 != &hci_cmd_pool 0x200209cc
    00> [1970-01-01 00:00:03.039000]<err> bt_driver: Unknown H:4 type 0x0e

    Do I miss something in nRF52840 configuration? What should I change in nRF9160 configuration?

    Also, is it possible to run hci_uart_async sample (nRF52840) and lte_ble_gateway sample (nRF9160) together on nrf9160dk? Should it work?

  • Sorry, I thought the host the was using the Async API, but I see the HCI driver uses the interrupt API, and I don't think it will help if the async API is only used on one side of the connection. I have reported the issues you have experienced internally. Another option would be to use the HCI uart sample with the regular driver and HW flow control, but then you will get an increased idle current as long as the BT stack is enabled, or run the whole BT application (host + controller) on the nRF52840 and only expose a custom command interface to the nRF9160 for sending and receiving BLE data.

Related