MPSL Assert in project involving BLE, async UART and Nordic Distance Measurement Library

We are developing a project that runs BLE, the Nordic Uart Service, the Nordic Distance Measurement toolikt and Async UART (NCS v2.9.0). The Peripheral device shall advertise (connectable) the Nordic Uart Service UUID, the Central Scans for this and connects to the found Peripheral, and registers the NUS Service. After the connection it starts/changes the required advertising-scanning for the distance measurement, as in the example provided from the SDK nrf_dm (we adapted only the part of Distance Estimation, and not the DDFS service or the Azimuth simulation). So only the pair advertising-scanning with the corresponding manufacturer data values, and the call to dm_request_add in the callback to the advertising scanned and scan filter match.

It works as expected, but sometime after the measurement has been running, an assert is triggered:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
D: Sending Uart State
D: Idle State
W: Dist measurement updated: 2.050781
D: Sending Ble State
D: Idle State
D: Sending Uart State
D: Idle State
D: Sending Ble State
D: Idle State
D: Sending Uart State
D: Idle State
D: Sending Ble State
D: Idle State
D: Sending Uart State
D: Idle State
D: Sending Ble State
D: Idle State
D: Sending Uart State
D: Idle State
D: Sending Ble State
D: Idle State
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


As fas as we can understand, the MPSL is being used in the DM toolkit (or BLE, or both?), but we do not interact directly with it. So we are unsure what the problem might be. From other posts here we might interpret that it might be a timing problem with an interrupt, but we are not directly stopping or missusing any interrupt that we know of. The software would receive data via UART, pass it to the main task, that would check the data with CRC32, decode the data with nanopb, and encode a response that is sent via the NUS to the other node, where something similar is performed. All of this is made in main task, only callbacks that might come from an interrupt are the UART callback and NUS RX callback, but they only load data into a FIFO and return. Similarly with the BLE callbacks, except for the 2 callbacks for advertising and scanning that contain the call to the DM library.

Also, we have the problem that the assert behaves differently in our EvalBoard (Ezurio BL653-DVK based on the BL653/nRF52833) and our custom hardware around the BL653micro/nRF52833. In the EvalBoard, the system seems to hang, but the LOG output (using Segger RTT backend) freezes (no assert is seen, but the whole system is unresponsive), while in the custom hardware the Assert output is there. Both configurations have the CONFIG_ASSERT as seen above.

Central prj.conf

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CONFIG_FPU=y
CONFIG_UART_ASYNC_API=y
CONFIG_UART_1_NRF_HW_ASYNC=y
CONFIG_UART_1_NRF_HW_ASYNC_TIMER=3
CONFIG_CRC=y
CONFIG_NANOPB=y
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_DEVICE_NAME="central"
CONFIG_BT_EXT_ADV=y
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
CONFIG_BT_GATT_CLIENT=y
CONFIG_BT_GATT_DM=y
CONFIG_HEAP_MEM_POOL_SIZE=1024
CONFIG_BT_CTLR_PHY_2M=y
CONFIG_BT_CTLR_PHY_CODED=y
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


Central DM Adv-Scan parameters:

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static struct bt_le_adv_param app_ble_adv_params_noconnectable =
BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_USE_IDENTITY | BT_LE_ADV_OPT_SCANNABLE | BT_LE_ADV_OPT_NOTIFY_SCAN_REQ,
BT_GAP_ADV_SLOW_INT_MIN, // 160 * 0.625 ms = 100 ms
BT_GAP_ADV_SLOW_INT_MAX, // 240 * 0.625 ms = 150 ms
NULL);
static struct bt_data app_ble_advertisement_data[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
BT_DATA(BT_DATA_NAME_COMPLETE, APP_BLE_DEVICE_NAME, APP_BLE_DEVICE_NAME_LEN),
};
static struct bt_data app_ble_scan_response_dm_data[] = {
BT_DATA(BT_DATA_MANUFACTURER_DATA, (unsigned char*)&app_ble.mfg_data, sizeof(app_ble.mfg_data)),
};
static struct bt_le_scan_param app_ble_scan_params = {
.type = BT_LE_SCAN_TYPE_ACTIVE,
.interval = BT_GAP_SCAN_FAST_INTERVAL,
.window = BT_GAP_SCAN_FAST_WINDOW,
.options = BT_LE_SCAN_OPT_NONE,
.timeout = 0,
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX



Peripheral prj.conf

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
CONFIG_FPU=y
CONFIG_UART_ASYNC_API=y
CONFIG_UART_1_NRF_HW_ASYNC=y
CONFIG_UART_1_NRF_HW_ASYNC_TIMER=3
CONFIG_CRC=y
CONFIG_NANOPB=y
CONFIG_BT=y
CONFIG_BT_PERIPHERAL=y
CONFIG_BT_CENTRAL=y
CONFIG_BT_DEVICE_NAME="Peripheral"
CONFIG_BT_EXT_ADV=y
CONFIG_BT_SCAN=y
CONFIG_BT_SCAN_FILTER_ENABLE=y
CONFIG_BT_SCAN_MANUFACTURER_DATA_CNT=1
CONFIG_BT_SCAN_WITH_IDENTITY=y
CONFIG_BT_CTLR_PHY_2M=y
CONFIG_BT_CTLR_PHY_CODED=y
CONFIG_BT_AUTO_PHY_UPDATE=n
CONFIG_BT_USER_PHY_UPDATE=y
CONFIG_BT_USER_DATA_LEN_UPDATE=y
CONFIG_BT_PERIPHERAL_PREF_MIN_INT=6
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX


peripheral DM Adv-Scan parameters

Fullscreen
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
static struct bt_le_adv_param app_ble_adv_params_noconnectable =
BT_LE_ADV_PARAM_INIT(BT_LE_ADV_OPT_USE_IDENTITY | BT_LE_ADV_OPT_SCANNABLE | BT_LE_ADV_OPT_NOTIFY_SCAN_REQ,
BT_GAP_ADV_FAST_INT_MIN_2, // 160 * 0.625 ms = 100 ms
BT_GAP_ADV_FAST_INT_MAX_2, // 240 * 0.625 ms = 150 ms
NULL);
static struct bt_data app_ble_advertisement_data[] = {
BT_DATA_BYTES(BT_DATA_FLAGS, (BT_LE_AD_GENERAL | BT_LE_AD_NO_BREDR)),
};
static struct bt_data app_ble_scan_response_dm_data[] = {
BT_DATA(BT_DATA_MANUFACTURER_DATA, (unsigned char*)&app_ble.mfg_data, sizeof(app_ble.mfg_data)),
};
static struct bt_le_scan_param app_ble_scan_params = {
.type = BT_LE_SCAN_TYPE_ACTIVE,
.interval = BT_GAP_SCAN_FAST_INTERVAL,
.window = BT_GAP_SCAN_FAST_WINDOW,
.options = BT_LE_SCAN_OPT_NONE,
.timeout = 0,
};
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX



What should be checked when an MPSL assert happens? Is there any helpful guide on how does the MPSL internally works, or how is it used in the Distance Measurement Library? What might cause such assert error?

How to explain the difference in the error behavior between the EvalBoard and the custom hardware? What might cause the Logging output to be visible in one hardware but not in another?

Any idea or comment would be helpful.

Thanks in advance

Regards

Javier