I'm running the central_hci example, initially on an nRF54LM20 DK and then on an nRF52840 DK. I'm trying to pair with a Redragon Antonium Pro 108 keyboard. The sniffer capture indicates that it never gets past the CONNECT_IND. Comparing this with a pairing I was able to successfully perform with my phone indicates that the only difference in the CONNECT_IND is the transmitWindowOffset, which is 0 on the DK.
I found the SoftDevice Controller compatibility-mode window-offset command, hci_vs_sdc_compat_mode_window_offset_set, and tried this using version 3.4.1 of the SDK on the 54 DK, but hit an asserttion 57, 2024. I then started going back in SDK versions and using the nRF52840 as well. I had to use the direct SDC API function, sdc_hci_cmd_vs_compat_mode_window_offset_set, on earlier versions since the hci_vs_sdc_compat_mode_window_offset_set wasn't supported earlier. The direct call succeeds on NCS v2.4.0 but crashes on later releases.
The test calls sdc_hci_cmd_vs_compat_mode_window_offset_set() after bt_enable() and holds the NCS multithreading lock around the call. The parameter struct is initialized with .enable = 0 or .enable = 1; it contains no other fields.
Results:
NCS v2.4.0, nRF52840 DK: returns 0 for both enable = 0 and enable = 1.
NCS v2.7.0, nRF52840 DK: crashes. I have not captured the assertion ID yet.
NCS v2.9.3, nRF52840 DK: crashes. I have not captured the assertion ID yet.
NCS v3.2.0, nRF52840 DK: direct call with enable = 1 asserts with 57, 2530.
NCS v3.4.1, nRF54LM20 DK: assertion 57, 2024 observed; the assertion also occurs with enable = 0.
An HCI-wrapper call in NCS v3.2.0 returns -5, but inspection of that release’s NCS HCI dispatcher shows the opcode is not routed to SDC there. I understand this result is separate from the direct-call assertion.
The SDC header says the APIs in sdc_hci_vs.h are expected to be called at the same execution priority as mpsl_low_priority_process(). The direct test runs in the application thread after bt_enable() while holding the SDK multithreading lock. Could you confirm whether that call context is supported for this API, or whether it must run specifically at the MPSL low-priority execution priority? If the context is supported, could you decode assertion IDs 57, 2530 and 57, 2024 and advise which release introduced the failure?
I have attached the test app main.c file.
#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/bluetooth/bluetooth.h>
#include <mpsl/mpsl_work.h>
#include <sdc_hci_vs.h>
int multithreading_lock_acquire(k_timeout_t timeout);
void multithreading_lock_release(void);
static const sdc_hci_cmd_vs_compat_mode_window_offset_set_t params = {
.enable = 1,
};
static struct k_work compat_mode_work;
static struct k_sem compat_mode_done;
static int compat_mode_lock_error;
static int compat_mode_result;
static void compat_mode_work_handler(struct k_work *work)
{
ARG_UNUSED(work);
printk("MPSL work handler entered\n");
compat_mode_lock_error = multithreading_lock_acquire(K_NO_WAIT);
if (!compat_mode_lock_error) {
printk("About to call SDC compat-mode API (enable=%u)\n",
(unsigned int)params.enable);
compat_mode_result = sdc_hci_cmd_vs_compat_mode_window_offset_set(¶ms);
multithreading_lock_release();
}
k_sem_give(&compat_mode_done);
}
int main(void)
{
int err;
printk("Enabling Bluetooth\n");
err = bt_enable(NULL);
if (err) {
printk("bt_enable failed: %d\n", err);
return 0;
}
printk("Bluetooth enabled\n");
k_sem_init(&compat_mode_done, 0, 1);
k_work_init(&compat_mode_work, compat_mode_work_handler);
printk("Submitting SDC window-offset command to MPSL workqueue (enable=%u)\n",
(unsigned int)params.enable);
mpsl_work_submit(&compat_mode_work);
err = k_sem_take(&compat_mode_done, K_FOREVER);
if (err) {
printk("Waiting for MPSL work item failed: %d\n", err);
return 0;
}
if (compat_mode_lock_error) {
printk("Controller lock unavailable in MPSL work item: %d\n",
compat_mode_lock_error);
} else {
printk("MPSL workqueue SDC call returned: %d\n", compat_mode_result);
}
return 0;
}