Assert error when Coded PHY is used for BLE NUS

For a project running a BLE connection and sharing data via the NUS service, we have seen that setting up Coded PHY (S2 or S8) will eventually produce an assert error as follows:


Peripheral Log:

...
D: Received  17 bytes
D: Received 167 bytes
D: Received  96 bytes
D: Received 230 bytes
D: Received 215 bytes

ASSERTION FAIL [0] @ WEST_TOPDIR/nrf/subsys/bluetooth/controller/hci_driver.c:311
  SoftDevice Controller ASSERT: 48, 889

E: ***** HARD FAULT *****
E:   Fault escalation (see below)
E: ARCH_EXCEPT with reason 4

E: r0/a1:  0x00000004  r1/a2:  0x00000137  r2/a3:  0x20006cd8
E: r3/a4:  0x00000004 r12/ip:  0x00000000 r14/lr:  0x0002881b
E:  xpsr:  0x21000011
E: s[ 0]:  0x20006db0  s[ 1]:  0x00000bfb  s[ 2]:  0x00000030  s[ 3]:  0x00003834
E: s[ 4]:  0x00000000  s[ 5]:  0x00ffffc6  s[ 6]:  0x20002fa8  s[ 7]:  0x00003bb9
E: s[ 8]:  0x20003434  s[ 9]:  0x20006dd6  s[10]:  0x20001690  s[11]:  0x0000016d
E: s[12]:  0x200016b8  s[13]:  0x20001690  s[14]:  0x00000000  s[15]:  0x20002fa8
E: fpscr:  0x00000000
E: Faulting instruction address (r15/pc): 0x0002ffb2
E: >>> ZEPHYR FATAL ERROR 4: Kernel panic on CPU 0
E: Fault during interrupt handling

E: Current thread: 0x200044a8 (unknown)
E: Halting system



Central Log:

...
D: >  17 bytes in   9 ms
D: > 167 bytes in  83 ms
D: >  96 bytes in  31 ms
D: > 230 bytes in  76 ms
W: BLE NUS response timeout
W: NUS TX notifications disabled
W: Disconnected from DE:4D:9B:B9:6C:55 (random) (reason 0x08)
W: BLE connection lost
I: Scanning...



We have this Minimal Working Example prepared where the issue is reproducible. It contains both the Central and Peripheral project. Central will scan and connect to the Peripheral (a hardcoded address), set PHY, set connection interval to the minimum allowed, datalen and MTU are set, and then the GATT discovery service procedure is run to also enable the NUS RX. After it, Central will send a random amount of bytes, and expect back the same amount of bytes in reverse order.

Everything works as expected for PHY 1M and 2M. But when we use Coded S2 or S8, communication works for a few seconds/minutes, but then the assert is triggered (sometimes in the Central, sometimes in the Peripheral).

For reference, the relevant parts of the PHY configuration in the central:

/* PHY connection parameters */
struct bt_conn_le_phy_param param = {
    .options       = BT_CONN_LE_PHY_OPT_CODED_S2,
    .pref_tx_phy   = BT_GAP_LE_PHY_CODED,
    .pref_rx_phy   = BT_GAP_LE_PHY_CODED,
};

// ...


CUSTOM_LOG_INF("Requesting PHY update\n");
res = bt_conn_le_phy_update(current_conn, &param);
if (res != 0)
{
    CUSTOM_LOG_ERR("Failed to update PHY (err %d)\n", res);
    state = STATE_ERROR;
    break;
}
state = STATE_WAIT_FOR_PHY;


And our config contains:

#
# Bluetooth stack
#
CONFIG_BT=y

#
# Extended stack for BLE RX is necessary due to the high load on data exchange
#
CONFIG_BT_RX_STACK_SIZE=2048

#
# Supported Bluetooth roles
#
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=y

#
# Name to be advertised from Bluetooth device
#
CONFIG_BT_DEVICE_NAME="rangeCentral"

#
# Enables extended advertisement for Bluetooth
#
CONFIG_BT_CTLR_ADV_EXT=y
CONFIG_BT_EXT_ADV=y

#
# Activates the scanning features of Bluetooth und configure Scan specifics
#
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_MANUFACTURER_DATA_CNT=1
CONFIG_BT_SCAN_UUID_CNT=1
CONFIG_BT_SCAN_WITH_IDENTITY=y

#
# GATT Client for GATT Services discovery
#
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_DM=y

#
# Dynamic memory allocation required by the (GATT Discovery Manager)
#
CONFIG_HEAP_MEM_POOL_SIZE=2048

#
# Enable all PHYs and allow user connection parameters, phy and datalen
#
CONFIG_BT_CTLR_PHY_2M=y
CONFIG_BT_CTLR_PHY_CODED=y
CONFIG_BT_AUTO_PHY_UPDATE=n
CONFIG_BT_PHY_UPDATE=y
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_GAP_AUTO_UPDATE_CONN_PARAMS=n

CONFIG_BT_L2CAP_TX_MTU=247
CONFIG_BT_BUF_ACL_TX_SIZE=251
CONFIG_BT_BUF_ACL_RX_SIZE=251
CONFIG_BT_CTLR_DATA_LENGTH_MAX=251

#
# Enable the Nordic UART Service (client)
#
CONFIG_BT_NUS_CLIENT=y

#
# Extended stack is required for Main task
#
CONFIG_MAIN_STACK_SIZE=1536

#
# Maximal TX power configuration for nRF52833 +8dBm
#
CONFIG_BT_CTLR_TX_PWR_ANTENNA=8


The central LOG at boot confirms that the PHY is correctly set.

 
*** Booting nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
I: Starting Central...
I: SoftDevice Controller build revision: 
I: 2d 79 a1 c8 6a 40 b7 3c |-y..j@.<
I: f6 74 f9 0b 22 d3 c4 80 |.t.."...
I: 74 72 82 ba             |tr..    
I: HW Platform: Nordic Semiconductor (0x0002)
I: HW Variant: nRF52x (0x0002)
I: Firmware: Standard Bluetooth controller (0x00) Version 45.41337 Build 3074452168
I: Identity: E8:C2:FC:1E:F8:52 (random)
I: HCI: version 6.0 (0x0e) revision 0x106b, manufacturer 0x0059
I: LMP: version 6.0 (0x0e) subver 0x106b
I: BT initialized
I: BT NUS client initialized
I: Scan initialized
I: Expected address: DE:4D:9B:B9:6C:55 (random)
I: Scanning...
I: Expected device found. Addr: DE:4D:9B:B9:6C:55 (random), connectable: true
I: Connecting to device...
I: Connected to DE:4D:9B:B9:6C:55 (random), role 0, interval 50.0 ms, latency 0, timeout 4000 ms, phy 1
I: Requesting PHY update
I: PHY updated: tx_phy = 4, rx_phy = 4
I: Data length updated: tx_max_len 27, tx_max_time 2704, rx_max_len 27, rx_max_time 2704
I: Requesting connection parameters update
I: Connection parameters updated: interval 7.5 ms, latency 0, timeout 500 ms
I: Requesting data length update
I: Data length updated: tx_max_len 251, tx_max_time 2704, rx_max_len 251, rx_max_time 2704
I: Requesting MTU exchange
I: MTU exchange done
I: Starting service discovery
I: NUS subscribed
I: Discovery complete
D: >  57 bytes in  23 ms
...



The peripheral LOG at boot looks so:

*** Booting nRF Connect SDK v2.9.0-7787b2649840 ***
*** Using Zephyr OS v3.7.99-1f8f3dc29142 ***
I: Starting Peripheral...
I: SoftDevice Controller build revision: 
I: 2d 79 a1 c8 6a 40 b7 3c |-y..j@.<
I: f6 74 f9 0b 22 d3 c4 80 |.t.."...
I: 74 72 82 ba             |tr..    
I: HW Platform: Nordic Semiconductor (0x0002)
I: HW Variant: nRF52x (0x0002)
I: Firmware: Standard Bluetooth controller (0x00) Version 45.41337 Build 3074452168
I: Identity: DE:4D:9B:B9:6C:55 (random)
I: HCI: version 6.0 (0x0e) revision 0x106b, manufacturer 0x0059
I: LMP: version 6.0 (0x0e) subver 0x106b
I: BT initialized
I: BT NUS initialized
I: Advertising started
I: Connected to E8:C2:FC:1E:F8:52 (random), role 1, interval 50.00 ms, latency 0, timeout 4000, phy 1
I: PHY updated: tx_phy = 4, rx_phy = 4
I: Data length updated: tx_max_len 27, tx_max_time 2704, rx_max_len 27, rx_max_time 2704
I: Connection parameters updated: interval 7.50 ms, latency 0, timeout 500 ms
I: Data length updated: tx_max_len 251, tx_max_time 2704, rx_max_len 251, rx_max_time 2704
I: NUS send enabled
D: Received  57 bytes
...


We are working on SDK v2.9.0, and have reproduced the assert on Ezurio evalboard BL653 (based on the nRF52833) and our custom board for the BL653 micro (also based on same nRF). I assume it should also work on a Nordic evalboard for the 52833 or similar.

Q: Is there anything special that we should do in our code for Coded PHY to work correclty? Or might this be an SDK problem?

Thanks in advance for any feedback on this

Kind regards

Javier Reyes

assert_error_coded_phy.zip

Related