BLE central scanning fails to reliably discover/connect to peripherals when scan-window idle gap drops to ~1.875 ms on nRF54L15 — works at 2.5 ms gap

SDK/Toolchain:

  • nRF Connect SDK version: [ v3.3.0 ]
  • Board: Custom board based on nRF54L15 (cpuapp core)
  • Role: Central (continuous passive scanning + initiating connections to discovered peripherals), also acts as Peripheral (multirole)

Summary:

We run continuous passive scanning with scan_interval = 36 (22.5 ms) while also initiating new connections to discovered peripherals. We tested several scan-window values on this interval:

scan.window (ticks, 0.625 ms units) window (ms) idle gap (ms) Result
32 20.000 2.500 Works normally
33 20.625 1.875 Discovery becomes extremely slow; connection attempts to new peripherals consistently time out

We independently arrived at window=33 via four different percentage inputs (92%, 93%, 94%, 95% of the 22.5 ms interval) — all four round to the identical 33-tick window through our percentage→ms→tick conversion, and all four reproduce the identical failure, confirming the behavior is tied to the absolute tick values, not the percentage.

Reproduction:

static struct bt_le_scan_param scan_param = {
    .type     = BT_LE_SCAN_TYPE_PASSIVE,
    .interval = 36,   /* 22.5 ms */
    .window   = 33,   /* 20.625 ms -- fails */
    /* .window = 32 -- 20.000 ms -- works */
    .timeout  = 0,
};
bt_le_scan_start(&scan_param, NULL);
/* concurrently, on discovering a target peripheral: */
bt_conn_le_create(peer_addr, &create_param, &conn_param, &conn);


Observed logs:

[00:03:31.362,559] <wrn> bt_hci_core: Connection creation timeout triggered
[00:04:19.219,706] <err> bt_att: ATT channel not connected
[00:07:29.333,660] <err> bt_att: ATT Timeout for device EA:82:E1:83:8D:B3 (random). Disconnecting...
[00:07:46.095,420] <err> bt_att: ATT channel not connected
[00:07:46.095,604] <err> bt_att: ATT channel not connected

This same scan/connect logic does not show the problem on our nRF52840-based boards  even at tighter ratios.

Question:

  1. What could cause scanning and connection-initiation to become unreliable when the idle time between scan windows drops from 2.5 ms to 1.875 ms on nRF54L15? Is there a scheduling constraint in the controller that this might be hitting?
  2. Is there a recommended minimum idle time (or minimum gap between scan window and scan interval) for reliable scanning and connection initiation on nRF54L15?
  3. Would the same idle-time constraint apply to nRF52/nRF53 devices  or is this specific to nRF54L15?

 

Parents
  • Hello,

    If you want to scan continuous, just set interval = window, if you also have some links active, you can set the interval=window to a smaller value to scan between active links.

    E.g. set window=interval=10.

    Kenneth

  • Thanks Kenneth,
    One follow-up for our own understanding: the same narrow-gap configuration (scan window ~1.875 ms short of the interval, i.e. window=33/interval=36 in 0.625 ms units) that fails on nRF54L15 works without issue on our nRF52840-based products, running the same scan/connect logic.

    Is there a specific architectural difference between the nRF52 Series and nRF54L Series  that would make the nRF54L15 more sensitive to a small idle gap between scan window and scan interval?

  • I don't have a reasonable explanation as to why that fails. Do you know what the startup time of the HFXO you have is configured as?

    Normally this is set in startup-time-us in hfxo in devicetree or overlay. Can it be that the actual startup time is longer than configured?

    Kenneth

  • Good question

    Our board's dts file doesn't set startup-time-us at all, so it inherits the default 1650 µs (0x672) from the nRF54L05/10/15 vendor dtsi. the same value used by the nRF54L15 DK. 

    build/app/zephyr/zephyr.dts

    /* node '/clocks' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:52 */
    	clocks {
    
    		/* node '/clocks/pclk' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:53 */
    		pclk: pclk {
    			compatible = "fixed-clock";     /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:54 */
    			#clock-cells = < 0x0 >;         /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:55 */
    			clock-frequency = < 0xf42400 >; /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:56 */
    			phandle = < 0x10 >;             /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:595 */
    		};
    
    		/* node '/clocks/lfxo' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:59 */
    		lfxo: lfxo {
    			compatible = "nordic,nrf54l-lfxo";        /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:60 */
    			#clock-cells = < 0x0 >;                   /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:61 */
    			clock-frequency = < 0x8000 >;             /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:62 */
    			load-capacitors = "internal";             /* in zephyr\boards\nordic\nrf54l15dk\nrf54l_05_10_15_cpuapp_common.dtsi:35 */
    			load-capacitance-femtofarad = < 0x4268 >; /* in zephyr\boards\nordic\nrf54l15dk\nrf54l_05_10_15_cpuapp_common.dtsi:36 */
    			phandle = < 0xf >;                        /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:595 */
    		};
    
    		/* node '/clocks/hfxo' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:65 */
    		hfxo: hfxo {
    			compatible = "nordic,nrf54l-hfxo";        /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:66 */
    			#clock-cells = < 0x0 >;                   /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:67 */
    			clock-frequency = < 0x1e84800 >;          /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:68 */
    			startup-time-us = < 0x672 >;              /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:69 */
    			load-capacitors = "internal";             /* in zephyr\boards\nordic\nrf54l15dk\nrf54l_05_10_15_cpuapp_common.dtsi:40 */
    			load-capacitance-femtofarad = < 0x3a98 >; /* in zephyr\boards\nordic\nrf54l15dk\nrf54l_05_10_15_cpuapp_common.dtsi:41 */
    			phandle = < 0x6 >;                        /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:242 */
    		};
    
    		/* node '/clocks/hfpll' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:72 */
    		hfpll: hfpll {
    			compatible = "fixed-clock";      /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:73 */
    			#clock-cells = < 0x0 >;          /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:74 */
    			clock-frequency = < 0x7a12000 >; /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:75 */
    			phandle = < 0x1 >;               /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:30 */
    		};
    	};



    device.dts

    &lfxo {
    	load-capacitors = "internal";
    	load-capacitance-femtofarad = <17000>;
    };
    
    &hfxo {
    	load-capacitors = "internal";
    	load-capacitance-femtofarad = <15000>;
    };

Reply
  • Good question

    Our board's dts file doesn't set startup-time-us at all, so it inherits the default 1650 µs (0x672) from the nRF54L05/10/15 vendor dtsi. the same value used by the nRF54L15 DK. 

    build/app/zephyr/zephyr.dts

    /* node '/clocks' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:52 */
    	clocks {
    
    		/* node '/clocks/pclk' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:53 */
    		pclk: pclk {
    			compatible = "fixed-clock";     /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:54 */
    			#clock-cells = < 0x0 >;         /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:55 */
    			clock-frequency = < 0xf42400 >; /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:56 */
    			phandle = < 0x10 >;             /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:595 */
    		};
    
    		/* node '/clocks/lfxo' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:59 */
    		lfxo: lfxo {
    			compatible = "nordic,nrf54l-lfxo";        /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:60 */
    			#clock-cells = < 0x0 >;                   /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:61 */
    			clock-frequency = < 0x8000 >;             /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:62 */
    			load-capacitors = "internal";             /* in zephyr\boards\nordic\nrf54l15dk\nrf54l_05_10_15_cpuapp_common.dtsi:35 */
    			load-capacitance-femtofarad = < 0x4268 >; /* in zephyr\boards\nordic\nrf54l15dk\nrf54l_05_10_15_cpuapp_common.dtsi:36 */
    			phandle = < 0xf >;                        /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:595 */
    		};
    
    		/* node '/clocks/hfxo' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:65 */
    		hfxo: hfxo {
    			compatible = "nordic,nrf54l-hfxo";        /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:66 */
    			#clock-cells = < 0x0 >;                   /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:67 */
    			clock-frequency = < 0x1e84800 >;          /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:68 */
    			startup-time-us = < 0x672 >;              /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:69 */
    			load-capacitors = "internal";             /* in zephyr\boards\nordic\nrf54l15dk\nrf54l_05_10_15_cpuapp_common.dtsi:40 */
    			load-capacitance-femtofarad = < 0x3a98 >; /* in zephyr\boards\nordic\nrf54l15dk\nrf54l_05_10_15_cpuapp_common.dtsi:41 */
    			phandle = < 0x6 >;                        /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:242 */
    		};
    
    		/* node '/clocks/hfpll' defined in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:72 */
    		hfpll: hfpll {
    			compatible = "fixed-clock";      /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:73 */
    			#clock-cells = < 0x0 >;          /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:74 */
    			clock-frequency = < 0x7a12000 >; /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:75 */
    			phandle = < 0x1 >;               /* in zephyr\dts\vendor\nordic\nrf54l_05_10_15.dtsi:30 */
    		};
    	};



    device.dts

    &lfxo {
    	load-capacitors = "internal";
    	load-capacitance-femtofarad = <17000>;
    };
    
    &hfxo {
    	load-capacitors = "internal";
    	load-capacitance-femtofarad = <15000>;
    };

Children
Related